/* ============= RB_SurfacePolychain ============= */ static void RB_SurfacePolychain( srfPoly_t *p ) { int i; int numv; RB_CheckVao(tess.vao); RB_CHECKOVERFLOW( p->numVerts, 3*(p->numVerts - 2) ); // fan triangles into the tess array numv = tess.numVertexes; for ( i = 0; i < p->numVerts; i++ ) { VectorCopy( p->verts[i].xyz, tess.xyz[numv] ); tess.texCoords[numv][0] = p->verts[i].st[0]; tess.texCoords[numv][1] = p->verts[i].st[1]; tess.color[numv][0] = (int)p->verts[i].modulate[0] * 257; tess.color[numv][1] = (int)p->verts[i].modulate[1] * 257; tess.color[numv][2] = (int)p->verts[i].modulate[2] * 257; tess.color[numv][3] = (int)p->verts[i].modulate[3] * 257; numv++; } // generate fan indexes into the tess array for ( i = 0; i < p->numVerts-2; i++ ) { tess.indexes[tess.numIndexes + 0] = tess.numVertexes; tess.indexes[tess.numIndexes + 1] = tess.numVertexes + i + 1; tess.indexes[tess.numIndexes + 2] = tess.numVertexes + i + 2; tess.numIndexes += 3; } tess.numVertexes = numv; }
static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth ) { float spanWidth2; int vbase; float t = len / 256.0f; RB_CheckVao(tess.vao); RB_CHECKOVERFLOW( 4, 6 ); vbase = tess.numVertexes; spanWidth2 = -spanWidth; // FIXME: use quad stamp? VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0] = 0; tess.texCoords[tess.numVertexes][1] = 0; tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25f * 257.0f; tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25f * 257.0f; tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25f * 257.0f; tess.numVertexes++; VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0] = 0; tess.texCoords[tess.numVertexes][1] = 1; tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 257; tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 257; tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 257; tess.numVertexes++; VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0] = t; tess.texCoords[tess.numVertexes][1] = 0; tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 257; tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 257; tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 257; tess.numVertexes++; VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0] = t; tess.texCoords[tess.numVertexes][1] = 1; tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 257; tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 257; tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 257; tess.numVertexes++; tess.indexes[tess.numIndexes++] = vbase; tess.indexes[tess.numIndexes++] = vbase + 1; tess.indexes[tess.numIndexes++] = vbase + 2; tess.indexes[tess.numIndexes++] = vbase + 2; tess.indexes[tess.numIndexes++] = vbase + 1; tess.indexes[tess.numIndexes++] = vbase + 3; }
const void *RB_Draw2dPolys( const void *data ) { const poly2dCommand_t *cmd; shader_t *shader; int i; cmd = ( const poly2dCommand_t * ) data; if ( !backEnd.projection2D ) { RB_SetGL2D(); } shader = cmd->shader; if ( shader != tess.shader ) { if ( tess.numIndexes ) { RB_EndSurface(); } backEnd.currentEntity = &backEnd.entity2D; RB_BeginSurface( shader, 0 ); } RB_CHECKOVERFLOW( cmd->numverts, ( cmd->numverts - 2 ) * 3 ); for ( i = 0; i < cmd->numverts - 2; i++ ) { tess.indexes[ tess.numIndexes + 0 ] = tess.numVertexes; tess.indexes[ tess.numIndexes + 1 ] = tess.numVertexes + i + 1; tess.indexes[ tess.numIndexes + 2 ] = tess.numVertexes + i + 2; tess.numIndexes += 3; } for ( i = 0; i < cmd->numverts; i++ ) { tess.xyz[ tess.numVertexes ].v[ 0 ] = cmd->verts[ i ].xyz[ 0 ]; tess.xyz[ tess.numVertexes ].v[ 1 ] = cmd->verts[ i ].xyz[ 1 ]; tess.xyz[ tess.numVertexes ].v[ 2 ] = 0; tess.texCoords0[ tess.numVertexes ].v[ 0 ] = cmd->verts[ i ].st[ 0 ]; tess.texCoords0[ tess.numVertexes ].v[ 1 ] = cmd->verts[ i ].st[ 1 ]; tess.vertexColors[ tess.numVertexes ].v[ 0 ] = cmd->verts[ i ].modulate[ 0 ]; tess.vertexColors[ tess.numVertexes ].v[ 1 ] = cmd->verts[ i ].modulate[ 1 ]; tess.vertexColors[ tess.numVertexes ].v[ 2 ] = cmd->verts[ i ].modulate[ 2 ]; tess.vertexColors[ tess.numVertexes ].v[ 3 ] = cmd->verts[ i ].modulate[ 3 ]; tess.numVertexes++; } return ( const void * )( cmd + 1 ); }
static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes ) { int s, t; int vertexStart = tess.numVertexes; int tHeight, sWidth; tHeight = maxs[1] - mins[1] + 1; sWidth = maxs[0] - mins[0] + 1; RB_CHECKOVERFLOW( ( maxs[ 0 ] - mins[ 0 ] ) * ( maxs[ 1 ] - mins[ 1 ] ), ( sWidth - 1 ) * ( tHeight - 1 ) * 6 ); for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) { for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) { VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0]; tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1]; tess.numVertexes++; if ( tess.numVertexes >= SHADER_MAX_VERTEXES ) { ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()" ); } } } // only add indexes for one pass, otherwise it would draw multiple times for each pass if ( addIndexes ) { for ( t = 0; t < tHeight-1; t++ ) { for ( s = 0; s < sWidth-1; s++ ) { tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth ); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth ); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); tess.numIndexes++; } } } }
static void FillCloudySkySide(const int mins[2], const int maxs[2], qboolean addIndexes) { int s, t; int vertexStart = tess.numVertexes; int tHeight = maxs[1] - mins[1] + 1; int sWidth = maxs[0] - mins[0] + 1; // overflow check RB_CHECKOVERFLOW((maxs[0] - mins[0]) * (maxs[1] - mins[1]), (sWidth - 1) * (tHeight - 1) * 6); for (t = mins[1] + HALF_SKY_SUBDIVISIONS; t <= maxs[1] + HALF_SKY_SUBDIVISIONS; t++) { for (s = mins[0] + HALF_SKY_SUBDIVISIONS; s <= maxs[0] + HALF_SKY_SUBDIVISIONS; s++) { VectorAdd(s_skyPoints[t][s], backEnd.viewParms.orientation.origin, tess.xyz[tess.numVertexes].v); tess.texCoords0[tess.numVertexes].v[0] = s_skyTexCoords[t][s][0]; tess.texCoords0[tess.numVertexes].v[1] = s_skyTexCoords[t][s][1]; tess.numVertexes++; if (tess.numVertexes >= tess.maxShaderVerts) { Ren_Drop("tess.maxShaderVerts(%i) hit in FillCloudySkySide()\n", tess.maxShaderVerts); } } } // only add indexes for one pass, otherwise it would draw multiple times for each pass if (addIndexes) { for (t = 0; t < tHeight - 1; t++) { for (s = 0; s < sWidth - 1; s++) { tess.indexes[tess.numIndexes] = vertexStart + s + t * (sWidth); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + (t + 1) * (sWidth); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * (sWidth); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + (t + 1) * (sWidth); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + 1 + (t + 1) * (sWidth); tess.numIndexes++; tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * (sWidth); tess.numIndexes++; } } } }
/* ============= RB_SurfaceMesh ============= */ static void RB_SurfaceMesh(mdvSurface_t *surface) { int j; float backlerp; mdvSt_t *texCoords; int Bob, Doug; int numVerts; if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) { backlerp = 0; } else { backlerp = backEnd.currentEntity->e.backlerp; } RB_CheckVao(tess.vao); RB_CHECKOVERFLOW( surface->numVerts, surface->numIndexes ); LerpMeshVertexes (surface, backlerp); Bob = tess.numIndexes; Doug = tess.numVertexes; for (j = 0 ; j < surface->numIndexes ; j++) { tess.indexes[Bob + j] = Doug + surface->indexes[j]; } tess.numIndexes += surface->numIndexes; texCoords = surface->st; numVerts = surface->numVerts; for ( j = 0; j < numVerts; j++ ) { tess.texCoords[Doug + j][0] = texCoords[j].st[0]; tess.texCoords[Doug + j][1] = texCoords[j].st[1]; // FIXME: fill in lightmapST for completeness? } tess.numVertexes += surface->numVerts; }
/* * RB_StretchPic */ const void * RB_StretchPic(const void *data) { const stretchPicCommand_t *cmd; material_t *shader; int numVerts, numIndexes; cmd = (const stretchPicCommand_t*)data; /* FIXME: HUGE hack */ if(glRefConfig.framebufferObject && !glState.currentFBO){ if(backEnd.framePostProcessed){ FBO_Bind(tr.screenScratchFbo); }else{ FBO_Bind(tr.renderFbo); } } RB_SetGL2D(); shader = cmd->shader; if(shader != tess.shader){ if(tess.numIndexes){ RB_EndSurface(); } backEnd.currentEntity = &backEnd.entity2D; RB_BeginSurface(shader, 0); } RB_CHECKOVERFLOW(4, 6); numVerts = tess.numVertexes; numIndexes = tess.numIndexes; tess.numVertexes += 4; tess.numIndexes += 6; tess.indexes[ numIndexes ] = numVerts + 3; tess.indexes[ numIndexes + 1 ] = numVerts + 0; tess.indexes[ numIndexes + 2 ] = numVerts + 2; tess.indexes[ numIndexes + 3 ] = numVerts + 2; tess.indexes[ numIndexes + 4 ] = numVerts + 0; tess.indexes[ numIndexes + 5 ] = numVerts + 1; { Vec4 color; scalev34(backEnd.color2D, 1.0f / 255.0f, color); copyv34(color, tess.vertexColors[ numVerts ]); copyv34(color, tess.vertexColors[ numVerts + 1]); copyv34(color, tess.vertexColors[ numVerts + 2]); copyv34(color, tess.vertexColors[ numVerts + 3 ]); } tess.xyz[ numVerts ][0] = cmd->x; tess.xyz[ numVerts ][1] = cmd->y; tess.xyz[ numVerts ][2] = 0; tess.texCoords[ numVerts ][0][0] = cmd->s1; tess.texCoords[ numVerts ][0][1] = cmd->t1; tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 1 ][1] = cmd->y; tess.xyz[ numVerts + 1 ][2] = 0; tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2; tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1; tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 2 ][2] = 0; tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2; tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2; tess.xyz[ numVerts + 3 ][0] = cmd->x; tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 3 ][2] = 0; tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1; tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2; return (const void*)(cmd + 1); }
/* ============== RB_AddQuadStampExt ============== */ void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4], float s1, float t1, float s2, float t2 ) { vec3_t normal; int16_t iNormal[4]; uint16_t iColor[4]; int ndx; RB_CheckVao(tess.vao); RB_CHECKOVERFLOW( 4, 6 ); ndx = tess.numVertexes; // triangle indexes for a simple quad tess.indexes[ tess.numIndexes ] = ndx; tess.indexes[ tess.numIndexes + 1 ] = ndx + 1; tess.indexes[ tess.numIndexes + 2 ] = ndx + 3; tess.indexes[ tess.numIndexes + 3 ] = ndx + 3; tess.indexes[ tess.numIndexes + 4 ] = ndx + 1; tess.indexes[ tess.numIndexes + 5 ] = ndx + 2; tess.xyz[ndx][0] = origin[0] + left[0] + up[0]; tess.xyz[ndx][1] = origin[1] + left[1] + up[1]; tess.xyz[ndx][2] = origin[2] + left[2] + up[2]; tess.xyz[ndx+1][0] = origin[0] - left[0] + up[0]; tess.xyz[ndx+1][1] = origin[1] - left[1] + up[1]; tess.xyz[ndx+1][2] = origin[2] - left[2] + up[2]; tess.xyz[ndx+2][0] = origin[0] - left[0] - up[0]; tess.xyz[ndx+2][1] = origin[1] - left[1] - up[1]; tess.xyz[ndx+2][2] = origin[2] - left[2] - up[2]; tess.xyz[ndx+3][0] = origin[0] + left[0] - up[0]; tess.xyz[ndx+3][1] = origin[1] + left[1] - up[1]; tess.xyz[ndx+3][2] = origin[2] + left[2] - up[2]; // constant normal all the way around VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal ); R_VaoPackNormal(iNormal, normal); VectorCopy4(iNormal, tess.normal[ndx]); VectorCopy4(iNormal, tess.normal[ndx + 1]); VectorCopy4(iNormal, tess.normal[ndx + 2]); VectorCopy4(iNormal, tess.normal[ndx + 3]); // standard square texture coordinates VectorSet2(tess.texCoords[ndx], s1, t1); VectorSet2(tess.lightCoords[ndx], s1, t1); VectorSet2(tess.texCoords[ndx+1], s2, t1); VectorSet2(tess.lightCoords[ndx+1], s2, t1); VectorSet2(tess.texCoords[ndx+2], s2, t2); VectorSet2(tess.lightCoords[ndx+2], s2, t2); VectorSet2(tess.texCoords[ndx+3], s1, t2); VectorSet2(tess.lightCoords[ndx+3], s1, t2); // constant color all the way around // should this be identity and let the shader specify from entity? R_VaoPackColor(iColor, color); VectorCopy4(iColor, tess.color[ndx]); VectorCopy4(iColor, tess.color[ndx + 1]); VectorCopy4(iColor, tess.color[ndx + 2]); VectorCopy4(iColor, tess.color[ndx + 3]); tess.numVertexes += 4; tess.numIndexes += 6; }
//QTZTODO: Support Centered Pic or vice versa? const void *RB_RotatedPic( const void *data ) { const stretchPicCommand_t *cmd; shader_t *shader; int numVerts, numIndexes; float angle; float pi2 = M_PI * 2; cmd = (const stretchPicCommand_t *)data; if ( !backEnd.projection2D ) RB_SetGL2D(); shader = cmd->shader; if ( shader != tess.shader ) { if ( tess.numIndexes ) RB_EndSurface(); backEnd.currentEntity = &backEnd.entity2D; RB_BeginSurface( shader, 0 ); } RB_CHECKOVERFLOW( 4, 6 ); numVerts = tess.numVertexes; numIndexes = tess.numIndexes; tess.numVertexes += 4; tess.numIndexes += 6; tess.indexes[ numIndexes ] = numVerts + 3; tess.indexes[ numIndexes + 1 ] = numVerts + 0; tess.indexes[ numIndexes + 2 ] = numVerts + 2; tess.indexes[ numIndexes + 3 ] = numVerts + 2; tess.indexes[ numIndexes + 4 ] = numVerts + 0; tess.indexes[ numIndexes + 5 ] = numVerts + 1; *(int *)tess.vertexColors[ numVerts ] = *(int *)tess.vertexColors[ numVerts + 1 ] = *(int *)tess.vertexColors[ numVerts + 2 ] = *(int *)tess.vertexColors[ numVerts + 3 ] = *(int *)backEnd.color2D; angle = cmd->angle * pi2; tess.xyz[ numVerts ].x = cmd->x + ( cosf( angle ) * cmd->w ); tess.xyz[ numVerts ].y = cmd->y + ( sinf( angle ) * cmd->h ); tess.xyz[ numVerts ].z = 0; tess.texCoords[ numVerts ][0].x = cmd->s1; tess.texCoords[ numVerts ][0].y = cmd->t1; angle = cmd->angle * pi2 + 0.25f * pi2; tess.xyz[ numVerts + 1 ].x = cmd->x + ( cosf( angle ) * cmd->w ); tess.xyz[ numVerts + 1 ].y = cmd->y + ( sinf( angle ) * cmd->h ); tess.xyz[ numVerts + 1 ].z = 0; tess.texCoords[ numVerts + 1 ][0].x = cmd->s2; tess.texCoords[ numVerts + 1 ][0].y = cmd->t1; angle = cmd->angle * pi2 + 0.50f * pi2; tess.xyz[ numVerts + 2 ].x = cmd->x + ( cosf( angle ) * cmd->w ); tess.xyz[ numVerts + 2 ].y = cmd->y + ( sinf( angle ) * cmd->h ); tess.xyz[ numVerts + 2 ].z = 0; tess.texCoords[ numVerts + 2 ][0].x = cmd->s2; tess.texCoords[ numVerts + 2 ][0].y = cmd->t2; angle = cmd->angle * pi2 + 0.75f * pi2; tess.xyz[ numVerts + 3 ].x = cmd->x + ( cosf( angle ) * cmd->w ); tess.xyz[ numVerts + 3 ].y = cmd->y + ( sinf( angle ) * cmd->h ); tess.xyz[ numVerts + 3 ].z = 0; tess.texCoords[ numVerts + 3 ][0].x = cmd->s1; tess.texCoords[ numVerts + 3 ][0].y = cmd->t2; return (const void *)( cmd + 1 ); }
/* ================= RB_AddIQMSurfaces Compute vertices for this model surface ================= */ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { srfIQModel_t *surf = (srfIQModel_t *)surface; iqmData_t *data = surf->data; float jointMats[IQM_MAX_JOINTS * 12]; int i; vec4_t *outXYZ; uint32_t *outNormal; #ifdef USE_VERT_TANGENT_SPACE uint32_t *outTangent; #endif vec2_t (*outTexCoord)[2]; vec4_t *outColor; iqmData_t *skeleton = R_GetIQMModelDataByHandle( backEnd.currentEntity->e.frameModel, data ); iqmData_t *oldSkeleton = R_GetIQMModelDataByHandle( backEnd.currentEntity->e.oldframeModel, data ); int frame = skeleton->num_frames ? backEnd.currentEntity->e.frame % skeleton->num_frames : 0; int oldframe = oldSkeleton->num_frames ? backEnd.currentEntity->e.oldframe % oldSkeleton->num_frames : 0; float backlerp = backEnd.currentEntity->e.backlerp; int *tri; glIndex_t *ptr; glIndex_t base; if ( data != skeleton && data->num_joints != skeleton->num_poses ) { ri.Printf( PRINT_WARNING, "WARNING: frameModel '%s' for model '%s' has different number of joints\n", R_GetModelByHandle( backEnd.currentEntity->e.frameModel )->name, R_GetModelByHandle( backEnd.currentEntity->e.hModel )->name ); skeleton = data; } if ( data != oldSkeleton && data->num_joints != oldSkeleton->num_poses ) { ri.Printf( PRINT_WARNING, "WARNING: oldframeModel '%s' for model '%s' has different number of joints\n", R_GetModelByHandle( backEnd.currentEntity->e.oldframeModel )->name, R_GetModelByHandle( backEnd.currentEntity->e.hModel )->name ); oldSkeleton = data; } RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 ); outXYZ = &tess.xyz[tess.numVertexes]; outNormal = &tess.normal[tess.numVertexes]; #ifdef USE_VERT_TANGENT_SPACE outTangent = &tess.tangent[tess.numVertexes]; #endif outTexCoord = &tess.texCoords[tess.numVertexes]; outColor = &tess.vertexColors[tess.numVertexes]; // compute interpolated joint matrices if ( skeleton->num_poses > 0 ) { ComputePoseMats( data, skeleton, oldSkeleton, frame, oldframe, backlerp, jointMats ); } // transform vertexes and fill other data for( i = 0; i < surf->num_vertexes; i++, outXYZ++, outNormal++, outTexCoord++, outColor++ ) { int j, k; float vtxMat[12]; float nrmMat[9]; int vtx = i + surf->first_vertex; float blendWeights[4]; int numWeights; for ( numWeights = 0; numWeights < 4; numWeights++ ) { if ( data->blendWeightsType == IQM_FLOAT ) blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights]; else blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f; if ( blendWeights[numWeights] <= 0 ) break; } if ( skeleton->num_poses == 0 || numWeights == 0 ) { // no blend joint, use identity matrix. Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) ); } else { // compute the vertex matrix by blending the up to // four blend weights Com_Memset( vtxMat, 0, 12 * sizeof (float) ); for( j = 0; j < numWeights; j++ ) { for( k = 0; k < 12; k++ ) { vtxMat[k] += blendWeights[j] * jointMats[12*data->blendIndexes[4*vtx + j] + k]; } } } // compute the normal matrix as transpose of the adjoint // of the vertex matrix nrmMat[ 0] = vtxMat[ 5]*vtxMat[10] - vtxMat[ 6]*vtxMat[ 9]; nrmMat[ 1] = vtxMat[ 6]*vtxMat[ 8] - vtxMat[ 4]*vtxMat[10]; nrmMat[ 2] = vtxMat[ 4]*vtxMat[ 9] - vtxMat[ 5]*vtxMat[ 8]; nrmMat[ 3] = vtxMat[ 2]*vtxMat[ 9] - vtxMat[ 1]*vtxMat[10]; nrmMat[ 4] = vtxMat[ 0]*vtxMat[10] - vtxMat[ 2]*vtxMat[ 8]; nrmMat[ 5] = vtxMat[ 1]*vtxMat[ 8] - vtxMat[ 0]*vtxMat[ 9]; nrmMat[ 6] = vtxMat[ 1]*vtxMat[ 6] - vtxMat[ 2]*vtxMat[ 5]; nrmMat[ 7] = vtxMat[ 2]*vtxMat[ 4] - vtxMat[ 0]*vtxMat[ 6]; nrmMat[ 8] = vtxMat[ 0]*vtxMat[ 5] - vtxMat[ 1]*vtxMat[ 4]; (*outTexCoord)[0][0] = data->texcoords[2*vtx + 0]; (*outTexCoord)[0][1] = data->texcoords[2*vtx + 1]; (*outTexCoord)[1][0] = (*outTexCoord)[0][0]; (*outTexCoord)[1][1] = (*outTexCoord)[0][1]; (*outXYZ)[0] = vtxMat[ 0] * data->positions[3*vtx+0] + vtxMat[ 1] * data->positions[3*vtx+1] + vtxMat[ 2] * data->positions[3*vtx+2] + vtxMat[ 3]; (*outXYZ)[1] = vtxMat[ 4] * data->positions[3*vtx+0] + vtxMat[ 5] * data->positions[3*vtx+1] + vtxMat[ 6] * data->positions[3*vtx+2] + vtxMat[ 7]; (*outXYZ)[2] = vtxMat[ 8] * data->positions[3*vtx+0] + vtxMat[ 9] * data->positions[3*vtx+1] + vtxMat[10] * data->positions[3*vtx+2] + vtxMat[11]; (*outXYZ)[3] = 1.0f; { vec3_t normal; vec4_t tangent; normal[0] = DotProduct(&nrmMat[0], &data->normals[3*vtx]); normal[1] = DotProduct(&nrmMat[3], &data->normals[3*vtx]); normal[2] = DotProduct(&nrmMat[6], &data->normals[3*vtx]); *outNormal = R_VboPackNormal(normal); #ifdef USE_VERT_TANGENT_SPACE tangent[0] = DotProduct(&nrmMat[0], &data->tangents[4*vtx]); tangent[1] = DotProduct(&nrmMat[3], &data->tangents[4*vtx]); tangent[2] = DotProduct(&nrmMat[6], &data->tangents[4*vtx]); tangent[3] = data->tangents[4*vtx+3]; *outTangent++ = R_VboPackTangent(tangent); #endif } (*outColor)[0] = data->colors[4*vtx+0] / 255.0f; (*outColor)[1] = data->colors[4*vtx+1] / 255.0f; (*outColor)[2] = data->colors[4*vtx+2] / 255.0f; (*outColor)[3] = data->colors[4*vtx+3] / 255.0f; } tri = data->triangles + 3 * surf->first_triangle; ptr = &tess.indexes[tess.numIndexes]; base = tess.numVertexes; for( i = 0; i < surf->num_triangles; i++ ) { *ptr++ = base + (*tri++ - surf->first_vertex); *ptr++ = base + (*tri++ - surf->first_vertex); *ptr++ = base + (*tri++ - surf->first_vertex); } tess.numIndexes += 3 * surf->num_triangles; tess.numVertexes += surf->num_vertexes; }
/* ============== RB_MDRSurfaceAnim ============== */ void RB_MDRSurfaceAnim( mdrSurface_t *surface ) { int i, j, k; float frontlerp, backlerp; int *triangles; int indexes; int baseIndex, baseVertex; int numVerts; mdrVertex_t *v; mdrHeader_t *header; mdrFrame_t *frame; mdrFrame_t *oldFrame; mdrBone_t bones[MDR_MAX_BONES], *bonePtr, *bone; int frameSize; // don't lerp if lerping off, or this is the only frame, or the last frame... // if (backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame) { backlerp = 0; // if backlerp is 0, lerping is off and frontlerp is never used frontlerp = 1; } else { backlerp = backEnd.currentEntity->e.backlerp; frontlerp = 1.0f - backlerp; } header = (mdrHeader_t *)((byte *)surface + surface->ofsHeader); frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] ); frame = (mdrFrame_t *)((byte *)header + header->ofsFrames + backEnd.currentEntity->e.frame * frameSize ); oldFrame = (mdrFrame_t *)((byte *)header + header->ofsFrames + backEnd.currentEntity->e.oldframe * frameSize ); RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles * 3 ); triangles = (int *) ((byte *)surface + surface->ofsTriangles); indexes = surface->numTriangles * 3; baseIndex = tess.numIndexes; baseVertex = tess.numVertexes; // Set up all triangles. for (j = 0 ; j < indexes ; j++) { tess.indexes[baseIndex + j] = baseVertex + triangles[j]; } tess.numIndexes += indexes; // // lerp all the needed bones // if ( !backlerp ) { // no lerping needed bonePtr = frame->bones; } else { bonePtr = bones; for ( i = 0 ; i < header->numBones*12 ; i++ ) { ((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i] + backlerp * ((float *)oldFrame->bones)[i]; } } // // deform the vertexes by the lerped bones // numVerts = surface->numVerts; v = (mdrVertex_t *) ((byte *)surface + surface->ofsVerts); for ( j = 0; j < numVerts; j++ ) { vec3_t tempVert, tempNormal; mdrWeight_t *w; VectorClear( tempVert ); VectorClear( tempNormal ); w = v->weights; for ( k = 0 ; k < v->numWeights ; k++, w++ ) { bone = bonePtr + w->boneIndex; tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] ); tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] ); tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] ); tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal ); tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal ); tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal ); } tess.xyz[baseVertex + j][0] = tempVert[0]; tess.xyz[baseVertex + j][1] = tempVert[1]; tess.xyz[baseVertex + j][2] = tempVert[2]; R_VaoPackNormal(tess.normal[baseVertex + j], tempNormal); tess.texCoords[baseVertex + j][0] = v->texCoords[0]; tess.texCoords[baseVertex + j][1] = v->texCoords[1]; v = (mdrVertex_t *)&v->weights[v->numWeights]; } tess.numVertexes += surface->numVerts; }
/* ================= RB_AddIQMSurfaces Compute vertices for this model surface ================= */ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { srfIQModel_t *surf = (srfIQModel_t *)surface; iqmData_t *data = surf->data; float jointMats[IQM_MAX_JOINTS * 12]; int i; vec4_t *outXYZ; vec4_t *outNormal; vec2_t (*outTexCoord)[2]; color4ub_t *outColor; int frame = data->num_frames ? backEnd.currentEntity->e.frame % data->num_frames : 0; int oldframe = data->num_frames ? backEnd.currentEntity->e.oldframe % data->num_frames : 0; float backlerp = backEnd.currentEntity->e.backlerp; int *tri; glIndex_t *ptr; glIndex_t base; RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 ); outXYZ = &tess.xyz[tess.numVertexes]; outNormal = &tess.normal[tess.numVertexes]; outTexCoord = &tess.texCoords[tess.numVertexes]; outColor = &tess.vertexColors[tess.numVertexes]; // compute interpolated joint matrices if ( data->num_poses > 0 ) { ComputePoseMats( data, frame, oldframe, backlerp, jointMats ); } // transform vertexes and fill other data for( i = 0; i < surf->num_vertexes; i++, outXYZ++, outNormal++, outTexCoord++, outColor++ ) { int j, k; float vtxMat[12]; float nrmMat[9]; int vtx = i + surf->first_vertex; float blendWeights[4]; int numWeights; for ( numWeights = 0; numWeights < 4; numWeights++ ) { if ( data->blendWeightsType == IQM_FLOAT ) blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights]; else blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f; if ( blendWeights[numWeights] <= 0 ) break; } if ( data->num_poses == 0 || numWeights == 0 ) { // no blend joint, use identity matrix. Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) ); } else { // compute the vertex matrix by blending the up to // four blend weights Com_Memset( vtxMat, 0, 12 * sizeof (float) ); for( j = 0; j < numWeights; j++ ) { for( k = 0; k < 12; k++ ) { vtxMat[k] += blendWeights[j] * jointMats[12*data->blendIndexes[4*vtx + j] + k]; } } } // compute the normal matrix as transpose of the adjoint // of the vertex matrix nrmMat[ 0] = vtxMat[ 5]*vtxMat[10] - vtxMat[ 6]*vtxMat[ 9]; nrmMat[ 1] = vtxMat[ 6]*vtxMat[ 8] - vtxMat[ 4]*vtxMat[10]; nrmMat[ 2] = vtxMat[ 4]*vtxMat[ 9] - vtxMat[ 5]*vtxMat[ 8]; nrmMat[ 3] = vtxMat[ 2]*vtxMat[ 9] - vtxMat[ 1]*vtxMat[10]; nrmMat[ 4] = vtxMat[ 0]*vtxMat[10] - vtxMat[ 2]*vtxMat[ 8]; nrmMat[ 5] = vtxMat[ 1]*vtxMat[ 8] - vtxMat[ 0]*vtxMat[ 9]; nrmMat[ 6] = vtxMat[ 1]*vtxMat[ 6] - vtxMat[ 2]*vtxMat[ 5]; nrmMat[ 7] = vtxMat[ 2]*vtxMat[ 4] - vtxMat[ 0]*vtxMat[ 6]; nrmMat[ 8] = vtxMat[ 0]*vtxMat[ 5] - vtxMat[ 1]*vtxMat[ 4]; (*outTexCoord)[0][0] = data->texcoords[2*vtx + 0]; (*outTexCoord)[0][1] = data->texcoords[2*vtx + 1]; (*outTexCoord)[1][0] = (*outTexCoord)[0][0]; (*outTexCoord)[1][1] = (*outTexCoord)[0][1]; (*outXYZ)[0] = vtxMat[ 0] * data->positions[3*vtx+0] + vtxMat[ 1] * data->positions[3*vtx+1] + vtxMat[ 2] * data->positions[3*vtx+2] + vtxMat[ 3]; (*outXYZ)[1] = vtxMat[ 4] * data->positions[3*vtx+0] + vtxMat[ 5] * data->positions[3*vtx+1] + vtxMat[ 6] * data->positions[3*vtx+2] + vtxMat[ 7]; (*outXYZ)[2] = vtxMat[ 8] * data->positions[3*vtx+0] + vtxMat[ 9] * data->positions[3*vtx+1] + vtxMat[10] * data->positions[3*vtx+2] + vtxMat[11]; (*outXYZ)[3] = 1.0f; (*outNormal)[0] = nrmMat[ 0] * data->normals[3*vtx+0] + nrmMat[ 1] * data->normals[3*vtx+1] + nrmMat[ 2] * data->normals[3*vtx+2]; (*outNormal)[1] = nrmMat[ 3] * data->normals[3*vtx+0] + nrmMat[ 4] * data->normals[3*vtx+1] + nrmMat[ 5] * data->normals[3*vtx+2]; (*outNormal)[2] = nrmMat[ 6] * data->normals[3*vtx+0] + nrmMat[ 7] * data->normals[3*vtx+1] + nrmMat[ 8] * data->normals[3*vtx+2]; (*outNormal)[3] = 0.0f; (*outColor)[0] = data->colors[4*vtx+0]; (*outColor)[1] = data->colors[4*vtx+1]; (*outColor)[2] = data->colors[4*vtx+2]; (*outColor)[3] = data->colors[4*vtx+3]; } tri = data->triangles + 3 * surf->first_triangle; ptr = &tess.indexes[tess.numIndexes]; base = tess.numVertexes; for( i = 0; i < surf->num_triangles; i++ ) { *ptr++ = base + (*tri++ - surf->first_vertex); *ptr++ = base + (*tri++ - surf->first_vertex); *ptr++ = base + (*tri++ - surf->first_vertex); } tess.numIndexes += 3 * surf->num_triangles; tess.numVertexes += surf->num_vertexes; }
void RB_DrawPolys( const void *data ) { const drawPolysCmd_t *cmd = (drawPolysCmd_t*)data; uint i; uint numVerts, numIndices; float *xy, *st; uint *colors; glIndex_t *indices; uint baseVtx; if( !backEnd.projection2D ) RB_SetGL2D(); numVerts = cmd->numVertsPerPoly * cmd->numPolys; numIndices = cmd->numPolys * (cmd->numVertsPerPoly - 2) * 3; RB_CheckSurface( cmd->shader, 0, GL_TRIANGLES ); RB_CHECKOVERFLOW( numVerts, numIndices ); baseVtx = tess.numVertexes; xy = tess.xyz[baseVtx]; st = tess.texCoords[baseVtx][0]; colors = (uint*)tess.vertexColors + baseVtx; tess.numVertexes = baseVtx + numVerts; for( i = 0; i < numVerts; i++ ) { xy[0] = cmd->verts[i].xy[0]; xy[1] = cmd->verts[i].xy[1]; xy[2] = 0; st[0] = cmd->verts[i].st[0]; st[1] = cmd->verts[i].st[1]; *colors = *(uint*)cmd->verts[i].modulate; xy++; st++; colors++; } indices = tess.indexes + tess.numIndexes; for( i = 0; i < cmd->numPolys; i++ ) { uint j; //emit fan-order indices for( j = 2; j < cmd->numVertsPerPoly; j++ ) { indices[0] = baseVtx; indices[1] = baseVtx + j - 1; indices[2] = baseVtx + j; indices += 3; } baseVtx += cmd->numVertsPerPoly; } tess.numIndexes += numIndices; }
/*============================================================== RB_SurfaceMyGhoul Called when a MyGhoul surf is asked to render. ==============================================================*/ void RB_SurfaceMyGhoul( surfaceType_t *surface ) { glmSurface_t *surf = (glmSurface_t *)surface; // int i, j, k; int j, k; int *triangles; int indexes; int baseIndex, baseVertex; int numVerts; glmVertex_t *v; glmVertexTexCoord_t *t; glmHeader_t *header; model_t *model_anims = NULL; // mdxaHeader_t *anims; vec3_t tempVert, tempNormal; int animated = 0; // int numWeights; // int boneIndices[4]; // float boneWeights[4]; // float totalWeight = 0.0; //mgMatrix34_t final; //mg_animstate_t *as = NULL; //mgMatrix34_t *pose = NULL; float *outXyz, *outNormal; // vec3_t newXyz, newNormal; float zrots[3][4]; int do_zrot = 1; zrots[0][0] = 0.0; zrots[0][1] = -1.0; zrots[0][2] = 0.0; zrots[0][3] = 0.0; zrots[1][0] = 1.0; zrots[1][1] = 0.0; zrots[1][2] = 0.0; zrots[1][3] = 0.0; zrots[2][0] = 0.0; zrots[2][1] = 0.0; zrots[2][2] = 1.0; zrots[2][3] = 0.0; header = (glmHeader_t *)((byte *)surf + surf->ofsHeader); RB_CHECKOVERFLOW( surf->numVerts, surf->numTriangles * 3 ); triangles = (int *) ((byte *)surf + surf->ofsTriangles); indexes = surf->numTriangles * 3; baseIndex = tess.numIndexes; baseVertex = tess.numVertexes; outXyz = tess.xyz[baseVertex]; outNormal = tess.normal[baseVertex]; for (j = 0 ; j < indexes ; j++) { tess.indexes[baseIndex + j] = baseVertex + triangles[j]; } tess.numIndexes += indexes; #if 0 if( header->animIndex != 0 ) { model_anims = R_GetModelByHandle( header->animIndex ); if( model_anims->type == MOD_GLA ) { anims = model_anims->gla; as = RE_AS_Fetch( backEnd.currentEntity->e.frame ); } if( as->index == 0 ) { anims = 0; animated = 0; } else { animated = 1; pose = as->pose; } } else #endif { animated = 0; } //animated = 0; numVerts = surf->numVerts; v = (glmVertex_t *)((byte *)surf + surf->ofsVerts); triangles = (int *)((byte *)surf + surf->ofsBoneReferences ); for( k=0; k<numVerts; k++, outXyz+=4, outNormal+=4 ) { tempVert[0] = v->vertCoords[0]; tempVert[1] = v->vertCoords[1]; tempVert[2] = v->vertCoords[2]; tempNormal[0] = v->normal[0]; tempNormal[1] = v->normal[1]; tempNormal[2] = v->normal[2]; #if 0 if( animated ) { numWeights = GLM_GetVertNumWeights( v ); final.matrix[0][0] = final.matrix[0][1] = final.matrix[0][2] = final.matrix[0][3] = final.matrix[1][0] = final.matrix[1][1] = final.matrix[1][2] = final.matrix[1][3] = final.matrix[2][0] = final.matrix[2][1] = final.matrix[2][2] = final.matrix[2][3] = 0.0; totalWeight = 0.0; for( i = 0; i < numWeights; i++ ) { boneIndices[i] = triangles[( v->uiNmWeightsAndBoneIndexes >> ( 5 * i ) ) & ( ( 1 << 5 ) - 1 )]; if( i == numWeights-1 ) { boneWeights[i] = 1.0f-totalWeight; } else { boneWeights[i] = GLM_GetVertBoneWeight( v, i, v->BoneWeightings[i], v->uiNmWeightsAndBoneIndexes, totalWeight ); } totalWeight += boneWeights[i]; Matrix34AddScale( final.matrix, pose[boneIndices[i]].matrix, boneWeights[i] ); } Matrix34VectorRotateAdd( final.matrix, tempVert, newXyz ); Matrix34VectorRotate( final.matrix, tempNormal, newNormal ); outXyz[0] = newXyz[0]; outXyz[1] = newXyz[1]; outXyz[2] = newXyz[2]; outNormal[0] = newNormal[0]; outNormal[1] = newNormal[1]; outNormal[2] = newNormal[2]; } else #endif { if( do_zrot )
/* ============= RB_RotatedPic ============= */ const void *RB_RotatedPic( const void *data ) { const stretchPicCommand_t *cmd; shader_t *shader; int numVerts, numIndexes; float mx, my, cosA, sinA, cw, ch, sw, sh; cmd = ( const stretchPicCommand_t * ) data; if ( !backEnd.projection2D ) { RB_SetGL2D(); } shader = cmd->shader; if ( shader != tess.shader ) { if ( tess.numIndexes ) { RB_EndSurface(); } backEnd.currentEntity = &backEnd.entity2D; RB_BeginSurface( shader, 0 ); } RB_CHECKOVERFLOW( 4, 6 ); numVerts = tess.numVertexes; numIndexes = tess.numIndexes; tess.numVertexes += 4; tess.numIndexes += 6; tess.indexes[ numIndexes ] = numVerts + 3; tess.indexes[ numIndexes + 1 ] = numVerts + 0; tess.indexes[ numIndexes + 2 ] = numVerts + 2; tess.indexes[ numIndexes + 3 ] = numVerts + 2; tess.indexes[ numIndexes + 4 ] = numVerts + 0; tess.indexes[ numIndexes + 5 ] = numVerts + 1; * ( int * ) tess.vertexColors[ numVerts ].v = * ( int * ) tess.vertexColors[ numVerts + 1 ].v = * ( int * ) tess.vertexColors[ numVerts + 2 ].v = * ( int * ) tess.vertexColors[ numVerts + 3 ].v = * ( int * ) backEnd.color2D; mx = cmd->x + ( cmd->w / 2 ); my = cmd->y + ( cmd->h / 2 ); cosA = cos( DEG2RAD( cmd->angle ) ); sinA = sin( DEG2RAD( cmd->angle ) ); cw = cosA * ( cmd->w / 2 ); ch = cosA * ( cmd->h / 2 ); sw = sinA * ( cmd->w / 2 ); sh = sinA * ( cmd->h / 2 ); tess.xyz[ numVerts ].v[ 0 ] = mx - cw - sh; tess.xyz[ numVerts ].v[ 1 ] = my + sw - ch; tess.xyz[ numVerts ].v[ 2 ] = 0; tess.texCoords0[ numVerts ].v[ 0 ] = cmd->s1; tess.texCoords0[ numVerts ].v[ 1 ] = cmd->t1; tess.xyz[ numVerts + 1 ].v[ 0 ] = mx + cw - sh; tess.xyz[ numVerts + 1 ].v[ 1 ] = my - sw - ch; tess.xyz[ numVerts + 1 ].v[ 2 ] = 0; tess.texCoords0[ numVerts + 1 ].v[ 0 ] = cmd->s2; tess.texCoords0[ numVerts + 1 ].v[ 1 ] = cmd->t1; tess.xyz[ numVerts + 2 ].v[ 0 ] = mx + cw + sh; tess.xyz[ numVerts + 2 ].v[ 1 ] = my - sw + ch; tess.xyz[ numVerts + 2 ].v[ 2 ] = 0; tess.texCoords0[ numVerts + 2 ].v[ 0 ] = cmd->s2; tess.texCoords0[ numVerts + 2 ].v[ 1 ] = cmd->t2; tess.xyz[ numVerts + 3 ].v[ 0 ] = mx - cw + sh; tess.xyz[ numVerts + 3 ].v[ 1 ] = my + sw + ch; tess.xyz[ numVerts + 3 ].v[ 2 ] = 0; tess.texCoords0[ numVerts + 3 ].v[ 0 ] = cmd->s1; tess.texCoords0[ numVerts + 3 ].v[ 1 ] = cmd->t2; return ( const void * )( cmd + 1 ); }
static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up ) { int i; vec3_t pos[4]; vec3_t v; int spanWidth = r_railWidth->integer; float c, s; float scale; if ( numSegs > 1 ) numSegs--; if ( !numSegs ) return; scale = 0.25; for ( i = 0; i < 4; i++ ) { c = cos( DEG2RAD( 45 + i * 90 ) ); s = sin( DEG2RAD( 45 + i * 90 ) ); v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth; v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth; v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth; VectorAdd( start, v, pos[i] ); if ( numSegs > 1 ) { // offset by 1 segment if we're doing a long distance shot VectorAdd( pos[i], dir, pos[i] ); } } RB_CheckVao(tess.vao); for ( i = 0; i < numSegs; i++ ) { int j; RB_CHECKOVERFLOW( 4, 6 ); for ( j = 0; j < 4; j++ ) { VectorCopy( pos[j], tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0] = (j < 2); tess.texCoords[tess.numVertexes][1] = (j && j != 3); tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 257; tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 257; tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 257; tess.numVertexes++; VectorAdd( pos[j], dir, pos[j] ); } tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0; tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2; } }
static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIndexes, glIndex_t *indexes, int dlightBits, int pshadowBits) { int i; glIndex_t *inIndex; srfVert_t *dv; float *xyz, *texCoords, *lightCoords; int16_t *lightdir; int16_t *normal; int16_t *tangent; glIndex_t *outIndex; uint16_t *color; RB_CheckVao(tess.vao); RB_CHECKOVERFLOW( numVerts, numIndexes ); inIndex = indexes; outIndex = &tess.indexes[ tess.numIndexes ]; for ( i = 0 ; i < numIndexes ; i++ ) { *outIndex++ = tess.numVertexes + *inIndex++; } tess.numIndexes += numIndexes; if ( tess.shader->vertexAttribs & ATTR_POSITION ) { dv = verts; xyz = tess.xyz[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, xyz+=4 ) VectorCopy(dv->xyz, xyz); } if ( tess.shader->vertexAttribs & ATTR_NORMAL ) { dv = verts; normal = tess.normal[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, normal+=4 ) VectorCopy4(dv->normal, normal); } if ( tess.shader->vertexAttribs & ATTR_TANGENT ) { dv = verts; tangent = tess.tangent[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, tangent+=4 ) VectorCopy4(dv->tangent, tangent); } if ( tess.shader->vertexAttribs & ATTR_TEXCOORD ) { dv = verts; texCoords = tess.texCoords[tess.numVertexes]; for ( i = 0 ; i < numVerts ; i++, dv++, texCoords+=2 ) VectorCopy2(dv->st, texCoords); } if ( tess.shader->vertexAttribs & ATTR_LIGHTCOORD ) { dv = verts; lightCoords = tess.lightCoords[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, lightCoords+=2 ) VectorCopy2(dv->lightmap, lightCoords); } if ( tess.shader->vertexAttribs & ATTR_COLOR ) { dv = verts; color = tess.color[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, color+=4 ) VectorCopy4(dv->color, color); } if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION ) { dv = verts; lightdir = tess.lightdir[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, lightdir+=4 ) VectorCopy4(dv->lightdir, lightdir); } #if 0 // nothing even uses vertex dlightbits for ( i = 0 ; i < numVerts ; i++ ) { tess.vertexDlightBits[ tess.numVertexes + i ] = dlightBits; } #endif tess.dlightBits |= dlightBits; tess.pshadowBits |= pshadowBits; tess.numVertexes += numVerts; }
/* ================= RB_AddIQMSurfaces Compute vertices for this model surface ================= */ void RB_IQMSurfaceAnim(surfaceType_t* surface) { srfIQModel_t* surf = (srfIQModel_t*)surface; iqmData_t* data = surf->data; float jointMats[IQM_MAX_JOINTS * 12]; int i; vec4_t* outXYZ = &tess.xyz[tess.numVertexes]; vec4_t* outNormal = &tess.normal[tess.numVertexes]; vec2_t (*outTexCoord)[2] = &tess.texCoords[tess.numVertexes]; color4ub_t* outColor = &tess.vertexColors[tess.numVertexes]; int frame = backEnd.currentEntity->e.frame % data->num_frames; int oldframe = backEnd.currentEntity->e.oldframe % data->num_frames; float backlerp = backEnd.currentEntity->e.backlerp; int* tri; glIndex_t* ptr; glIndex_t base; RB_CHECKOVERFLOW(surf->num_vertexes, surf->num_triangles * 3); // compute interpolated joint matrices ComputeJointMats(data, frame, oldframe, backlerp, jointMats); // transform vertexes and fill other data for (i = 0; i < surf->num_vertexes; i++, outXYZ++, outNormal++, outTexCoord++, outColor++) { int j, k; float vtxMat[12]; float nrmMat[9]; int vtx = i + surf->first_vertex; // compute the vertex matrix by blending the up to // four blend weights for (k = 0; k < 12; k++) vtxMat[k] = data->blendWeights[4 * vtx] * jointMats[12 * data->blendIndexes[4 * vtx] + k]; for (j = 1; j < 4; j++) { if (data->blendWeights[4 * vtx + j] <= 0) break; for (k = 0; k < 12; k++) vtxMat[k] += data->blendWeights[4 * vtx + j] * jointMats[12 * data->blendIndexes[4 * vtx + j] + k]; } for (k = 0; k < 12; k++) vtxMat[k] *= 1.0f / 255.0f; // compute the normal matrix as transpose of the adjoint // of the vertex matrix nrmMat[ 0] = vtxMat[ 5] * vtxMat[10] - vtxMat[ 6] * vtxMat[ 9]; nrmMat[ 1] = vtxMat[ 6] * vtxMat[ 8] - vtxMat[ 4] * vtxMat[10]; nrmMat[ 2] = vtxMat[ 4] * vtxMat[ 9] - vtxMat[ 5] * vtxMat[ 8]; nrmMat[ 3] = vtxMat[ 2] * vtxMat[ 9] - vtxMat[ 1] * vtxMat[10]; nrmMat[ 4] = vtxMat[ 0] * vtxMat[10] - vtxMat[ 2] * vtxMat[ 8]; nrmMat[ 5] = vtxMat[ 1] * vtxMat[ 8] - vtxMat[ 0] * vtxMat[ 9]; nrmMat[ 6] = vtxMat[ 1] * vtxMat[ 6] - vtxMat[ 2] * vtxMat[ 5]; nrmMat[ 7] = vtxMat[ 2] * vtxMat[ 4] - vtxMat[ 0] * vtxMat[ 6]; nrmMat[ 8] = vtxMat[ 0] * vtxMat[ 5] - vtxMat[ 1] * vtxMat[ 4]; (*outTexCoord)[0][0] = data->texcoords[2 * vtx + 0]; (*outTexCoord)[0][1] = data->texcoords[2 * vtx + 1]; (*outTexCoord)[1][0] = (*outTexCoord)[0][0]; (*outTexCoord)[1][1] = (*outTexCoord)[0][1]; (*outXYZ)[0] = vtxMat[ 0] * data->positions[3 * vtx + 0] + vtxMat[ 1] * data->positions[3 * vtx + 1] + vtxMat[ 2] * data->positions[3 * vtx + 2] + vtxMat[ 3]; (*outXYZ)[1] = vtxMat[ 4] * data->positions[3 * vtx + 0] + vtxMat[ 5] * data->positions[3 * vtx + 1] + vtxMat[ 6] * data->positions[3 * vtx + 2] + vtxMat[ 7]; (*outXYZ)[2] = vtxMat[ 8] * data->positions[3 * vtx + 0] + vtxMat[ 9] * data->positions[3 * vtx + 1] + vtxMat[10] * data->positions[3 * vtx + 2] + vtxMat[11]; (*outXYZ)[3] = 1.0f; (*outNormal)[0] = nrmMat[ 0] * data->normals[3 * vtx + 0] + nrmMat[ 1] * data->normals[3 * vtx + 1] + nrmMat[ 2] * data->normals[3 * vtx + 2]; (*outNormal)[1] = nrmMat[ 3] * data->normals[3 * vtx + 0] + nrmMat[ 4] * data->normals[3 * vtx + 1] + nrmMat[ 5] * data->normals[3 * vtx + 2]; (*outNormal)[2] = nrmMat[ 6] * data->normals[3 * vtx + 0] + nrmMat[ 7] * data->normals[3 * vtx + 1] + nrmMat[ 8] * data->normals[3 * vtx + 2]; (*outNormal)[3] = 0.0f; (*outColor)[0] = data->colors[4 * vtx + 0]; (*outColor)[1] = data->colors[4 * vtx + 1]; (*outColor)[2] = data->colors[4 * vtx + 2]; (*outColor)[3] = data->colors[4 * vtx + 3]; } tri = data->triangles + 3 * surf->first_triangle; ptr = &tess.indexes[tess.numIndexes]; base = tess.numVertexes; for (i = 0; i < surf->num_triangles; i++) { *ptr++ = base + (*tri++ - surf->first_vertex); *ptr++ = base + (*tri++ - surf->first_vertex); *ptr++ = base + (*tri++ - surf->first_vertex); } tess.numIndexes += 3 * surf->num_triangles; tess.numVertexes += surf->num_vertexes; }
/* ============= RB_StretchPic ============= */ const void *RB_StretchPic ( const void *data ) { const stretchPicCommand_t *cmd; shader_t *shader; int numVerts, numIndexes; cmd = (const stretchPicCommand_t *)data; // FIXME: HUGE hack if (glRefConfig.framebufferObject) FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo); RB_SetGL2D(); shader = cmd->shader; if ( shader != tess.shader ) { if ( tess.numIndexes ) { RB_EndSurface(); } backEnd.currentEntity = &backEnd.entity2D; RB_BeginSurface( shader, 0, 0 ); } RB_CHECKOVERFLOW( 4, 6 ); numVerts = tess.numVertexes; numIndexes = tess.numIndexes; tess.numVertexes += 4; tess.numIndexes += 6; tess.indexes[ numIndexes ] = numVerts + 3; tess.indexes[ numIndexes + 1 ] = numVerts + 0; tess.indexes[ numIndexes + 2 ] = numVerts + 2; tess.indexes[ numIndexes + 3 ] = numVerts + 2; tess.indexes[ numIndexes + 4 ] = numVerts + 0; tess.indexes[ numIndexes + 5 ] = numVerts + 1; { uint16_t color[4]; VectorScale4(backEnd.color2D, 257, color); VectorCopy4(color, tess.color[ numVerts ]); VectorCopy4(color, tess.color[ numVerts + 1]); VectorCopy4(color, tess.color[ numVerts + 2]); VectorCopy4(color, tess.color[ numVerts + 3 ]); } tess.xyz[ numVerts ][0] = cmd->x; tess.xyz[ numVerts ][1] = cmd->y; tess.xyz[ numVerts ][2] = 0; tess.texCoords[ numVerts ][0] = cmd->s1; tess.texCoords[ numVerts ][1] = cmd->t1; tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 1 ][1] = cmd->y; tess.xyz[ numVerts + 1 ][2] = 0; tess.texCoords[ numVerts + 1 ][0] = cmd->s2; tess.texCoords[ numVerts + 1 ][1] = cmd->t1; tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 2 ][2] = 0; tess.texCoords[ numVerts + 2 ][0] = cmd->s2; tess.texCoords[ numVerts + 2 ][1] = cmd->t2; tess.xyz[ numVerts + 3 ][0] = cmd->x; tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 3 ][2] = 0; tess.texCoords[ numVerts + 3 ][0] = cmd->s1; tess.texCoords[ numVerts + 3 ][1] = cmd->t2; return (const void *)(cmd + 1); }
/* ============= RB_StretchPic ============= */ const void *RB_StretchPic ( const void *data ) { const stretchPicCommand_t *cmd; shader_t *shader; int numVerts, numIndexes; cmd = (const stretchPicCommand_t *)data; if ( !backEnd.projection2D ) { RB_SetGL2D(); } shader = cmd->shader; if ( shader != tess.shader ) { if ( tess.numIndexes ) { RB_EndSurface(); } backEnd.currentEntity = &backEnd.entity2D; RB_BeginSurface( shader, 0 ); } RB_CHECKOVERFLOW( 4, 6 ); numVerts = tess.numVertexes; numIndexes = tess.numIndexes; tess.numVertexes += 4; tess.numIndexes += 6; tess.indexes[ numIndexes ] = numVerts + 3; tess.indexes[ numIndexes + 1 ] = numVerts + 0; tess.indexes[ numIndexes + 2 ] = numVerts + 2; tess.indexes[ numIndexes + 3 ] = numVerts + 2; tess.indexes[ numIndexes + 4 ] = numVerts + 0; tess.indexes[ numIndexes + 5 ] = numVerts + 1; *(int *)tess.vertexColors[ numVerts ] = *(int *)tess.vertexColors[ numVerts + 1 ] = *(int *)tess.vertexColors[ numVerts + 2 ] = *(int *)tess.vertexColors[ numVerts + 3 ] = *(int *)backEnd.color2D; tess.xyz[ numVerts ][0] = cmd->x; tess.xyz[ numVerts ][1] = cmd->y; tess.xyz[ numVerts ][2] = 0; tess.texCoords[ numVerts ][0][0] = cmd->s1; tess.texCoords[ numVerts ][0][1] = cmd->t1; tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 1 ][1] = cmd->y; tess.xyz[ numVerts + 1 ][2] = 0; tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2; tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1; tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 2 ][2] = 0; tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2; tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2; tess.xyz[ numVerts + 3 ][0] = cmd->x; tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 3 ][2] = 0; tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1; tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2; return (const void *)(cmd + 1); }
static void RB_StretchPic ( const void *data ) { const stretchPicCommand_t *cmd = (const stretchPicCommand_t *)data; int i; shader_t *shader; int numVerts, numIndexes; if( !backEnd.projection2D ) RB_SetGL2D(); shader = cmd->shader; RB_CheckSurface( shader, 0, GL_TRIANGLES ); RB_CHECKOVERFLOW( 4, 6 ); numVerts = tess.numVertexes; numIndexes = tess.numIndexes; tess.numVertexes += 4; tess.numIndexes += 6; tess.indexes[ numIndexes ] = numVerts + 3; tess.indexes[ numIndexes + 1 ] = numVerts + 0; tess.indexes[ numIndexes + 2 ] = numVerts + 2; tess.indexes[ numIndexes + 3 ] = numVerts + 2; tess.indexes[ numIndexes + 4 ] = numVerts + 0; tess.indexes[ numIndexes + 5 ] = numVerts + 1; *(int *)tess.vertexColors[ numVerts ] = *(int *)tess.vertexColors[ numVerts + 1 ] = *(int *)tess.vertexColors[ numVerts + 2 ] = *(int *)tess.vertexColors[ numVerts + 3 ] = *(int *)backEnd.color2D; tess.xyz[ numVerts ][0] = cmd->x; tess.xyz[ numVerts ][1] = cmd->y; tess.xyz[ numVerts ][2] = 0; tess.texCoords[ numVerts ][0][0] = cmd->s1; tess.texCoords[ numVerts ][0][1] = cmd->t1; tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 1 ][1] = cmd->y; tess.xyz[ numVerts + 1 ][2] = 0; tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2; tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1; tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 2 ][2] = 0; tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2; tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2; tess.xyz[ numVerts + 3 ][0] = cmd->x; tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 3 ][2] = 0; tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1; tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2; for( i = 0; i < 4; i++ ) { vec2_t v; Vec2_Cpy( v, tess.xyz[numVerts + i] ); tess.xyz[numVerts + i][0] = v[0] * cmd->mat[0][0] + v[1] * cmd->mat[0][1] + cmd->mat[0][2]; tess.xyz[numVerts + i][1] = v[0] * cmd->mat[1][0] + v[1] * cmd->mat[1][1] + cmd->mat[1][2]; } }