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); } }
qboolean G2_SetRootSurface(CGhoul2Info_v &ghoul2, const int modelIndex, const char *surfaceName) { int surf; int flags; int *activeSurfaces, *activeBones; assert(ghoul2[modelIndex].currentModel && ghoul2[modelIndex].animModel); model_t *mod_m = (model_t *)ghoul2[modelIndex].currentModel; model_t *mod_a = (model_t *)ghoul2[modelIndex].animModel; // did we find a ghoul 2 model or not? if (!mod_m->mdxm) { return qfalse; } // first find if we already have this surface in the list surf = G2_IsSurfaceLegal(mod_m, surfaceName, &flags); if (surf != -1) { // first see if this ghoul2 model already has this as a root surface if (ghoul2[modelIndex].mSurfaceRoot == surf) { return qtrue; } // set the root surface ghoul2[modelIndex].mSurfaceRoot = surf; // ok, now the tricky bits. // firstly, generate a list of active / on surfaces below the root point // gimme some space to put this list into activeSurfaces = (int *)Z_Malloc(mod_m->mdxm->numSurfaces * 4, TAG_GHOUL2, qtrue); memset(activeSurfaces, 0, (mod_m->mdxm->numSurfaces * 4)); activeBones = (int *)Z_Malloc(mod_a->mdxa->numBones * 4, TAG_GHOUL2, qtrue); memset(activeBones, 0, (mod_a->mdxa->numBones * 4)); G2_FindRecursiveSurface(mod_m, surf, ghoul2[modelIndex].mSlist, activeSurfaces); // now generate the used bone list CConstructBoneList CBL(ghoul2[modelIndex].mSurfaceRoot, activeBones, ghoul2[modelIndex].mSlist, mod_m, ghoul2[modelIndex].mBlist); G2_ConstructUsedBoneList(CBL); // now remove all procedural or override surfaces that refer to surfaces that arent on this list G2_RemoveRedundantGeneratedSurfaces(ghoul2[modelIndex].mSlist, activeSurfaces); // now remove all bones that are pointing at bones that aren't active G2_RemoveRedundantBoneOverrides(ghoul2[modelIndex].mBlist, activeBones); // then remove all bolts that point at surfaces or bones that *arent* active. G2_RemoveRedundantBolts(ghoul2[modelIndex].mBltlist, ghoul2[modelIndex].mSlist, activeSurfaces, activeBones); // then remove all models on this ghoul2 instance that use those bolts that are being removed. for (int i=0; i<ghoul2.size(); i++) { // are we even bolted to anything? if (ghoul2[i].mModelBoltLink != -1) { int boltMod = (ghoul2[i].mModelBoltLink >> MODEL_SHIFT) & MODEL_AND; int boltNum = (ghoul2[i].mModelBoltLink >> BOLT_SHIFT) & BOLT_AND; // if either the bolt list is too small, or the bolt we are pointing at references nothing, remove this model if (((int)ghoul2[boltMod].mBltlist.size() <= boltNum) || ((ghoul2[boltMod].mBltlist[boltNum].boneNumber == -1) && (ghoul2[boltMod].mBltlist[boltNum].surfaceNumber == -1))) { CGhoul2Info_v *g2i = &ghoul2; G2API_RemoveGhoul2Model((CGhoul2Info_v **)&g2i, i); } } } //No support for this, for now. // remember to free what we used Z_Free(activeSurfaces); Z_Free(activeBones); return (qtrue); }