/* * RB_BeginBatch */ void RB_BeginBatch( void ) { mesh_t *mesh; mesh = RB_MapBatchMesh( 0, 0 ); assert( mesh != NULL ); }
/* * R_RenderDebugBounds */ static void R_RenderDebugBounds( void ) { int i, j; vec3_t corner; const vec_t *mins, *maxs; mesh_t *rb_mesh; elem_t elems[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; if( !r_num_debug_bounds ) return; RB_EnableTriangleOutlines( qtrue ); RB_BindShader( rsc.worldent, rsh.whiteShader, NULL ); RB_BindVBO( RB_VBO_STREAM, GL_TRIANGLE_STRIP ); for( i = 0; i < r_num_debug_bounds; i++ ) { mins = r_debug_bounds[i].mins; maxs = r_debug_bounds[i].maxs; rb_mesh = RB_MapBatchMesh( 8, 8 ); for( j = 0; j < 8; j++ ) { corner[0] = ( ( j & 1 ) ? mins[0] : maxs[0] ); corner[1] = ( ( j & 2 ) ? mins[1] : maxs[1] ); corner[2] = ( ( j & 4 ) ? mins[2] : maxs[2] ); VectorCopy( corner, rb_mesh->xyzArray[j] ); } rb_mesh->numVerts = 8; rb_mesh->numElems = 8; rb_mesh->elems = elems; RB_UploadMesh( rb_mesh ); RB_EndBatch(); } RB_EnableTriangleOutlines( qfalse ); }
/* * R_DrawSkeletalSurf */ qboolean R_DrawSkeletalSurf( const entity_t *e, const shader_t *shader, const mfog_t *fog, drawSurfaceSkeletal_t *drawSurf ) { unsigned int i, j; int framenum = e->frame; int oldframenum = e->oldframe; float backlerp = e->backlerp; float frontlerp = 1.0 - backlerp; bonepose_t tempbonepose[256]; const bonepose_t *bp, *oldbp, *bonepose, *oldbonepose, *lerpedbonepose; bonepose_t *out, tp; mskbone_t *bone; mat4_t *bonePoseRelativeMat; dualquat_t *bonePoseRelativeDQ; size_t bonePoseRelativeMatSize, bonePoseRelativeDQSize; const model_t *mod = drawSurf->model; const mskmodel_t *skmodel = ( const mskmodel_t * )mod->extradata; const mskmesh_t *skmesh = drawSurf->mesh; qboolean hardwareTransform = skmesh->vbo != NULL && glConfig.maxGLSLBones > 0 ? qtrue : qfalse; vattribmask_t vattribs; bonePoseRelativeMat = NULL; bonePoseRelativeDQ = NULL; bp = e->boneposes; oldbp = e->oldboneposes; // not sure if it's really needed if( bp == skmodel->frames[0].boneposes ) { bp = NULL; framenum = oldframenum = 0; } // choose boneposes for lerping if( bp ) { if( !oldbp ) oldbp = bp; } else { if( ( framenum >= (int)skmodel->numframes ) || ( framenum < 0 ) ) { #ifndef PUBLIC_BUILD ri.Com_DPrintf( "R_DrawBonesFrameLerp %s: no such frame %d\n", mod->name, framenum ); #endif framenum = 0; } if( ( oldframenum >= (int)skmodel->numframes ) || ( oldframenum < 0 ) ) { #ifndef PUBLIC_BUILD ri.Com_DPrintf( "R_DrawBonesFrameLerp %s: no such oldframe %d\n", mod->name, oldframenum ); #endif oldframenum = 0; } bp = skmodel->frames[framenum].boneposes; oldbp = skmodel->frames[oldframenum].boneposes; } if( bp == oldbp && !framenum && skmesh->vbo != NULL ) { // fastpath: render static frame 0 as is RB_BindVBO( skmesh->vbo->index, GL_TRIANGLES ); RB_DrawElements( 0, skmesh->numverts, 0, skmesh->numtris * 3 ); return qfalse; } // see what vertex attribs backend needs vattribs = RB_GetVertexAttribs(); // cache size bonePoseRelativeMatSize = sizeof( mat4_t ) * (skmodel->numbones + skmodel->numblends); bonePoseRelativeDQSize = sizeof( dualquat_t ) * skmodel->numbones; // fetch bones tranforms from cache (both matrices and dual quaternions) bonePoseRelativeDQ = ( dualquat_t * )R_GetSketalCache( R_ENT2NUM( e ), mod->lodnum ); if( bonePoseRelativeDQ ) { bonePoseRelativeMat = ( mat4_t * )(( qbyte * )bonePoseRelativeDQ + bonePoseRelativeDQSize); } else { // lerp boneposes and store results in cache lerpedbonepose = tempbonepose; if( bp == oldbp || frontlerp == 1 ) { if( e->boneposes ) { // assume that parent transforms have already been applied lerpedbonepose = bp; } else { for( i = 0; i < skmodel->numbones; i++ ) { j = i; out = tempbonepose + j; bonepose = bp + j; bone = skmodel->bones + j; if( bone->parent >= 0 ) { DualQuat_Multiply( tempbonepose[bone->parent].dualquat, bonepose->dualquat, out->dualquat ); } else { DualQuat_Copy( bonepose->dualquat, out->dualquat ); } } } } else { if( e->boneposes ) { // lerp, assume that parent transforms have already been applied for( i = 0, out = tempbonepose, bonepose = bp, oldbonepose = oldbp, bone = skmodel->bones; i < skmodel->numbones; i++, out++, bonepose++, oldbonepose++, bone++ ) { DualQuat_Lerp( oldbonepose->dualquat, bonepose->dualquat, frontlerp, out->dualquat ); } } else { // lerp and transform for( i = 0; i < skmodel->numbones; i++ ) { j = i; out = tempbonepose + j; bonepose = bp + j; oldbonepose = oldbp + j; bone = skmodel->bones + j; DualQuat_Lerp( oldbonepose->dualquat, bonepose->dualquat, frontlerp, out->dualquat ); if( bone->parent >= 0 ) { DualQuat_Copy( out->dualquat, tp.dualquat ); DualQuat_Multiply( tempbonepose[bone->parent].dualquat, tp.dualquat, out->dualquat ); } } } } bonePoseRelativeDQ = ( dualquat_t * )R_AllocSkeletalDataCache( R_ENT2NUM( e ), mod->lodnum, bonePoseRelativeDQSize + bonePoseRelativeMatSize ); // generate dual quaternions for all bones for( i = 0; i < skmodel->numbones; i++ ) { DualQuat_Multiply( lerpedbonepose[i].dualquat, skmodel->invbaseposes[i].dualquat, bonePoseRelativeDQ[i] ); DualQuat_Normalize( bonePoseRelativeDQ[i] ); } // CPU transforms if( !hardwareTransform ) { bonePoseRelativeMat = ( mat4_t * )(( qbyte * )bonePoseRelativeDQ + bonePoseRelativeDQSize); // generate matrices for all bones for( i = 0; i < skmodel->numbones; i++ ) { Matrix4_FromDualQuaternion( bonePoseRelativeDQ[i], bonePoseRelativeMat[i] ); } // generate matrices for all blend combinations R_SkeletalBlendPoses( skmodel->numblends, skmodel->blends, skmodel->numbones, bonePoseRelativeMat ); } } if( hardwareTransform ) { RB_BindVBO( skmesh->vbo->index, GL_TRIANGLES ); RB_SetBonesData( skmodel->numbones, bonePoseRelativeDQ, skmesh->maxWeights ); RB_DrawElements( 0, skmesh->numverts, 0, skmesh->numtris * 3 ); } else { mesh_t *rb_mesh; RB_BindVBO( RB_VBO_STREAM, GL_TRIANGLES ); rb_mesh = RB_MapBatchMesh( skmesh->numverts, skmesh->numtris * 3 ); if( !rb_mesh ) { ri.Com_DPrintf( S_COLOR_YELLOW "R_DrawAliasSurf: RB_MapBatchMesh returned NULL for (%s)(%s)", drawSurf->model->name, skmesh->name ); return qfalse; } R_SkeletalTransformVerts( skmesh->numverts, skmesh->vertexBlends, bonePoseRelativeMat, ( vec_t * )skmesh->xyzArray[0], ( vec_t * )rb_mesh->xyzArray ); if( vattribs & VATTRIB_SVECTOR_BIT ) { R_SkeletalTransformNormalsAndSVecs( skmesh->numverts, skmesh->vertexBlends, bonePoseRelativeMat, ( vec_t * )skmesh->normalsArray[0], ( vec_t * )rb_mesh->normalsArray, ( vec_t * )skmesh->sVectorsArray[0], ( vec_t * )rb_mesh->sVectorsArray ); } else if( vattribs & VATTRIB_NORMAL_BIT ) { R_SkeletalTransformNormals( skmesh->numverts, skmesh->vertexBlends, bonePoseRelativeMat, ( vec_t * )skmesh->normalsArray[0], ( vec_t * )rb_mesh->normalsArray ); } rb_mesh->elems = skmesh->elems; rb_mesh->numElems = skmesh->numtris * 3; rb_mesh->numVerts = skmesh->numverts; rb_mesh->stArray = skmesh->stArray; RB_UploadMesh( rb_mesh ); RB_EndBatch(); } return qfalse; }
/* * R_DrawAliasSurf * * Interpolates between two frames and origins */ qboolean R_DrawAliasSurf( const entity_t *e, const shader_t *shader, const mfog_t *fog, drawSurfaceAlias_t *drawSurf ) { int i; int framenum, oldframenum; float backv[3], frontv[3]; vec3_t normal, oldnormal; qboolean calcVerts, calcNormals, calcSTVectors; vec3_t move; const maliasframe_t *frame, *oldframe; const maliasvertex_t *v, *ov; float backlerp = e->backlerp; const maliasmodel_t *model = ( const maliasmodel_t * )drawSurf->model->extradata; const maliasmesh_t *aliasmesh = drawSurf->mesh; vattribmask_t vattribs; // see what vertex attribs backend needs vattribs = RB_GetVertexAttribs(); framenum = bound( e->frame, 0, model->numframes ); oldframenum = bound( e->oldframe, 0, model->numframes ); frame = model->frames + framenum; oldframe = model->frames + oldframenum; for( i = 0; i < 3; i++ ) move[i] = frame->translate[i] + ( oldframe->translate[i] - frame->translate[i] ) * backlerp; // based on backend's needs calcNormals = calcSTVectors = qfalse; calcNormals = ( ( vattribs & VATTRIB_NORMAL_BIT ) != 0 ) && ( ( framenum != 0 ) || ( oldframenum != 0 ) ); calcSTVectors = ( ( vattribs & VATTRIB_SVECTOR_BIT ) != 0 ) && calcNormals; if( aliasmesh->vbo != NULL && !framenum && !oldframenum ) { RB_BindVBO( aliasmesh->vbo->index, GL_TRIANGLES ); RB_DrawElements( 0, aliasmesh->numverts, 0, aliasmesh->numtris * 3 ); } else { mesh_t *rb_mesh; vec3_t *inVertsArray; vec3_t *inNormalsArray; vec4_t *inSVectorsArray; RB_BindVBO( RB_VBO_STREAM, GL_TRIANGLES ); rb_mesh = RB_MapBatchMesh( aliasmesh->numverts, aliasmesh->numtris * 3 ); if( !rb_mesh ) { ri.Com_DPrintf( S_COLOR_YELLOW "R_DrawAliasSurf: RB_MapBatchMesh returned NULL for (%s)(%s)", drawSurf->model->name, aliasmesh->name ); return qfalse; } inVertsArray = rb_mesh->xyzArray; inNormalsArray = rb_mesh->normalsArray; inSVectorsArray = rb_mesh->sVectorsArray; if( !framenum && !oldframenum ) { calcVerts = qfalse; if( calcNormals ) { v = aliasmesh->vertexes; for( i = 0; i < aliasmesh->numverts; i++, v++ ) R_LatLongToNorm( v->latlong, inNormalsArray[i] ); } } else if( framenum == oldframenum ) { calcVerts = qtrue; for( i = 0; i < 3; i++ ) frontv[i] = frame->scale[i]; v = aliasmesh->vertexes + framenum * aliasmesh->numverts; for( i = 0; i < aliasmesh->numverts; i++, v++ ) { VectorSet( inVertsArray[i], move[0] + v->point[0]*frontv[0], move[1] + v->point[1]*frontv[1], move[2] + v->point[2]*frontv[2] ); if( calcNormals ) R_LatLongToNorm( v->latlong, inNormalsArray[i] ); } } else { calcVerts = qtrue; for( i = 0; i < 3; i++ ) { backv[i] = backlerp * oldframe->scale[i]; frontv[i] = ( 1.0f - backlerp ) * frame->scale[i]; } v = aliasmesh->vertexes + framenum * aliasmesh->numverts; ov = aliasmesh->vertexes + oldframenum * aliasmesh->numverts; for( i = 0; i < aliasmesh->numverts; i++, v++, ov++ ) { VectorSet( inVertsArray[i], move[0] + v->point[0]*frontv[0] + ov->point[0]*backv[0], move[1] + v->point[1]*frontv[1] + ov->point[1]*backv[1], move[2] + v->point[2]*frontv[2] + ov->point[2]*backv[2] ); if( calcNormals ) { R_LatLongToNorm( v->latlong, normal ); R_LatLongToNorm( ov->latlong, oldnormal ); VectorSet( inNormalsArray[i], normal[0] + ( oldnormal[0] - normal[0] ) * backlerp, normal[1] + ( oldnormal[1] - normal[1] ) * backlerp, normal[2] + ( oldnormal[2] - normal[2] ) * backlerp ); } } } if( calcSTVectors ) R_BuildTangentVectors( aliasmesh->numverts, inVertsArray, inNormalsArray, aliasmesh->stArray, aliasmesh->numtris, aliasmesh->elems, inSVectorsArray ); if( !calcVerts ) { rb_mesh->xyzArray = aliasmesh->xyzArray; } rb_mesh->elems = aliasmesh->elems; rb_mesh->numElems = aliasmesh->numtris * 3; rb_mesh->numVerts = aliasmesh->numverts; rb_mesh->stArray = aliasmesh->stArray; if( !calcNormals ) { rb_mesh->normalsArray = aliasmesh->normalsArray; } if( !calcSTVectors ) { rb_mesh->sVectorsArray = aliasmesh->sVectorsArray; } RB_UploadMesh( rb_mesh ); RB_EndBatch(); } return qfalse; }