StdSubMesh::Vertex TransformVertex(const StdSubMesh::Vertex& vertex) { StdMeshVector pos, normal; pos.x = vertex.x; pos.y = vertex.y; pos.z = vertex.z; normal.x = vertex.nx; normal.y = vertex.ny; normal.z = vertex.nz; pos = TransformVector(pos); normal = TransformNormalVector(normal); StdSubMesh::Vertex result = vertex; result.x = pos.x; result.y = pos.y; result.z = pos.z; result.nx = normal.x; result.ny = normal.y; result.nz = normal.z; return result; }
/* ================= Tess_SurfaceIQM Compute vertices for this model surface ================= */ void Tess_SurfaceIQM( srfIQModel_t *surf ) { IQModel_t *model = surf->data; int i, j; int offset = tess.numVertexes - surf->first_vertex; GLimp_LogComment( "--- RB_SurfaceIQM ---\n" ); Tess_CheckOverflow( surf->num_vertexes, surf->num_triangles * 3 ); // compute bones for ( i = 0; i < model->num_joints; i++ ) { if ( backEnd.currentEntity->e.skeleton.type == SK_ABSOLUTE ) { refBone_t *bone = &backEnd.currentEntity->e.skeleton.bones[ i ]; TransInverse( &model->joints[ i ], &bones[ i ] ); TransCombine( &bones[ i ], &bone->t, &bones[ i ] ); } else { TransInit( &bones[ i ] ); } TransAddScale( backEnd.currentEntity->e.skeleton.scale, &bones[ i ] ); TransInsScale( model->internalScale, &bones[ i ] ); } if( surf->vbo && surf->ibo ) { if( model->num_joints > 0 ) { Com_Memcpy( tess.bones, bones, model->num_joints * sizeof(transform_t) ); tess.numBones = model->num_joints; } else { TransInitScale( model->internalScale * backEnd.currentEntity->e.skeleton.scale, &tess.bones[ 0 ] ); tess.numBones = 1; } R_BindVBO( surf->vbo ); R_BindIBO( surf->ibo ); tess.vboVertexSkinning = true; tess.multiDrawIndexes[ tess.multiDrawPrimitives ] = ((glIndex_t *)nullptr) + surf->first_triangle * 3; tess.multiDrawCounts[ tess.multiDrawPrimitives ] = surf->num_triangles * 3; tess.multiDrawPrimitives++; Tess_End(); return; } for ( i = 0; i < surf->num_triangles; i++ ) { tess.indexes[ tess.numIndexes + i * 3 + 0 ] = offset + model->triangles[ 3 * ( surf->first_triangle + i ) + 0 ]; tess.indexes[ tess.numIndexes + i * 3 + 1 ] = offset + model->triangles[ 3 * ( surf->first_triangle + i ) + 1 ]; tess.indexes[ tess.numIndexes + i * 3 + 2 ] = offset + model->triangles[ 3 * ( surf->first_triangle + i ) + 2 ]; } tess.attribsSet |= ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT; if( model->num_joints > 0 && model->blendWeights && model->blendIndexes ) { // deform the vertices by the lerped bones for ( i = 0; i < surf->num_vertexes; i++ ) { int idxIn = surf->first_vertex + i; int idxOut = tess.numVertexes + i; const float weightFactor = 1.0f / 255.0f; vec3_t tangent, binormal, normal, tmp; if( model->blendWeights[ 4 * idxIn + 0 ] == 0 && model->blendWeights[ 4 * idxIn + 1 ] == 0 && model->blendWeights[ 4 * idxIn + 2 ] == 0 && model->blendWeights[ 4 * idxIn + 3 ] == 0 ) model->blendWeights[ 4 * idxIn + 0 ] = 255; VectorClear( tess.verts[ idxOut ].xyz ); VectorClear( normal ); VectorClear( tangent ); VectorClear( binormal ); for ( j = 0; j < 4; j++ ) { int bone = model->blendIndexes[ 4 * idxIn + j ]; float weight = weightFactor * model->blendWeights[ 4 * idxIn + j ]; TransformPoint( &bones[ bone ], &model->positions[ 3 * idxIn ], tmp ); VectorMA( tess.verts[ idxOut ].xyz, weight, tmp, tess.verts[ idxOut ].xyz ); TransformNormalVector( &bones[ bone ], &model->normals[ 3 * idxIn ], tmp ); VectorMA( normal, weight, tmp, normal ); TransformNormalVector( &bones[ bone ], &model->tangents[ 3 * idxIn ], tmp ); VectorMA( tangent, weight, tmp, tangent ); TransformNormalVector( &bones[ bone ], &model->bitangents[ 3 * idxIn ], tmp ); VectorMA( binormal, weight, tmp, binormal ); } VectorNormalize( normal ); VectorNormalize( tangent ); VectorNormalize( binormal ); R_TBNtoQtangents( tangent, binormal, normal, tess.verts[ idxOut ].qtangents ); tess.verts[ idxOut ].texCoords[ 0 ] = model->texcoords[ 2 * idxIn + 0 ]; tess.verts[ idxOut ].texCoords[ 1 ] = model->texcoords[ 2 * idxIn + 1 ]; } } else { for ( i = 0; i < surf->num_vertexes; i++ ) { int idxIn = surf->first_vertex + i; int idxOut = tess.numVertexes + i; float scale = model->internalScale * backEnd.currentEntity->e.skeleton.scale; VectorScale( &model->positions[ 3 * idxIn ], scale, tess.verts[ idxOut ].xyz ); R_TBNtoQtangents( &model->tangents[ 3 * idxIn ], &model->bitangents[ 3 * idxIn ], &model->normals[ 3 * idxIn ], tess.verts[ idxOut ].qtangents ); tess.verts[ idxOut ].texCoords[ 0 ] = model->texcoords[ 2 * idxIn + 0 ]; tess.verts[ idxOut ].texCoords[ 1 ] = model->texcoords[ 2 * idxIn + 1 ]; } } tess.numIndexes += 3 * surf->num_triangles; tess.numVertexes += surf->num_vertexes; }
/* ============== Tess_SurfaceMD5 ============== */ static void Tess_SurfaceMD5( md5Surface_t *srf ) { int j; int numIndexes = 0; int numVertexes; md5Model_t *model; md5Vertex_t *v; srfTriangle_t *tri; GLimp_LogComment( "--- Tess_SurfaceMD5 ---\n" ); Tess_CheckOverflow( srf->numVerts, srf->numTriangles * 3 ); model = srf->model; numIndexes = srf->numTriangles * 3; tri = srf->triangles; for (unsigned i = 0; i < srf->numTriangles; i++, tri++ ) { tess.indexes[ tess.numIndexes + i * 3 + 0 ] = tess.numVertexes + tri->indexes[ 0 ]; tess.indexes[ tess.numIndexes + i * 3 + 1 ] = tess.numVertexes + tri->indexes[ 1 ]; tess.indexes[ tess.numIndexes + i * 3 + 2 ] = tess.numVertexes + tri->indexes[ 2 ]; } tess.attribsSet |= ATTR_POSITION | ATTR_TEXCOORD; if ( tess.skipTangentSpaces ) { // convert bones back to matrices for (unsigned i = 0; i < model->numBones; i++ ) { if ( backEnd.currentEntity->e.skeleton.type == SK_ABSOLUTE ) { refBone_t *bone = &backEnd.currentEntity->e.skeleton.bones[ i ]; TransInitRotationQuat( model->bones[ i ].rotation, &bones[ i ] ); TransAddTranslation( model->bones[ i ].origin, &bones[ i ] ); TransInverse( &bones[ i ], &bones[ i ] ); TransCombine( &bones[ i ], &bone->t, &bones[ i ] ); TransAddScale( backEnd.currentEntity->e.skeleton.scale, &bones[ i ] ); } else { TransInitRotationQuat( model->bones[ i ].rotation, &bones[i] ); TransAddTranslation( model->bones[ i ].origin, &bones[ i ] ); } TransInsScale( model->internalScale, &bones[ i ] ); } // deform the vertices by the lerped bones numVertexes = srf->numVerts; for ( j = 0, v = srf->verts; j < numVertexes; j++, v++ ) { vec3_t tmp; VectorClear( tess.verts[ tess.numVertexes + j ].xyz ); for (unsigned k = 0; k < v->numWeights; k++ ) { TransformPoint( &bones[ v->boneIndexes[ k ] ], v->position, tmp ); VectorMA( tess.verts[ tess.numVertexes + j ].xyz, v->boneWeights[ k ], tmp, tess.verts[ tess.numVertexes + j ].xyz ); } tess.verts[ tess.numVertexes + j ].texCoords[ 0 ] = floatToHalf( v->texCoords[ 0 ] ); tess.verts[ tess.numVertexes + j ].texCoords[ 1 ] = floatToHalf( v->texCoords[ 1 ] ); } } else { tess.attribsSet |= ATTR_QTANGENT; // convert bones back to matrices for (unsigned i = 0; i < model->numBones; i++ ) { if ( backEnd.currentEntity->e.skeleton.type == SK_ABSOLUTE ) { refBone_t *bone = &backEnd.currentEntity->e.skeleton.bones[ i ]; TransInitRotationQuat( model->bones[ i ].rotation, &bones[ i ] ); TransAddTranslation( model->bones[ i ].origin, &bones[ i ] ); TransInverse( &bones[ i ], &bones[ i ] ); TransCombine( &bones[ i ], &bone->t, &bones[ i ] ); TransAddScale( backEnd.currentEntity->e.skeleton.scale, &bones[ i ] ); } else { TransInitScale( backEnd.currentEntity->e.skeleton.scale, &bones[ i ] ); } TransInsScale( model->internalScale, &bones[ i ] ); } // deform the vertices by the lerped bones numVertexes = srf->numVerts; for ( j = 0, v = srf->verts; j < numVertexes; j++, v++ ) { vec3_t tangent, binormal, normal, tmp; VectorClear( tess.verts[ tess.numVertexes + j ].xyz ); VectorClear( normal ); VectorClear( binormal ); VectorClear( tangent ); for(unsigned k = 0; k < v->numWeights; k++ ) { TransformPoint( &bones[ v->boneIndexes[ k ] ], v->position, tmp ); VectorMA( tess.verts[ tess.numVertexes + j ].xyz, v->boneWeights[ k ], tmp, tess.verts[ tess.numVertexes + j ].xyz ); TransformNormalVector( &bones[ v->boneIndexes[ k ] ], v->normal, tmp ); VectorMA( normal, v->boneWeights[ k ], tmp, normal ); TransformNormalVector( &bones[ v->boneIndexes[ k ] ], v->tangent, tmp ); VectorMA( tangent, v->boneWeights[ k ], tmp, tangent ); TransformNormalVector( &bones[ v->boneIndexes[ k ] ], v->binormal, tmp ); VectorMA( binormal, v->boneWeights[ k ], tmp, binormal ); } VectorNormalize( normal ); VectorNormalize( tangent ); VectorNormalize( binormal ); R_TBNtoQtangents( tangent, binormal, normal, tess.verts[ tess.numVertexes + j ].qtangents ); tess.verts[ tess.numVertexes + j ].texCoords[ 0 ] = floatToHalf( v->texCoords[ 0 ] ); tess.verts[ tess.numVertexes + j ].texCoords[ 1 ] = floatToHalf( v->texCoords[ 1 ] ); } } tess.numIndexes += numIndexes; tess.numVertexes += numVertexes; }