In this assignment you will get experience with some basic but important techniques used in physically-based modelling.
Update 30 April 2004: A lot of people made the same mistake in this assignment with respect to integrating the system; I have posted a note describing this problem and how to fix it.
/afs/cs/academic/class/15864-s04/turnin
.
Let me know if you don't have one.
One way to store an arbitrary implicit surface is on a grid. Here is some code which will read in an arbitrary implicit surface which is defined this way and do trilinear interpolation of the function values. It reads in two files, one which contains the distance values (which are of course scalars) and another which contains the normals. To use this representation, first construct it as follows:
SignedDistanceRepresentation collisionObject("originalHead.obj.dist", "originalHead.obj.grad");
You can then sample from this field by using the .distance
and .gradient
functions, each of which takes in a point in space and returns a scalar or a Vec3d
, respectively.
You should, however, verify that each sample is within the grid like so,
Vec3d point = ...; if( collisionObject.outside(point) ) { // too far away, no collision handling necessary } else { double dist = collisionObject.dist(point); // ... }
I have provided you with a simple sample shape, which is just the head you may recall from assignment 2. I will shortly also provide you with code you can use to generate your own signed-distance implicit surfaces out of closed polymeshes (Update: see below). Since I don't know where your cloth is located in space, you may want to relocate and perhaps resize the example shape (and others you work with) so that your cloth interacts with it in a reasonable way. To transform the grid, it is sufficient to merely apply the inverse transform to your point before sampling,
Mat3d objectTransform = ...; // ... double dist = collisionObject.dist( inv(objectTransform) * point );
However, be careful. Remember that if you perform any sort of rotation/scaling, you will need to transform your normals back into the global frame and renormalize; also remember that vectors transform differently from points.
You should also render the boundary (i.e. polygon mesh) representation of your implicit surface collision object in the scene for your own visualization purposes and so that we can see what is going on while we are doing grading. To this end, I have included the .obj version of the sample head implicit surface; you should turn in both the mesh and the implicit surface representations of any collision objects you create yourself.
One additional note; in the slides I mention that the collision force should be along the direction of the field gradient. You should apply the repulsion force a reasonable distance from the surface so that the cloth never penetrates the 0 level set of the implicit surface (this is dependent somewhat on the lengths of your triangle edges), and make it directly proportional to the depth of penetration beyond this distance.
I have slightly modified Sean Mauch's
Closest
Point Transform code to add a couple of useful
pieces of header information (about the bounding box, etc.).
These are the files that the code I provide above takes as
input. You can generate your own implicit surfaces out
of arbitrary closed polygon meshes using the binary that I
placed in the class directory. This will only work on
Linux; I have never gotten it to build under Windows (or
indeed using any compiler other than gcc).
First, you need to add
the appropriate directories to your PATH
and LD_LIBRARY_PATH
environment variables,
setenv PATH /afs/cs/academic/class/15864-s04/bin:$PATH setenv LD_LIBRARY_PATH /afs/cs/academic/class/15864-s04/lib:$LD_LIBRARY_PATH
Now, generate .geom
and .brep
files from the .obj
file (these are CPT's inputs).
objToDat originalHead.obj
Finally, use the CPT tool to generate the appropriate
.grad
and .dist
files,
Note that while this particular implementation of the closest point transform is provably asymptotically faster than other proposed methods, because it is a purely computational geometry formulation it relies very heavily on the mesh being closed, with no gaps. Otherwise it will give lots of unpleasant errors, generate an invalid distance field, and potentially crash. You should see at least the following output,cpt -b -g -o originalHead.obj originalHead.obj.geom originalHead.obj.brep
The surface is closed. Checking the grid...The grid is valid. Writing the distance...done. Writing the: gradient of the distance...done.
All my warnings about using random ill-behaved meshes from the web go over double here, so be careful! Note also that this part is not required for the assignment, you are welcome to use my example surface if you wish.
/afs/cs/academic/class/15864-s04/
so you don't have to
build it yourself.Questions? Contact Christopher Twigg.