void G2_TraceModels(CGhoul2Info_v &ghoul2, vec3_t rayStart, vec3_t rayEnd, CCollisionRecord *collRecMap, int entNum, EG2_Collision eG2TraceType, int useLod, float fRadius) { int i, lod; skin_t *skin; shader_t *cust_shader; // walk each possible model for this entity and try tracing against it for (i=0; i<ghoul2.size(); i++) { // don't bother with models that we don't care about. if (!ghoul2[i].mValid) { continue; } assert(G2_MODEL_OK(&ghoul2[i])); // do we really want to collide with this object? if (ghoul2[i].mFlags & GHOUL2_NOCOLLIDE) { continue; } if (ghoul2[i].mCustomShader) { cust_shader = R_GetShaderByHandle(ghoul2[i].mCustomShader ); } else { cust_shader = NULL; } // figure out the custom skin thing if ( ghoul2[i].mSkin > 0 && ghoul2[i].mSkin < tr.numSkins ) { skin = R_GetSkinByHandle( ghoul2[i].mSkin ); } else { skin = NULL; } lod = G2_DecideTraceLod(ghoul2[i],useLod); //reset the quick surface override lookup G2_FindOverrideSurface(-1, ghoul2[i].mSlist); CTraceSurface TS(ghoul2[i].mSurfaceRoot, ghoul2[i].mSlist, ghoul2[i].currentModel, lod, rayStart, rayEnd, collRecMap, entNum, i, skin, cust_shader, ghoul2[i].mTransformedVertsArray, eG2TraceType, fRadius); // start the surface recursion loop G2_TraceSurfaces(TS); // if we've hit one surface on one model, don't bother doing the rest if (TS.hitOne) { break; } } }
// main calling point for the model transform for collision detection. At this point all of the skeleton has been transformed. void G2_TransformModel(CGhoul2Info_v &ghoul2, const int frameNum, vec3_t scale, CMiniHeap *G2VertSpace, int useLod) { int i, lod; vec3_t correctScale; VectorCopy(scale, correctScale); // check for scales of 0 - that's the default I believe if (!scale[0]) { correctScale[0] = 1.0; } if (!scale[1]) { correctScale[1] = 1.0; } if (!scale[2]) { correctScale[2] = 1.0; } // walk each possible model for this entity and try rendering it out for (i=0; i<ghoul2.size(); i++) { CGhoul2Info &g=ghoul2[i]; // don't bother with models that we don't care about. if (!g.mValid) { continue; } assert(g.mBoneCache); assert(G2_MODEL_OK(&g)); // stop us building this model more than once per frame g.mMeshFrameNum = frameNum; // decide the LOD lod = G2_DecideTraceLod(g, useLod); // give us space for the transformed vertex array to be put in ghoul2[i].mTransformedVertsArray = (int*)G2VertSpace->MiniHeapAlloc(g.currentModel->mdxm->numSurfaces * 4); if (!g.mTransformedVertsArray) { Com_Error(ERR_DROP, "Ran out of transform space for Ghoul2 Models. Adjust MiniHeapSize in SV_SpawnServer.\n"); } memset(g.mTransformedVertsArray, 0,(g.currentModel->mdxm->numSurfaces * 4)); G2_FindOverrideSurface(-1,g.mSlist); //reset the quick surface override lookup; // recursively call the model surface transform G2_TransformSurfaces(g.mSurfaceRoot, g.mSlist, g.mBoneCache, g.currentModel, lod, correctScale, G2VertSpace, g.mTransformedVertsArray, false); } }
// remove any bolts that reference original surfaces, generated surfaces, or bones that aren't active anymore void G2_RemoveRedundantBolts(boltInfo_v &bltlist, surfaceInfo_v &slist, int *activeSurfaces, int *activeBones) { // walk the bolt list for (size_t i=0; i<bltlist.size(); i++) { // are we using this bolt? if ((bltlist[i].surfaceNumber != -1) || (bltlist[i].boneNumber != -1)) { // is this referenceing a surface? if (bltlist[i].surfaceNumber != -1) { // is this bolt looking at a generated surface? if (bltlist[i].surfaceType) { // yes, so look for it in the surface list if (!G2_FindOverrideSurface(bltlist[i].surfaceNumber, slist)) { // no - we want to remove this bolt, regardless of how many people are using it bltlist[i].boltUsed = 1; G2_Remove_Bolt(bltlist, i); } } // no, it's an original, so look for it in the active surfaces list { if (!activeSurfaces[bltlist[i].surfaceNumber]) { // no - we want to remove this bolt, regardless of how many people are using it bltlist[i].boltUsed = 1; G2_Remove_Bolt(bltlist, i); } } } // no, must be looking at a bone then else { // is that bone active then? if (!activeBones[bltlist[i].boneNumber]) { // no - we want to remove this bolt, regardless of how many people are using it bltlist[i].boltUsed = 1; G2_Remove_Bolt(bltlist, i); } } } } }
void G2_FindRecursiveSurface(const model_t *currentModel, int surfaceNum, surfaceInfo_v &rootList, int *activeSurfaces) { assert(currentModel); assert(currentModel->mdxm); int i; const mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface(currentModel, surfaceNum, 0); const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)currentModel->mdxm + sizeof(mdxmHeader_t)); const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]); // see if we have an override surface in the surface list const surfaceInfo_t *surfOverride = G2_FindOverrideSurface(surfaceNum, rootList); // really, we should use the default flags for this surface unless it's been overriden int offFlags = surfInfo->flags; // set the off flags if we have some if (surfOverride) { offFlags = surfOverride->offFlags; } // if this surface is not off, indicate as such in the active surface list if (!(offFlags & G2SURFACEFLAG_OFF)) { activeSurfaces[surfaceNum] = 1; } else // if we are turning off all descendants, then stop this recursion now if (offFlags & G2SURFACEFLAG_NODESCENDANTS) { return; } // now recursively call for the children for (i=0; i< surfInfo->numChildren; i++) { surfaceNum = surfInfo->childIndexes[i]; G2_FindRecursiveSurface(currentModel, surfaceNum, rootList, activeSurfaces); } }
void G2_TransformSurfaces(int surfaceNum, surfaceInfo_v &rootSList, CBoneCache *boneCache, const model_t *currentModel, int lod, vec3_t scale, CMiniHeap *G2VertSpace, int *TransformedVertArray, bool secondTimeAround) { int i; assert(currentModel); assert(currentModel->mdxm); // back track and get the surfinfo struct for this surface const mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface(currentModel, surfaceNum, lod); const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)currentModel->mdxm + sizeof(mdxmHeader_t)); const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]); // see if we have an override surface in the surface list const surfaceInfo_t *surfOverride = G2_FindOverrideSurface(surfaceNum, rootSList); // really, we should use the default flags for this surface unless it's been overriden int offFlags = surfInfo->flags; if (surfOverride) { offFlags = surfOverride->offFlags; } // if this surface is not off, add it to the shader render list if (!offFlags) { R_TransformEachSurface(surface, scale, G2VertSpace, TransformedVertArray, boneCache); } // if we are turning off all descendants, then stop this recursion now if (offFlags & G2SURFACEFLAG_NODESCENDANTS) { return; } // now recursively call for the children for (i=0; i< surfInfo->numChildren; i++) { G2_TransformSurfaces(surfInfo->childIndexes[i], rootSList, boneCache, currentModel, lod, scale, G2VertSpace, TransformedVertArray, secondTimeAround); } }
// look at a surface and then do the trace on each poly static void G2_TraceSurfaces(CTraceSurface &TS) { int i; // back track and get the surfinfo struct for this surface assert(TS.currentModel); assert(TS.currentModel->mdxm); const mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface(TS.currentModel, TS.surfaceNum, TS.lod); const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)TS.currentModel->mdxm + sizeof(mdxmHeader_t)); const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]); // see if we have an override surface in the surface list const surfaceInfo_t *surfOverride = G2_FindOverrideSurface(TS.surfaceNum, TS.rootSList); // don't allow recursion if we've already hit a polygon if (TS.hitOne) { return; } // really, we should use the default flags for this surface unless it's been overriden int offFlags = surfInfo->flags; // set the off flags if we have some if (surfOverride) { offFlags = surfOverride->offFlags; } // if this surface is not off, try to hit it if (!offFlags) { if (!(fabs(TS.m_fRadius) < 0.1)) // if not a point-trace { // .. then use radius check // if (G2_RadiusTracePolys(surface, // const mdxmSurface_t *surface, TS ) && (TS.eG2TraceType == G2_RETURNONHIT) ) { TS.hitOne = true; return; } } else { // go away and trace the polys in this surface if (G2_TracePolys(surface, surfInfo, TS) && (TS.eG2TraceType == G2_RETURNONHIT) ) { // ok, we hit one, *and* we want to return instantly because the returnOnHit is set // so indicate we've hit one, so other surfaces don't get hit and return TS.hitOne = true; return; } } } // if we are turning off all descendants, then stop this recursion now if (offFlags & G2SURFACEFLAG_NODESCENDANTS) { return; } // now recursively call for the children for (i=0; i< surfInfo->numChildren && !TS.hitOne; i++) { TS.surfaceNum = surfInfo->childIndexes[i]; G2_TraceSurfaces(TS); } }