Verlet

Verlet Integration is a scheme commonly used in GAMING and MOLECULAR DYNAMICS. Whereas Euler (pronouned "oiler") Integration is a function of velocity and time, Verlet Integration ignores velocity (or rather, determines it based on distance travelled) and focusses on ACCELERATION. At its core is the TIMESTEP, and there are many ideas about how best to implement it. Ultimately, the best way seems to be to separate the PHYSICS from the GRAPHICS CARD REFRESH RATE. I have not done this . . . yet, and it is why you see flickering. One solution would be fill up a TIME BUFFER and then let the TIMESTEP drain it. Any REMAINDER could then be used as a PERCENTAGE for alpha-blending between frames. Pretty crazy.

Vector3f

A Vector3f holds three floating point values. Really, in OpenGL, they should hold GLFloats for cross-compatibility. I haven't implemented it this way though. Here are some basic things you can do with vector3f (the 3f is just so you know it is made up of floating point numbers, and also to distinguish it from the c++ "vector"): 1 - You can add them together to make another vector3f: 2 - You can find out the distance between two of them. 3 - You can find an floating point representaion of the angle between them. 4 - You can "normalize" them (later on look into "normals" and "versors") so that their length is exactly 1. 5 - You can "cross" them to get an another vector. 5 - Let's see, you can also scale them up or down. Mostly what this program does is scale them up and down, add them together, and calculate distances between them. There is some crossing going on, but only to move the camera view around. You can learn more about vectors and matrix transformations, I'm sure of it.

Basic Structure

A common way to build an environment is with a SCENE class that has an ARRAY of OBJECTS. Really, its an ARRAY of POINTERS with VIRTUAL VOID functions that specify OBJECT functions. And even more REALLY, in this case, they are not OBJECTS at all but PARTICLE SYSTEMS. What's in this Particle System? Well, a bunch of VECTOR3Fs that are controlled by VERLET INTEGRATION. Here's are some PROTECTED elements of the PARTICLESYSTEM class:
Constraint *constraints;
Vector3f *cur_pos; //an ARRAY of VECTOR3f that represent current positions;
Vector3f *old_pos; //an ARRAY of VECTOR3f that represent old positions;
Vector3f *acc; //an ARRAY of VECTOR3f that represent Force accumulations;
Vector3f gravity; //a VECTOR3f representing "gravity", really just a force in x,y,z directions;
float timestep;
The CONSTRAINTS array at the top will hold all the RULES that we will need to SATISFY. These rules could be anything -- in this case, I use the constraints to make nodes on my fabric STAY CLOSE -- they are DISTANCE CONTRAINTS. The way VERLET works is you ADD up all the VECTOR3f forces, which in this case is just {0.0,-.02,0.0} for gravity, then you figure out HOW FAR the PARTICLES (each one is a Vector3f) WANT to go, and finally you send them back a little bit based on the CONSTRAINTS. So here are some more functions in the PARTICLESYSTEM class:
void AccumulateForces(); //allow for Forces to add up
void Verlet(); //non-euler integration
void SatisfyConstraints(); //all sorts of constraints can be satisfied -- here I just satisfy length
void PinVertices(); //staple certain vertices in place
All the above functions are thrown into another function called TimeStep(), and TimeStep is called for every Particle System (i.e., for every piece of fabric). PinVertices() happens last, to make sure that the top two corners of the fabric stay in place. Indeed, these "pinned" vertices are the ones that are animated by the audio. All the other vertices just "integrate" along with the timestep. We also try to keep some constants available like:
int num_particles;
int num_constraints;
There is also a CLOTH class which INHERITS from the PARTICLESYSTEM CLASS and has a couple of members worth mentioning, specifically:
UV *map; POLY *faces;
That's an ARRAY of POLYs called "faces," and an ARRAY of UVs called "map". See, back in the Vector3f class I also defined these structs:
struct POLY {
int a, b, c, d;
};
struct UV {
float u, v; };
Basically, the DRAW function of the CLOTH CLASS is done PER FACE, NOT PER VERTEX. This is actually an important concept that I only recently learned. Each FACE of the CLOTH is a POLY with FOUR integer values (a, b, c, and d) which correspond to VERTEX numbers. Remember in our ParticleSystem class, we have an array of three-dimensional points:
Vector3f *cur_pos;
Well, the INTEGER numbers in POLY[myFaceNumber].a (.b, .c, .d) refer to INDEX numbers in the cur_pos ARRAY. As a result, you'll start to see a lot of this to DRAW your information:
for (int i = 0; i (lessthansymbol) num_faces; ++i){
glTexCoord2f(map[ faces[i].a ].u, map[ faces[i].a ].v);
glVertex3f(cur_pos[ faces[i].a ].x, cur_pos[ faces[i].a ].y, cur_pos[ faces[i].a ].z);
glTexCoord2f(map[ faces[i].b ].u, map[ faces[i].b ].v);
glVertex3f(cur_pos[ faces[i].b ].x, cur_pos[ faces[i].b ].y, cur_pos[ faces[i].b ].z);
glTexCoord2f(map[ faces[i].c ].u, map[ faces[i].c ].v);
glVertex3f(cur_pos[ faces[i].c ].x, cur_pos[ faces[i].c ].y, cur_pos[ faces[i].c ].z);
glTexCoord2f(map[ faces[i].d ].u, map[ faces[i].d ].v);
glVertex3f(cur_pos[ faces[i].d ].x, cur_pos[ faces[i].d ].y, cur_pos[ faces[i].d ].z);
}
That's about it for the CLOTH CLASS. Now, the SCENE CLASS (where it all began, and where it all ends) has these important members:

vector vecObj; /* A VECTOR of POINTERS to PARTICLESYSTEMS!*/
vector vecTex;
int activeObject;
int activeTexture;
Okay, the VECTOR of POINTERS to PARTICLESYSTEMS is so that I can write vecObj.push_back() whenever I add a cloth at runtime. activeObject and activeTexture I change by hitting keys on the keyboard. This helps in swapping texture maps, etc. Ah, yes there is also a Texture class. I'll get to that next time. In the meantime, check out SPACESIMULATOR.NET.