OpenGL rotation, translation, projection matrices

I’ve finally written my next progression program and generated a cube.

If you simply drew this cube, you would only see the front part of the cube and nothing else. To get some 3D effect, I had to rotate the cube, then translate it out into the world and projected it into our screen. I used Jamie King’s 3D Computer Graphics Using OpenGL tutorial to create this program.

I’ve used following glm math functions to generate the full transformation Matrix:

  • glm::perspective: The first parameter describes the field of view angle. It describes the angle the viewer can see. The second parameter is the aspect ratio and is the ratio between the screen width and screen height. The third and forth parameter describe the near and far clipping plane. Those two values need to be positive and near < far. These two values describe the area the camera can see. The resulting matrix is the projection matrix.
  • glm::translate: The first parameter is the projection matrix generated before. The second on requires a vector which contains the coordinates the object has to move to. E.g., if you take following vector glm::vec3(2.0f, 1.0f, -2.0f), you tell the function to move the object 2 points along the positive x axis, 1 point along the positive y axis, and 2 points along the negative z axis. The point to remember here is that we look into the negative z axis. For some reason, this changes as soon as we are in the projection matrix (we look into the positive z axis). The resulting matrix is the projection translation matrix.
  • glm::rotate: The first parameter is the projection translation matrix that has been generated before. The second one requires the degree by which the object needs to be rotated. The rotation uses the right hand rule. The third parameter requires a vector. If you want the rotation to be along the x axis, the vector would be glm::vec3(1.0f, .0f, .0f). Along the y axis, you need the vector to be glm::vec3(0f, 1.0f, .0f) and along the z axis glm::vec3(.0f, .0f, 1.0f). This function is fairly straight forward and easy to use.

Additionally, this program also uses a uniform matrix shader variable which can be written to by using the two OpenGL functions glGetUniformLocation and glUniformMatrix4fv. That’s the first program, that’s actually a bit exciting and already gives a lot of room for playing and experimenting. The code can as always be found in github.

Last but not least, the code generates two programs. One uses MFC (as before) as window creation/input wrapper and the other one uses freeglut. You can compile both by using NMAKE.

My passion for C++

Not too long ago, I was asked why I liked C++ more than other programming languages. I honestly couldn’t come up with a good answer. In hindsight, there is no specific reason for it and I don’t think there has to be. I love the color brown. Why? I don’t know, I just do.

I’ve done a bit of Java programming in the past and even less in C# (during a university course, that’s it). I could just never really get into those languages. I guess I missed what so many developers hate: the pointer. I like being able to mess around with pointers (maybe that’s because I was embedded systems programmer for years) and I do enjoy the speed advantage C++ gives. Do I think C++ is superior over others, such as Java and Ruby? Nope, not at all. Every language has it’s pros and cons. If you need performance, you’ll likely need C++ and possibly also OpenMP/MPI/Cuda/etc. But let’s face it, 95% (if not even more) of programs don’t need to be super fast. And C++ has the big drawback that it is not very safe due to the pointers.

I think, my passion for C++ became even stronger with the release of the C++11 standard. It truly improved the language by a lot and introduced many cool features (for an overview, have a look at the Wiki page). A bit over a year ago, C++14 was released and honestly, I couldn’t wait for Visual Studio 2015 to support this release (with a few exceptions).

Developers often argue which language is the best, but at the end, the choice of language depends on many factors. Which programming language are the developers in the company most familiar with, what kind of application has to be developed, which platforms does it have to run on, how big will it be, etc. As developer, I think it is important to be open to new languages and to know a few, but it is just natural that we all favor one language over the other, whatever the reason for that may be.

There are other programming languages I do enjoy using as well. I’m currently learning ELisp and I definitely like it quite a bit. I’ve little experience in Ruby, but would love to properly learn it soon, since I love looking at Ruby code. Lately, I also use Javascript and PHP as well as HTML5 and CSS3. Therefore, my programming world doesn’t just consist of C++, but so far (and who knows, that might change one day) it is my programming language of choice.

Cooking: Getting organized

I prefer staying at home and eating a homemade meal than going out and spending money for a meal I might not even enjoy that much. This attitude might have to do that I’m an introvert, but I also prefer knowing what’s in the food I’m eating (therefore, I’m not the biggest fan of ordering in either). Especially since I have my little sweetheart, I’m way more concerned about healthy nutrition than I was before.

Currently, I fall back to quick and boring suppers way too often due to a few reasons:

  1. There are days, were I just simply don’t feel like cooking.
  2. My little one tends to be very clingy later in the afternoon and as soon as I step into the kitchen, he wants me to pick him up (also because he wants to watch me cooking).
  3. Although cooking is generally cheaper than going out, it can get quite expensive if you choose organic ingredients. Therefore, it’s best to look weekly at the local flyers, buy groceries that are on a good sale and then plan recipes that use those ingredients. Also, stocking up on items while they are on sale is a good idea (as long as they have a due date far in the future of course).

