skeletal animation...the next step
ok i tweaked the MeshworkImporter code so it loads bones, and stores a list of vertices attached to each bone. the setup is...
a bone structure
[sourcecode]
typedef struct
{
const char *parentBone,*primaryBoneCode,*secondaryBoneCode;
float bone_x,bone_y,bone_z;
float bone_rx,bone_ry,bone_rz;
float def_bone_x,def_bone_y,def_bone_z;
float def_bone_rx,def_bone_ry,def_bone_rz;
int attached_vertices[2000];
int vertex_count;
} bone;
[/sourcecode]
a materials structure (as in MeshworkImporter)
[sourcecode]
struct {
float color[4];
BOOL smoothed;
int mapping;
int axis;
float center[3];
float extent[3];
unsigned numTriangles;
float *normals;
unsigned short *triangles;
float *texCoords;
} materials[8];
[/sourcecode]
an array for bones
[sourcecode]
bone *modelBone;
[/sourcecode]
an array vertices, an array for normals (as in MeshworkImporter)
[sourcecode]
float *vertices;
float *normals;
[/sourcecode]
the attached_vertices array in the bone struct contains the index of each vertex in the vertices array that is connected to the bone.
this is the only way i can think of drawing the model using its bones:
trueBones is the number of bones in the model
[sourcecode]
for(i=0;i<trueBones;i++)
{
glPointSize(3.0);
glBegin(GL_POINTS);
glColor3f(1.0,0.0,0.0);
glVertex3f(modelBone[i].bone_x,modelBone[i].bone_y,modelBone[i].bone_z);
glEnd();
glBegin(GL_TRIANGLES);
glColor3f(0.0,1.0,0.5);
for(a=0;a<modelBone[i].vertex_count;a++)
{
glVertex3f(vertices[modelBone[i].attached_vertices[a]*3], vertices[modelBone[i].attached_vertices[a]*3+1], vertices[modelBone[i].attached_vertices[a]*3+2]);
}
glEnd();
}
[/sourcecode]
now this would draw all the vertices, as it should, but the result is not as it should be (as should happen). i noticed that MeshworkImporter doesnt make use of the EDGES section of the Meshwork file format (or does it?), so i was thinking that this is probably my problem. my first question would be: does using glVertexPointer() automatically determine edges? if so, can this be applied to skeletal modeling? thanks.
a bone structure
[sourcecode]
typedef struct
{
const char *parentBone,*primaryBoneCode,*secondaryBoneCode;
float bone_x,bone_y,bone_z;
float bone_rx,bone_ry,bone_rz;
float def_bone_x,def_bone_y,def_bone_z;
float def_bone_rx,def_bone_ry,def_bone_rz;
int attached_vertices[2000];
int vertex_count;
} bone;
[/sourcecode]
a materials structure (as in MeshworkImporter)
[sourcecode]
struct {
float color[4];
BOOL smoothed;
int mapping;
int axis;
float center[3];
float extent[3];
unsigned numTriangles;
float *normals;
unsigned short *triangles;
float *texCoords;
} materials[8];
[/sourcecode]
an array for bones
[sourcecode]
bone *modelBone;
[/sourcecode]
an array vertices, an array for normals (as in MeshworkImporter)
[sourcecode]
float *vertices;
float *normals;
[/sourcecode]
the attached_vertices array in the bone struct contains the index of each vertex in the vertices array that is connected to the bone.
this is the only way i can think of drawing the model using its bones:
trueBones is the number of bones in the model
[sourcecode]
for(i=0;i<trueBones;i++)
{
glPointSize(3.0);
glBegin(GL_POINTS);
glColor3f(1.0,0.0,0.0);
glVertex3f(modelBone[i].bone_x,modelBone[i].bone_y,modelBone[i].bone_z);
glEnd();
glBegin(GL_TRIANGLES);
glColor3f(0.0,1.0,0.5);
for(a=0;a<modelBone[i].vertex_count;a++)
{
glVertex3f(vertices[modelBone[i].attached_vertices[a]*3], vertices[modelBone[i].attached_vertices[a]*3+1], vertices[modelBone[i].attached_vertices[a]*3+2]);
}
glEnd();
}
[/sourcecode]
now this would draw all the vertices, as it should, but the result is not as it should be (as should happen). i noticed that MeshworkImporter doesnt make use of the EDGES section of the Meshwork file format (or does it?), so i was thinking that this is probably my problem. my first question would be: does using glVertexPointer() automatically determine edges? if so, can this be applied to skeletal modeling? thanks.
No, vertexpointer does not do edge detection. There is, in general, no way to automatically do meshworkstyle softskin skeletal animation in GL.
Meshwork specifies bones by vertex, so you'll have to transform all the vertices to their posed location and then draw the triangles. I'm doing this "manually" with GL feedback mode, but you could also do your own matrix math.
Meshwork specifies bones by vertex, so you'll have to transform all the vertices to their posed location and then draw the triangles. I'm doing this "manually" with GL feedback mode, but you could also do your own matrix math.
after thinking about it for a while, i think i came up with a solution.
i have an array of all the vertices in the model
(index0=x1,index1=y1,index2=z1,index3=x2,index4=y2,etc..)
i have an array of all the edges in the model
(index0=a1,index1=b1,index2=a2,etc..)
each item is the index # of the edge vertex
i have an array of all the bones in the model
now i want to draw the model. if i scan through the edges array, would this work?
[sourcecode]
for(every other item in edges array [+=2])
{
1)find bone that edge vertex A is connected to
2)find bone that edge vertex B is connected to
3)save matrix
4)translate to the bone position that vertex A is connected to
5)rotate to the bone orientation that vertex A is connected to
6)draw vertex A
7)restore matrix
8)repeat steps 37 for vertex B
}
[/sourcecode]
it seems like it would, but i wanted to get a 2nd opinion before i start changing things. thanks for your help.
i have an array of all the vertices in the model
(index0=x1,index1=y1,index2=z1,index3=x2,index4=y2,etc..)
i have an array of all the edges in the model
(index0=a1,index1=b1,index2=a2,etc..)
each item is the index # of the edge vertex
i have an array of all the bones in the model
now i want to draw the model. if i scan through the edges array, would this work?
[sourcecode]
for(every other item in edges array [+=2])
{
1)find bone that edge vertex A is connected to
2)find bone that edge vertex B is connected to
3)save matrix
4)translate to the bone position that vertex A is connected to
5)rotate to the bone orientation that vertex A is connected to
6)draw vertex A
7)restore matrix
8)repeat steps 37 for vertex B
}
[/sourcecode]
it seems like it would, but i wanted to get a 2nd opinion before i start changing things. thanks for your help.
It may or may not work, but it'll be dogslow
Unfortunately, ARB_matrix_palette doesn't seem to be available on Mac OS X (though ARB_vertex_blend is?!?!), so the easy way's down the drain
In the absence of ARB_matrix_palette, you could write a vertex program, or transform all your vertices on the CPU:
For each bone:
figure out the transform matrix
For each vertex:
multiply by the matrix for bone 1 to get v1
multiply by the matrix for bone 2 to get v2
linearly interpolate v1 & v2 by the bone weights to get the final vertex
Use a vertex array to submit the vertices to the card
Unfortunately, ARB_matrix_palette doesn't seem to be available on Mac OS X (though ARB_vertex_blend is?!?!), so the easy way's down the drain
In the absence of ARB_matrix_palette, you could write a vertex program, or transform all your vertices on the CPU:
For each bone:
figure out the transform matrix
For each vertex:
multiply by the matrix for bone 1 to get v1
multiply by the matrix for bone 2 to get v2
linearly interpolate v1 & v2 by the bone weights to get the final vertex
Use a vertex array to submit the vertices to the card
i have a working bone model setup made, now i just need to figure out how to properly draw everything. heres what im working with:
[sourcecode]
typedef struct
{
const char *parentBoneCode,*primaryBoneCode,*secondaryBoneCode;
int parentBone,primaryBone,secondaryBone;
float bone_x,bone_y,bone_z;
float [b/]bone_rx,bone_ry,bone_rz[/b];
float def_bone_x,def_bone_y,def_bone_z;
float def_bone_rx,def_bone_ry,def_bone_rz;
unsigned short triangles_buf[2000];
int triangle_count;
} model_bone;
[/sourcecode]
parentBone is the index number of the bone's parent (in the mbone_buffer[] array, below)
bone_x... is the bone's xyz position
bone_rx... is the bone's xaxis, yaxis, zaxis orientation
triangles_buf[] is the geometry array of the bone
every 3 items is a triangle. every item is a index number of a vertex in the model_vertices or vrtb arrays (below).
[sourcecode]
@interface Model : NSObject
{
float *model_vertices;
float *vrtb;
model_bone mbone_buffer[1000];
int model_bone_count;
}
[/sourcecode]
model_vertices is the default vertex array (coordinates are as they are in the Meshwork model file). every 3 items is a vertex.
vrtb is the vertex relative to bone array. it is the same setup as the model_vertices, except each vertex is converted to its position relative to the (default) position of the bone that the vertex is connected to (vertex_x  bone_x, vertex_y  bone_y, ...).
now my problem is stepping through the bones logically. i basically need to go through each bone, and translate/rotate based on bone position and orientation, and bone parent position and orientation, then draw the geometry for the bone. here is what im trying:
[sourcecode]
(void)displayMeshworkFigure
{
int index,index2;
unsigned short *current_triangle,*current_triangles;
current_triangle = (unsigned short *)malloc(1 * sizeof(unsigned short) * 3);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vrtb);
//go through bones, and display its geometry
for(index=0;index<model_bone_count;index++)
{
current_triangles = (unsigned short *)malloc(mbone_buffer[index].triangle_count * sizeof(unsigned short) * 3);
//go through each triangle in the bones geometry, and add it to current triangles array (note: im aware that this shouldnt be done for each frame, but this is just a development thing)
for(index2=0;index2<mbone_buffer[index].triangle_count;index2++)
{
current_triangle[0] = mbone_buffer[index].triangles_buf[index2*3+0]; //x
current_triangle[1] = mbone_buffer[index].triangles_buf[index2*3+1]; //y
current_triangle[2] = mbone_buffer[index].triangles_buf[index2*3+2]; //z
current_triangles[index2*3+0] = current_triangle[0];
current_triangles[index2*3+1] = current_triangle[1];
current_triangles[index2*3+2] = current_triangle[2];
}
glPushMatrix();
//transform to parent bone
//(this will only allow bones to be linked to 1 other
//bone, the rest will be implemented once i figure this out)
if(mbone_buffer[index].parentBone!=1)
{
glRotatef(mbone_buffer[mbone_buffer[index].parentBone].bone_rx,1.0,0.0,0.0);
glRotatef(mbone_buffer[mbone_buffer[index].parentBone].bone_ry,0.0,1.0,0.0);
glRotatef(mbone_buffer[mbone_buffer[index].parentBone].bone_rz,0.0,0.0,1.0);
glTranslatef(mbone_buffer[mbone_buffer[index].parentBone].bone_x,mbone_buffer[mbone_buffer[index].parentBone].bone_y,mbone_buffer[mbone_buffer[index].parentBone].bone_z);
}
//transform to bone
glRotatef(mbone_buffer[index].bone_rx,1.0,0.0,0.0);
glRotatef(mbone_buffer[index].bone_ry,0.0,1.0,0.0);
glRotatef(mbone_buffer[index].bone_rz,0.0,0.0,1.0);
glTranslatef(mbone_buffer[index].bone_x,mbone_buffer[index].bone_y,mbone_buffer[index].bone_z);
//draw triangles
glDrawElements(GL_TRIANGLES, mbone_buffer[index].triangle_count*3, GL_UNSIGNED_SHORT, current_triangles);
glPopMatrix();
}
}
[/sourcecode]
if i don't transform to parent bone, as shown above, then everything is drawn as it should be. if i add a spin to one of the bone's, its triangles spin independently of the other bones geometry. but if i do transform to parent bone, the bone geometry is rotated properly, but its position is off. ive tried translating before rotating, transforming to bone parent after transforming to bone, etc, to no avail. any ideas? thanks.
p.s.
i tried implementing this using the setup on http://www.gamedev.net/reference/article...le1267.asp but i still cant get it quite right. its a step closer but theres still something im not getting.
[sourcecode]
typedef struct
{
const char *parentBoneCode,*primaryBoneCode,*secondaryBoneCode;
int parentBone,primaryBone,secondaryBone;
float bone_x,bone_y,bone_z;
float [b/]bone_rx,bone_ry,bone_rz[/b];
float def_bone_x,def_bone_y,def_bone_z;
float def_bone_rx,def_bone_ry,def_bone_rz;
unsigned short triangles_buf[2000];
int triangle_count;
} model_bone;
[/sourcecode]
parentBone is the index number of the bone's parent (in the mbone_buffer[] array, below)
bone_x... is the bone's xyz position
bone_rx... is the bone's xaxis, yaxis, zaxis orientation
triangles_buf[] is the geometry array of the bone
every 3 items is a triangle. every item is a index number of a vertex in the model_vertices or vrtb arrays (below).
[sourcecode]
@interface Model : NSObject
{
float *model_vertices;
float *vrtb;
model_bone mbone_buffer[1000];
int model_bone_count;
}
[/sourcecode]
model_vertices is the default vertex array (coordinates are as they are in the Meshwork model file). every 3 items is a vertex.
vrtb is the vertex relative to bone array. it is the same setup as the model_vertices, except each vertex is converted to its position relative to the (default) position of the bone that the vertex is connected to (vertex_x  bone_x, vertex_y  bone_y, ...).
now my problem is stepping through the bones logically. i basically need to go through each bone, and translate/rotate based on bone position and orientation, and bone parent position and orientation, then draw the geometry for the bone. here is what im trying:
[sourcecode]
(void)displayMeshworkFigure
{
int index,index2;
unsigned short *current_triangle,*current_triangles;
current_triangle = (unsigned short *)malloc(1 * sizeof(unsigned short) * 3);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vrtb);
//go through bones, and display its geometry
for(index=0;index<model_bone_count;index++)
{
current_triangles = (unsigned short *)malloc(mbone_buffer[index].triangle_count * sizeof(unsigned short) * 3);
//go through each triangle in the bones geometry, and add it to current triangles array (note: im aware that this shouldnt be done for each frame, but this is just a development thing)
for(index2=0;index2<mbone_buffer[index].triangle_count;index2++)
{
current_triangle[0] = mbone_buffer[index].triangles_buf[index2*3+0]; //x
current_triangle[1] = mbone_buffer[index].triangles_buf[index2*3+1]; //y
current_triangle[2] = mbone_buffer[index].triangles_buf[index2*3+2]; //z
current_triangles[index2*3+0] = current_triangle[0];
current_triangles[index2*3+1] = current_triangle[1];
current_triangles[index2*3+2] = current_triangle[2];
}
glPushMatrix();
//transform to parent bone
//(this will only allow bones to be linked to 1 other
//bone, the rest will be implemented once i figure this out)
if(mbone_buffer[index].parentBone!=1)
{
glRotatef(mbone_buffer[mbone_buffer[index].parentBone].bone_rx,1.0,0.0,0.0);
glRotatef(mbone_buffer[mbone_buffer[index].parentBone].bone_ry,0.0,1.0,0.0);
glRotatef(mbone_buffer[mbone_buffer[index].parentBone].bone_rz,0.0,0.0,1.0);
glTranslatef(mbone_buffer[mbone_buffer[index].parentBone].bone_x,mbone_buffer[mbone_buffer[index].parentBone].bone_y,mbone_buffer[mbone_buffer[index].parentBone].bone_z);
}
//transform to bone
glRotatef(mbone_buffer[index].bone_rx,1.0,0.0,0.0);
glRotatef(mbone_buffer[index].bone_ry,0.0,1.0,0.0);
glRotatef(mbone_buffer[index].bone_rz,0.0,0.0,1.0);
glTranslatef(mbone_buffer[index].bone_x,mbone_buffer[index].bone_y,mbone_buffer[index].bone_z);
//draw triangles
glDrawElements(GL_TRIANGLES, mbone_buffer[index].triangle_count*3, GL_UNSIGNED_SHORT, current_triangles);
glPopMatrix();
}
}
[/sourcecode]
if i don't transform to parent bone, as shown above, then everything is drawn as it should be. if i add a spin to one of the bone's, its triangles spin independently of the other bones geometry. but if i do transform to parent bone, the bone geometry is rotated properly, but its position is off. ive tried translating before rotating, transforming to bone parent after transforming to bone, etc, to no avail. any ideas? thanks.
p.s.
i tried implementing this using the setup on http://www.gamedev.net/reference/article...le1267.asp but i still cant get it quite right. its a step closer but theres still something im not getting.
this is what i think i need:
now, i have everything implemented except for the 4*4 matrix. i was wondering if someone could explain to me how i would set up a 4*4 matrix based on the position and orienation of a bone, and then multiply the bonematrix by the modelview matrix (glMultMatrixf(bonematrix) i presume?). im really hoping this is it. thanks.
Quote:Each bone is a 4*4 matrix, a list of it's child bones and a list of polys attached to that bone. Then do this:
Load identity matrix
//the following recurses through all bones
*pushmatrix
*multiply bonematrix by modelview matrix
*draw vertices attached to this bone
*visit children and draw them
*popmatrix
The coordinates for the vertices are supposed to be relative to the boneorigin. The translation in each bone's 4*4 matrix is then the offset from the parent bone's origin to the current bone's origin.
now, i have everything implemented except for the 4*4 matrix. i was wondering if someone could explain to me how i would set up a 4*4 matrix based on the position and orienation of a bone, and then multiply the bonematrix by the modelview matrix (glMultMatrixf(bonematrix) i presume?). im really hoping this is it. thanks.
Possibly Related Threads...
Thread:  Author  Replies:  Views:  Last Post  
The Next Step?  kodex  4  3,398 
Nov 30, 2004 05:36 AM Last Post: TomorrowPlusX 

skeletal animation  honkFactory  15  6,513 
Feb 11, 2003 04:12 PM Last Post: David 