Team Project 3: 3D morph and animation editor


Teams of 1 or 2 (you decide). But, if you are in a team of two, you should NOT split the work! Instead, you should design and code together.

Please keep track of the number of hours you spend on this project. Keep track of the total time (in hours) spent on
Please create a web page for your team, indicate the team members, even if there is only one person, create the categories for the time spent, and email me the url with in the subject line: "6491 Project 3" followed by the last names of the team members

Brown After

Brown Before


Gruetzmacher

Gruetzmacher


Gruetzmacher








Design, implement, debug, document, and demonstrate (through images (as shown above) and short, low-res animations the ability to compute and animate 3D morphs between triangle meshes.
Please use a white background for all images and keep the resolution below 600 horizontal x 200 vertical pixels.

Take as input two triangle-meshes, each representing a single manifold sheet as a Corner Table.
Let G1, V1, and O1 be the tables for mesh M1 and G2, V2, and O2 the tables for mesh M2.

As a preprocessing step, find out the minimax boxes around M1 and M2 and translate them so that the two boxes are in front of the viewer with a gap sufficient for a 3d box inbetween them. We will use that space to show the inbetween shape produced by morphing.  (Look at the image on the left in the above strip.)

In order to try and prevent singulat situations where an edge of M1 would be parallel to a triangle of M2, rotate M2 by a very small arbitrary amount around an arbitrary axis. You may look into a way of using OpenGL to do the rotation for you and get the rotated vertices of M2 back, but it may be simpler for you to program that rotation.

Your algorithm is to build a V table of corners of the new triangles for the morphing surface M and a G table whose entries each represent the motion of a vertex of M as an integer ID reference s to a vertex of M1 and a reference e to a vertex of M2.

Thus, for a given time t, vertex v of M will be computed as V1[v.s] + t(V2[v.e]-V1[v.s]). As time varies between 0 and 1, the vertex will be moving from a starting vertex of V1 to an ending vertex of V2 along a straight line.

To compute the V and G table, use the 3D morphing approch described in class and published in  (Pips.pdf) .

Basically, it matches each triangle t of M1 with each vertex v of the M2 whenever v happens to be a local maximum in the direction of the outward normal at t. When such a pair is matched, the 3 corners of t are appended to V and the corresponding entries for the moving vertices of M are entered into G. Each vertex will move along a striaight line between its initial position in M1 and v. To debug your program, show an image of the original shape on the left, of the final shape on the right, and of an intermediate shape for t=0.5 in the center, where you only show the triangles t for which you have found a matching vertex.

Show such an image for two different pairs of models. In each image, use a white background and use green triangles for M1 and blue triangles for M2. Use flat shading and a nice material property (something that looks like plastic).

In one, both M1 and M2 should be convex and simple. The morph image in the middle should show each triangle of M1 scaled down as it would be in its mid-course morph towards the mathed vertex of M2. Paint these triangles in green, so that we can later identify them as coming from triangles of M1.
These triangles will clearly not cover the entire mesh M, but this is the beginning.
In the second image, do the same thing, but use a simple convex shape for M1 and a non convex shape for M2. Keep M2 simple: we want simply to illustrate that some triangle of M1 will have more than one match.

Now, do the same, but inverting the role of M1 and M2. Hence, you are looking for matches between triangles of M2 and vertices of M1. Same criterion. Same insertion into V, but the insertion into G has s and e backwards so that at t=0, you start the motions from the vertex of M1 and at t=1 you end up haveing a full triangle of M2. Show the images for the two pairs of shapes used above. Preferably use the same view. Use the same colors as above. The new triangles in the middle should be painted blue to indicate that they are morphing into triangles of M2.
The middle shape should now have one or more instances of each triangle of M1 and of M2, but they should appear twice smaller. Although this mesh is still incomplete, you should be able to recognize a shape that is a compromise between M1 and M2.

Now, we are going to fill the gaps in the mesh produce above. To fill the gaps, match each edge of M1 with possibly several edges of M2. Two edges match if they correspond to local extrema in the direction of the cross-product of their tangent (you may need to try the two directions of that tangent). When the two edges match, they correspond to a parallelogram, which you should represent as 2 co-planar triangles. Append them to V and create the corresponding entries in G. Display the pairs of images described above again. Use the same colors as above. But this time, add the new edge-edge triangles and paint them red.

Please ensure that the triangles are oriented counterclockwise around that cross-product nornal N. Also, avoid generating the same parallelogram more than once. This would happen unless you take precautions. For instance, if you are using a double loop to visit all pairs of corners: a of A and on all corners b of B and then for each pair (a,b) you check that the opposite edges are "compatible", then you must not also do this for the other 3 pairs: (a.o,b), (a,b.o), or (a.o,b.o).
Also note that to ensure that two edges are compatible, you should compute the four bi-normal and check that their dot-products with N all have the same sign.
Given an outward pointing normal Ni to a triangle and a tangent Ti to the edge in question oriented counterclockwise around the triangle, the bi-normal Bi is NixTi.

In order to do animation more efficiently, you may want to create G1' anmd G2' tables for M1 and M2. Now, for each value of t, you would store (1-t)G1 into G1' and tG2 into G2'. Then, go through the V table and for each triangle, compute the location of its 3 vertices as an addition of coordinates from G1'[v.s] + G2'[v.e] and render.

To demonstrate that it all works, produce several images of morphs between differnt pairs of objects. Each image should contain 5 instances of the morph for t values in {0.00, 0.25, 0.50, 0.75, 1.00}. Use the same convention as above. Try it on a pair where both objects are not convex. You may want to spread M1 and M2 a bit more to leave room for the 3 intermediate shapes. (Look at the second image in the above strip.) Use one simple pair, one more complex pair, and one very complex pair. For each, in addition to the images, report statistics: Total time for the computation of the G and V tables. Number of triangles in M1, M2, and M.

Finally, write a loop that would animate the morph and capture an interesting animation as a low-resolution short video. Include it in your web site.

As usual, include the web site the title of the course and project, your name (your picture if you can), the images and videos discussed above, explanations of what your algorithm does, key pieces of code, and a link to the complete source code.

Note that we are using the O tables of M1 and M2 to access the neighbors and to do the matching tests. However, we need not create the O table for M. We could do so easily when M1 and M2 are convex and we would get a manifold mes. Explain why. Also discuss what would happen if we try to build the O table in situations where M1 and/or M2 are not convex.
The goal is to design an interactive motion editor.
Make a simple object that does not have symmetries, so that you can clearly see its orientation.
Design a user-interface that would allow you to rotate the object around its center and tanslate it in the desired direction.
Feel free to invent your own position editor. The goal is to make one that is effective and easy to use.  In particular, the user should not have to worry about where the axes and origins are and should instread be able to specify 3D rotations and 3D translations in user's coordinates. Use mouse clicks and drags if you can.

Now, let the user manipulate the shape with the GUI you have designed. When the shape is in an interesting pose. The user should be able to save that pose by pressing shift+F1, shift+F2,... or shift+F9. Then we can continue moving and rotating the object and save poses under other Fi keys.

Now, let the user jump to a saved pose by pressing F1, F2,... or F9.

These poses will be the control poses for your animation. Provide a simple way for the user to write to file a sequence of poses and then to read them back later. Use 4 vectors to describe a pose: the origin O, and the 3 unit basis vectors U, V, W.

Test your code and describe the details of your GUI on the web page. Comment on further extensions you may consider if you had the time.

Now, we want to provide smooth triansitions between two consecutive poses, say the ones stored in F3 and F4 for example. We will do so by using an interpolating screw, computed and animated as described in (Screw.pdf) and in other papers listed below.

Produce an image showing your object in 2 key poses (say F1 and F2). As before, please use white background and different colors for the object in these two poses (say green and blue). On the same image, display the screw axis and the lines joining O1 and O2 to their closest projection on the screw axis.

Then, in a second image with the same viewpoint, superimpose 5 instances of the moving object for t in {0.00, 0.25, 0.50, 0.75, 1.00}. Use a red color for the intermediate instances {0.25, 0.50, 0.75}. Pick some motion so that the projections on the screen of all 5 instances are disjoint.

Make a low-res animation showing the object animated doing a looping or some other cool motion with interpolating 9 key-poses. Make a picture with the 9 key-poses to go along the animation.
Now we want to make a simple amination editor by putting these two things together. The user should be able to add and delete 3D morphs to the animation. To add a morph, the user should be able to select two primitives from a precomputed set that you provide: sphere, block, cone, cylinder, chair.... Then, the user should be able to move the first primitive A where it should be at the beginning of the morph. Also, the user should be able to move the second primitive B to where it shold be at the end of the morph. These are specified using the GUI defined in phase B.

Finally, the user should be able to specify a motion M(t) of the morphing object. That motion is specified by specifying a motion of A using the motion editor of Phase B. We start with the starting position of A as key-frame 1 and insert more key-frames as desired. M(t) will interpolate them using evenly distributed time intervals in [0..1]. The morph should be computed between A transformed by M(1) and B. This way, you can manually align the two shapes so as to minimize the distortion that must be covered by the morph and instead using a rigid body motion.

Now, to animate the whole thing, you animate the morph and position it so that it travels between M(0) and M(1).
Produce several images with superimpsed instances of moving and deforming shapes and a video of the best animation you have produced. Try to do something interesting. Maybe morph between two pieces of furniture... or do an piece of animated modern art. Feel free to use colors and material properties as suited. Note that you may want to change them progressively during the morph.

In your write up, explain the user interface for your animation editor. Also discuss the difficulties you faced in this project and explain how you solved them. If you worked as a team, discuss whether this was beneficial to both and how much more (or less) time it would have taken each one of you to do the same thing individually.



Reading Material on the construction and animation of pose-interpolating srew motions
Reading Material on morphing