Hi there!,
Thanks Dark Photon for the advice, but the engine must run on Linux / Mac / Windows, and right now is not a good idea to made some kind of “hacking” to improve the upload of the joints and weights to the Gpu, It seems that I really can made some kind of optimization under Linux, but I cannot made it work under Windows so… U_U no luck at the moment.
I’m trying to test what you said in the previous post, but neither the mat3( matTransform ) or the transpose( mat3( matTransform ) ) seems to work.
mat3 normaMat = gl_NormalMatrix * mat3(matTransform);
The implementation is based on the MD5 one, so no scales or shares are applied, so I really cannot understand why is not working properly…
Here is the code from CPU side to fill the VBO.
voidddeCL::ddeMeshBuild( ddeMesh *tempMesh )
{
/* Local variables */
Vertex *tempVert = NULL;
Weight *tempWeight = NULL;
Joint *tempJoint = NULL;
ddeFloat *currVBOPos = NULL;
ddeFloat *VBOCPU = NULL;
ddeMath::vec3 tan1 [tempMesh->numVerts];
ddeMath::vec3 tan2 [tempMesh->numVerts];
[u]vector[/u]<ddeMath::vec4> WeightBuffer;
[u]vector[/u]<ddeMath::vec4> BoneIndexBuffer;
if( tempMesh->isSkinned == false )
{
[u]printf[/u]( "Processing Mesh... %s
", tempMesh->meshName );
//We create a temporary array in order to copy all the meshes from the file to the VBOCPU Array,
//We don't need 64 bytes of information for each vertex, but this way we will made a perfect pre-fetching
//and no cache miss on GPU, so that's why we send dummy information
VBOCPU = ( ddeFloat* )[u]malloc[/u]( ( tempMesh->numVerts * 16 ) * sizeof( float ) );
for ( ddeIntj = 0, vboCpuIterator = 0; j < tempMesh->numVerts; j++, vboCpuIterator += 16 )
{
//Temp Variables for boneweight and index matrix
ddeMath::vec4 boneIndices = ddeMath::vec4(0);
ddeMath::vec4 boneWeights = ddeMath::vec4(0);
tempVert = &tempMesh->verts[j];
tempVert->pos.x = tempVert->pos.y = tempVert->pos.z = 0.0;
tempVert->n.x = tempVert->n.y = tempVert->n.z = 0.0;
for ( ddeInt k=0; k < tempVert->weightCount; k++ )
{
tempWeight = &tempMesh->weights[ tempVert->weightIndex + k ];
tempJoint = &tempMesh->joints [ tempWeight->joint ];
ddeMath::quat q;
ddeMath::vec3 result = tempJoint->quat * ddeMath::vec3( tempWeight->pos[0],
tempWeight->pos[1],
tempWeight->pos[2] );
tempVert->pos.x += ( tempJoint->pos[0] + result.x ) * tempWeight->w;
tempVert->pos.y += ( tempJoint->pos[1] + result.y ) * tempWeight->w;
tempVert->pos.z += ( tempJoint->pos[2] + result.z ) * tempWeight->w;
boneIndices[k] = ( float )tempWeight->joint;
boneWeights[k] = tempWeight->w;
} // for (weights)
// Copy the 3 new vertices to the temporary VBO
currVBOPos = &VBOCPU[vboCpuIterator];
currVBOPos[0] = tempVert->pos.x; //Vertex Pos0.
currVBOPos[1] = tempVert->pos.y; //Vertex Pos1.
currVBOPos[2] = tempVert->pos.z; //Vertex Pos2.
currVBOPos[3] = 0.0f; //Vertex Pos3 (Dummy).
currVBOPos[8] = tempVert->tc.x; //Texture Coord 0.
currVBOPos[9] = tempVert->tc.y; //Texture Coord 1.
#ifdef DDEDEBUG
//Check for duplicates Verts in the VBO
ddeCheckCurrVertexVBO( tempVert->pos.x,
tempVert->pos.y,
tempVert->pos.z,
VBOCPU,
j,
tempMesh->meshName );
#endif
WeightBuffer.[u]push_back[/u] (boneWeights);
BoneIndexBuffer.[u]push_back[/u](boneIndices);
} // for (mesh vertices)
// For each normal, add contribution to normal from every face that vertex
// is part of and also made the first pass for the Tangent Creation
[u]printf[/u]( "Calculating Normals...
" );
for( ddeInt j = 0; j < tempMesh->numTris; j++ )
{
//Normal Stuff
//Retrieves Vertex from Index List
Vertex *v0 = &tempMesh->verts[ tempMesh->tris[j].v[0] ];
Vertex *v1 = &tempMesh->verts[ tempMesh->tris[j].v[1] ];
Vertex *v2 = &tempMesh->verts[ tempMesh->tris[j].v[2] ];
float Ax = v1->pos[0] - v0->pos[0];
float Ay = v1->pos[1] - v0->pos[1];
float Az = v1->pos[2] - v0->pos[2];
float Bx = v2->pos[0] - v0->pos[0];
float By = v2->pos[1] - v0->pos[1];
float Bz = v2->pos[2] - v0->pos[2];
float nx = Ay * Bz - By * Az;
float ny = -(Ax * Bz - Bx * Az);
float nz = Ax * By - Bx * Ay;
v0->n[0] += nx;
v0->n[1] += ny;
v0->n[2] += nz;
v1->n[0] += nx;
v1->n[1] += ny;
v1->n[2] += nz;
v2->n[0] += nx;
v2->n[1] += ny;
v2->n[2] += nz;
}
[u]printf[/u]( "Calculating First Pass Tangent...
" );
for( ddeInt j = 0; j < tempMesh->numTris; j++ )
{
//Tangent Stuff
//Retrieve Triangle from Index List
ddeLong i1 = tempMesh->tris[j].v[0];
ddeLong i2 = tempMesh->tris[j].v[1];
ddeLong i3 = tempMesh->tris[j].v[2];
//Fill the 3 Verts of the triangle
ddeMath::vec3 vert1 = ddeMath::vec3( tempMesh->verts[i1].pos[0],
tempMesh->verts[i1].pos[1],
tempMesh->verts[i1].pos[2] );
ddeMath::vec3 vert2 = ddeMath::vec3( tempMesh->verts[i2].pos[0],
tempMesh->verts[i2].pos[1],
tempMesh->verts[i2].pos[2] );
ddeMath::vec3 vert3 = ddeMath::vec3( tempMesh->verts[i3].pos[0],
tempMesh->verts[i3].pos[1],
tempMesh->verts[i3].pos[2] );
//Fill the 3 Texture Coords of each Vertex
ddeMath::vec2 tc1 = ddeMath::vec2( tempMesh->verts[i1].tc[0],
tempMesh->verts[i1].tc[1] );
ddeMath::vec2 tc2 = ddeMath::vec2( tempMesh->verts[i2].tc[0],
tempMesh->verts[i2].tc[1] );
ddeMath::vec2 tc3 = ddeMath::vec2( tempMesh->verts[i3].tc[0],
tempMesh->verts[i3].tc[1] );
//Calculate the Tangent
ddeFloatx1 = vert2.x - vert1.x;
ddeFloatx2 = vert3.x - vert1.x;
ddeFloaty1 = vert2.y - vert1.y;
ddeFloaty2 = vert3.y - vert1.y;
ddeFloatz1 = vert2.z - vert1.z;
ddeFloatz2 = vert3.z - vert1.z;
ddeFloats1 = tc2.x - tc1.x;
ddeFloats2 = tc3.x - tc1.x;
ddeFloatt1 = tc2.y - tc1.y;
ddeFloatt2 = tc3.y - tc1.y;
ddeFloat r = 1.0f / (s1 * t2 - s2 * t1);
ddeMath::vec3 sdir = ddeMath::vec3( ( t2 * x1 - t1 * x2 ) * r,
( t2 * y1 - t1 * y2 ) * r,
( t2 * z1 - t1 * z2 ) * r );
ddeMath::vec3 tdir = ddeMath::vec3( ( s1 * x2 - s2 * x1 ) * r,
( s1 * y2 - s2 * y1 ) * r,
( s1 * z2 - s2 * z1 ) * r );
//Add the result for each tangent
tan1[i1] += sdir; tan2[i1] += tdir;
tan2[i2] += sdir; tan2[i2] += tdir;
tan2[i3] += sdir; tan2[i3] += tdir;
}
// Normalize each normal && Calculate Final Tangent and BiNormal
[u]printf[/u]( "Filling Normal - Tangent - BiNormal...
" );
for( ddeIntj = 0, vboCpuIterator = 0; j < tempMesh->numVerts; j++, vboCpuIterator += 16 )
{
Vertex *v = &tempMesh->verts[j];
float mag = (float)[u]sqrt[/u]( float( v->n[0] * v->n[0] + v->n[1] * v->n[1] + v->n[2] * v->n[2] ) );
// Avoid Division By Zero
if ( mag > 0.0001f )
{
v->n[0] /= mag;
v->n[1] /= mag;
v->n[2] /= mag;
}
//Finish Tangent and Binormal Calculations
ddeMath::vec3 tmpNormal = ddeMath::vec3( v->n[0], v->n[1], v->n[2] );
ddeMath::vec3 tmpTan;
( ddeMath::dot( ddeMath::cross( tmpNormal, tan1[j] ), tan2[j] ) < 0.0f) ? tmpTan = tan1[j]
: tmpTan = tan2[j];
ddeMath::orthonormalize( tmpNormal, tmpTan );
ddeMath::vec3 resultTan = tmpTan;
ddeMath::vec3 biNormal = ddeMath::cross( tmpTan, tmpNormal );
// Now save Normals in the VBO Array
currVBOPos = &VBOCPU[vboCpuIterator];
currVBOPos[4] = v->n[0]; //Normal 0.
currVBOPos[5] = v->n[1]; //Normal 1.
currVBOPos[6] = v->n[2]; //Normal 2.
currVBOPos[7] = 0.0f; //Normal 3. (Dummy).
currVBOPos[10] = tmpTan.x; //Tangent x.
currVBOPos[11] = tmpTan.y; //Tangent y.
currVBOPos[12] = tmpTan.z; //Tangent z.
currVBOPos[13] = biNormal.x; //Binormal x.
currVBOPos[14] = biNormal.y; //Binormal y.
currVBOPos[15] = biNormal.z; //Binormal z.
}
// Creates a new Vertex Buffer Object for Mesh, Normals and TexCoords && Populate it
glGenBuffersARB( 1, &( tempMesh->V_N_TC_VBO ) );
glBindBufferARB( GL_ARRAY_BUFFER_ARB, tempMesh->V_N_TC_VBO );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, ( ( tempMesh->numVerts * 16 ) * sizeof( GLfloat ) ), VBOCPU,
GL_STATIC_DRAW_ARB );
// Create a Buffer for the Bone Weights
glGenBuffersARB( 1, &( tempMesh->BWEIGHT_VBO ) );
glBindBufferARB( GL_ARRAY_BUFFER_ARB, tempMesh->BWEIGHT_VBO );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof( ddeMath::vec4 ) * tempMesh->numVerts, &( WeightBuffer[0] ),
GL_STATIC_DRAW_ARB );
// Create a Buffer for the Bone Weights
glGenBuffersARB( 1, &( tempMesh->BINDEX_VBO ) );
glBindBufferARB( GL_ARRAY_BUFFER_ARB, tempMesh->BINDEX_VBO );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof( ddeMath::vec4 ) * tempMesh->numVerts, &( BoneIndexBuffer[0] ),
GL_STATIC_DRAW_ARB );
// Disables VBO Buffer
glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
// Also creates a Vertex Buffer Object for the Triagle List
glGenBuffersARB( 1, &( tempMesh->T_VBO ) );
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, tempMesh->T_VBO );
// At last we Populate the VBO
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ( ( tempMesh->numTris * 3 ) * sizeof( GLfloat ) ),
tempMesh->tris, GL_STATIC_DRAW_ARB );
// Disables VBO Buffer
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
tempMesh->isSkinned = true;
//CheckError();
// Free the temporaries VBOs
[u]free[/u]( VBOCPU );
//TESTING PURPOSE//
[u]free[/u]( tempMesh->verts );
[u]free[/u]( tempMesh->tris );
[u]free[/u]( tempMesh->weights );
}// Only for non skinned meshes
//} // for (meshes)
}
Well, I will keep looking for it!
Thx!