I’ve struggled with the above-mentioned hurdles for quite a while now. It’s time I tackle them finally.

Overcome ‘I’m too tired/lazy’

  • Plan meals ahead (at least a week in advance).
  • Write down recipes (it’s ingredients and maybe just a link to a site) that I like and some that I would like to try in the future.
  • Plan for 5 to 6 quick meals and only one or two more labor intense suppers.
  • Create the list of recipes via org-mode in emacs. Save the files in my gdrive so that I can access it on my phone.
  • Write an elisp script that copies ingredient lists into the ‘grocery shopping’ list via a key-press.
  • Write a script that organizes the weekly grocery shopping list by combining groceries and sorting them by store aisles.
  • Have a few quick meals (such as fish and chips) in the freezer for days where I’m truly lacking time for cooking or just really badly lazy.
  • Manage cooking with my little one

  • Find recipes that don’t require a lot of cutting.
  • Ask my hubby more often for help.
  • Prepare food already on the weekend while my husband and the little one are busy playing.
  • Keep the pantry full and organized

  • Create a list with all pantry items (name and amount) and it’s due date.
  • Create an emacs extension which will automatically search for recipes that use soon to be due pantry items.
  • Keep it cheap

  • Start searching every week for groceries that are on sale and create the meal plan accordingly.
  • Write an elisp script that takes as input groceries (that are on sale that week) and as output all kind of recipes that use those groceries.
  • Elisp code

    So far I have only one little function implemented which helps me copy an ingredients list in org-mode into my grocery.org file.
    An example ingredient list looks like:

    |   2 | small | shallots                 | minced      |
    |   1 |       | garlic clove             | minced      |
    |   2 | tsp   | Dijon mustard            |             |
    | 1/4 | cup   | balsamic vinegar         |             |
    |     |       | salt and pepper to taste |             |
    | 1/2 | cup   | olive oil                |             |
    

    If I have the pointer at the start of the table and call my elisp function, then it automatically puts the first three columns of my table in the kill ring. Afterwards, I just need to yank it into my grocery file and create a macro so that moving ingredient lists into my grocery list goes even faster. Below is my short unspectacular code.

    (defun custom/save-till-end-of-table()
      (interactive)
      (setq cont t)
      (setq startpoint (point))
      (while cont
        (next-line)
        (if (not(char-equal ?| (char-after)))
    	(progn
    	  (backward-char)
    	  (setq cont nil))))
      (org-shifttab)
      (backward-char 2)
      (kill-ring-save startpoint (point))
      (message (string (char-after))))

    My goal is to improve this code still so that it automatically yanks the table into a user-specified file.

    Aurebesh typing test for emacs

    This entry is part 3 of 3 in the series Aurebesh

    A few weeks ago, I posted the Aurebesh typing test. Since I’ve recently started learning elisp, I figured that I should implement the typing test as a feature for emacs.

    The code below is terrible with bugs and problems, but heck, it’s my first elisp program after all. My goal is to improve the version over time and to add features such as logging results in a separate file and displaying a progress statistic. To use it, you’ll need to first install the Aurebesh font.

    (setq correct 0)
    (setq wrong 0)
    (setq seconds-left 60)
    (setq test-start t)
    
    (require 'widget)
    
    (defun aurebesh-typing-test ()
      "Aurebesh typing test"
      (interactive)
      (get-buffer-create "*Aurebesh typing test*")
      (custom/reset-aurebesh-typing-test-vars)
      (custom/aurebesh-typing-test))
    
    (defun custom/reset-aurebesh-typing-test-vars()
      (setq test-start t)
      (setq correct 0)
      (setq wrong 0)
      (setq seconds-left 60))
    
    (defun custom/aurebesh-typing-test()
      (with-current-buffer "*Aurebesh typing test*"
        (custom/setup-buffer)
        (custom/refresh-seconds)
        (custom/create-line-with-widget)
        (insert "Correct / wrong answers: " (number-to-string correct) " / " (number-to-string wrong) " \n")
        (custom/setup-widget)
        (custom/set-aurebesh)))
    
    (defun custom/setup-buffer()
      (kill-all-local-variables)
      (let ((inhibit-read-only t))
        (erase-buffer))
      (remove-overlays))
    
    (defun custom/refresh-seconds()
      (with-no-warnings
        (goto-line 1)
        (custom/delete-line)
        (insert "Seconds: " (number-to-string seconds-left) "\n")))
    
    (defun custom/delete-line()
      (let ((beg (point)))
        (forward-line 1)
        (delete-region beg (point))))
    
    (defun custom/create-line-with-widget()
      (if (> seconds-left 0)
          (setq randomChar (custom/get-random-char))
        (setq randomChar ""))
      (widget-insert randomChar)
      (widget-insert "\t")
      (widget-create 'editable-field
    		 :size 15
    		 :correct (string randomChar)
    		 :notify 'custom/check-input-value)
      (widget-insert "\n"))
    
    (defun custom/setup-widget()
      (use-local-map widget-keymap)
      (widget-setup)
      (widget-forward 1))
    
    (defun custom/set-aurebesh()
      "Sets the aurebesh font in current buffer"
      (interactive)
      (setq buffer-face-mode-face '(:family "Aurebesh"))
      (buffer-face-mode))
    
    (defun custom/check-input-value(widget &rest ignore)
      "Compare aurebesh input character with requested one."
      (cond
       ((string-match 
         (widget-get widget :correct)
         (widget-value widget))
        (custom/correct-input widget))
       ((not(= (length (widget-value widget)) 0))
        (custom/wrong-input))))
    
    (defun custom/correct-input(widget)
      (if test-start
          (progn
    	(custom/start-timer)
    	(setq test-start nil)))
      (if (> seconds-left 0)
          (progn
    	(setq correct (+ correct 1))
    	(custom/next-character widget))))
    
    (defun custom/start-timer()
      "Start Aurebesh test"
      (setq seconds-left 60)
      (setq timer (run-with-timer 0 1 'custom/decrement-seconds)))
    
    (defun custom/decrement-seconds()
      (with-current-buffer "*Aurebesh typing test*"
        (if (> seconds-left 0)
    ;	(progn
    	  (setq seconds-left (- seconds-left 1))
    ;	  (custom/refresh-seconds)
    ;	  (widget-forward 1))
          (custom/stop-aurebesh-typing-test))))
    
    (defun custom/stop-aurebesh-typing-test()
      (with-current-buffer "*Aurebesh typing test*"
      (custom/refresh-seconds)
      (cancel-timer timer)
      (custom/set-arial)))
    
    (defun custom/set-arial()
       "Sets the arial font in current buffer"
       (interactive)
       (setq buffer-face-mode-face '(:family "Arial"))
       (buffer-face-mode))
    
    (defun custom/next-character(widget)
      (with-current-buffer "*Aurebesh typing test*"
        (custom/fill-random-character widget)
        (custom/fill-correct-wrong-answers)
        (custom/refresh-seconds)
        (widget-forward 1)
        ))
    
    (defun custom/fill-random-character(widget)
      (with-no-warnings
        (goto-line 2))
      (delete-char 1)
      (if (> seconds-left 0)
          (setq randomChar (custom/get-random-char))
        (setq randomChar ""))
      (widget-insert randomChar)
      (widget-put widget :correct (string randomChar))
      (widget-value-set widget ""))
    
    (defun custom/get-random-char ()
      "Insert a random alphanumeric character.."
      (let ((mycharset "abcdefghijklmnopqrstyvwxyz"))
        (elt mycharset (random (length mycharset)))))
    
    (defun custom/fill-correct-wrong-answers()
      (with-no-warnings
        (goto-line 3))
      (kill-line)
      (insert "Correct / wrong answers: " (number-to-string correct) " / " (number-to-string wrong) " \n"))
      
    (defun custom/wrong-input()
      (message "%s" (widget-get widget :correct))
      (widget-value-set widget "")
      (setq wrong (+ wrong 1)))
    

    OpenGL glMapBuffer/glMapBufferRange

    This entry is part 4 of 4 in the series Learning OpenGL

    I’ve changed the last program a bit to use glMapBufferRange instead of glBufferSubData. For this specific example, there isn’t really any advantage in using glMapBufferRange over glBufferSubData, but in general, it has better performance than glBufferSubData.

    I was actually going to change a bit more code, but I wasted quite a bit of time for a new laptop (from Santa) which turned out to have hardware issues (50% of laptops I’ve owned so far had defects when I got them – what a jinx I am).

    You can find my latest OpenGL program as always on github.

    Why glMapBuffer/glMapBufferRange?

    The problem with glBufferData as well as with glBufferSubData is that you need to allocate some memory provided by your application before you can copy it to memory owned by OpenGL. Let’s assume you have a file with all vertex data. Wouldn’t it be nice to directly read that file into OpenGL memory? That’s exactly what glMapBuffer and glMapBufferRange is good for. You avoid wasting memory and copying operations. If you compare my code in ‘OpenGL – Beginner 4’ and ‘OpenGL – Beginner 5’, you’ll find that the usage of glMapBufferRange and glBufferSubData is very similar.

    I suggest reading OpenGL’s wiki about mapping for a detailed explanation.