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:
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.
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.
