Shadows, animation and a small gui

In this assignment you will construct a GUI, do some animation and simulate some fake shadows.

You have a convex body in 3D. The surface may have been generated by commands such as ellipsoid and cylinder. The lab consists of writing a GUI that can be used to rotate the body. Start by looking at an mpeg-file showing what the animation may look like. Give the command  mplayer /chalmers/groups/thomas_math/VIS/data/body.mpeg (or double click on the file in the file manager) when logged in on the student system. Here is the file, body.mpeg (1.8 MiByte).
Here is a still image:

Shadows

The animation in Matlab is much smoother than what is shown in my mpeg-file. In fact, my Matlab-program produces an avi-file. The body should rotate around the centre of mass (or some other internal point that you have chosen). Using the gui one should be able to change the rotational axis. As you can see in the mpeg-file, the body casts shadows on the coordinate planes. The shadow on the x-y-plane should be constructed by projecting all the points, on the surface, orthogonally on the x-y-plane. This corresponds to having a very distant light source, placed on the z-axis, sending parallel rays on the body. The shadows on the x-z-plane and the y-z-plane are constructed similarly.

You may decide how to design the gui, but it should have the following functionality (at least):

Use a timer-object to control the animation.

There should be seven buttons named:
x
y
z
Quit
Start
Stop
Capture

There should be a menu called Figure having three choices: ellipsoid, cylinder and box.

You can have the buttons and menu in a separate window, or in the same as body.

When pressing Start, a figure-window should appear (unless you only have one window) in which an ellipsoid is rotating around the x-axis. There should be shadows, which are updated when the body is rotating. Pressing one of x, y or z should (instantly) make the body (in its present position) rotate around the chosen axis. The button, corresponding, the chosen axis should be highlighted (change colour).  The name of the present axis should be shown in the figure window as well (see the mpeg-file).

Pressing the Stop-button should freeze the rotation.
Pressing the Quit-button should close any open windows, belonging to the assignment. This should work even if the user has closed a window in some other way. Other figure-windows (not belonging to the assignment) should be left alone.

Using the menu one should be able to choose another surface. The ellipsoid should be the default. When pressing Start again the new surface should start to rotate.

When pressing the Capture-button, the program should collect frames (do not use up your disk quota). The button should be highlighted. Pressing Capture once again should reset the button's colour, and it should halt the collection of frames. The frames should be stored in an avi-file. To simplify the programming, you can use the same file name for storing the file. If you like, you can make a more fancy solution, where the user can choose the file name.

Hint: use the Matlab commands convhull and VideoWriter. Another hint: to get fast animation you need to use the graphics hardware. So, in the window where you are animating set the figure property 'Renderer' to 'opengl'. On some systems (but not ours) it may also help to set 'Doublebuffer' to 'On' (it is default). Don't forget the technique I mentioned in the lecture either (update the data directly in the object rather than issuing new plot-commands). Use a timer-object to control the animation.

Question Implement a gui according to the specification above. Your solution should not be too inefficient as we want a smooth animation.

Two notes on VideoWriter:
This is important: depending on how you write the code, you may get a so-called race condition (threads are "competing" with each other, and the outcome depends on which thread who wins the race). So, the VideoWriter object must have been created before you try to save a frame to it. A fair number of lab groups had problems with this in 2013. One way to fix it is like this. In your callback for the capture button write something like (this is pseudo code and it is not complete, so you need to add extra lines):

if start capturing
  stop(t)                  % stop animation timer
  vidObj = VideoWriter ... % create object
  open(vidObj)
  pause(1)                 % wait for this to complete, takes time
  start(t)                 % start timer again
else
  stop(t)
  close(vidObj)
  start(t)
end

This may not be a problem:
When you use the getframe-command to capture part of the figure window, some pieces may be missing. Test the example you can see at the end of  help VideoWriter . One way to fix that is to use the more general form of getframe where you can specify the size of the rectangle which should be captured. As it says in the documentation:

F = getframe(h) gets a frame from the figure or axes identified by handle h.

F = getframe(h,rect) specifies a rectangular area from which to copy the pixmap. rect is relative to the lower left corner of the figure or axes h, in pixel units. rect is a four-element vector in the form [left bottom width height], where width and height define the dimensions of the rectangle.

Back