void G2_SetSurfaceOnOffFromSkin (CGhoul2Info *ghlInfo, qhandle_t renderSkin) { int j; const skin_t *skin = R_GetSkinByHandle( renderSkin ); ghlInfo->mSlist.clear(); //remove any overrides we had before. ghlInfo->mMeshFrameNum = 0; for ( j = 0 ; j < skin->numSurfaces ; j++ ) { // the names have both been lowercased //Raz: why is this using the shader name and not the surface name? if ( !strcmp( ((shader_t *)skin->surfaces[j]->shader)->name, "*off") ) { G2_SetSurfaceOnOff(ghlInfo, ghlInfo->mSlist, skin->surfaces[j]->name, G2SURFACEFLAG_OFF); } else { int flags; int surfaceNum = G2_IsSurfaceLegal((void *)ghlInfo->currentModel, skin->surfaces[j]->name, &flags); if ( (surfaceNum != -1) && (!(flags&G2SURFACEFLAG_OFF)) ) //only turn on if it's not an "_off" surface { G2_SetSurfaceOnOff(ghlInfo, ghlInfo->mSlist, skin->surfaces[j]->name, 0); } } } }
// set a named surface offFlags - if it doesn't find a surface with this name in the list then it will add one. qboolean G2_SetSurfaceOnOff (CGhoul2Info *ghlInfo, surfaceInfo_v &slist, const char *surfaceName, const int offFlags) { int surfIndex = -1; surfaceInfo_t temp_slist_entry; mdxmSurface_t *surf; // find the model we want model_t *mod = (model_t *)ghlInfo->currentModel; // did we find a ghoul 2 model or not? if (!mod->mdxm) { assert(0); return qfalse; } // first find if we already have this surface in the list surf = G2_FindSurface(ghlInfo, slist, surfaceName, &surfIndex); if (surf) { // set descendants value // slist[surfIndex].offFlags = offFlags; // seems to me that we shouldn't overwrite the other flags. // the only bit we really care about in the incoming flags is the off bit slist[surfIndex].offFlags &= ~(G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS); slist[surfIndex].offFlags |= offFlags & (G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS); return qtrue; } else { // ok, not in the list already - in that case, lets verify this surface exists in the model mesh int flags; int surfaceNum = G2_IsSurfaceLegal((void*)mod, surfaceName, &flags); if (surfaceNum != -1) { int newflags = flags; // the only bit we really care about in the incoming flags is the off bit newflags &= ~(G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS); newflags |= offFlags & (G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS); if (newflags != flags) { // insert here then because it changed, no need to add an override otherwise temp_slist_entry.offFlags = newflags; temp_slist_entry.surface = surfaceNum; slist.push_back(temp_slist_entry); } return qtrue; } } return qfalse; }
qboolean G2_SetRootSurface( CGhoul2Info_v &ghoul2, const int modelIndex, const char *surfaceName) { int surf; int flags; assert(modelIndex>=0&&modelIndex<ghoul2.size()); assert(ghoul2[modelIndex].currentModel); assert(ghoul2[modelIndex].currentModel->mdxm); // first find if we already have this surface in the list surf = G2_IsSurfaceLegal(ghoul2[modelIndex].currentModel, surfaceName, &flags); if (surf != -1) { ghoul2[modelIndex].mSurfaceRoot = surf; return qtrue; } assert(0); return qfalse; }
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); }
int G2_Add_Bolt(CGhoul2Info *ghlInfo, boltInfo_v &bltlist, surfaceInfo_v &slist, const char *boneName) { assert(ghlInfo && ghlInfo->mValid); model_t *mod_m = (model_t *)ghlInfo->currentModel; model_t *mod_a = (model_t *)ghlInfo->animModel; int x, surfNum = -1; mdxaSkel_t *skel; mdxaSkelOffsets_t *offsets; mdxmHierarchyOffsets_t *surfOffsets; boltInfo_t tempBolt; int flags; surfOffsets = (mdxmHierarchyOffsets_t *)((byte*)mod_m->mdxm + sizeof(mdxmHeader_t)); // first up, we'll search for that which this bolt names in all the surfaces surfNum = G2_IsSurfaceLegal((void*)mod_m, boneName, &flags); // did we find it as a surface? if (surfNum != -1) { // look through entire list - see if it's already there first for (size_t i = 0; i<bltlist.size(); i++) { // already there?? if (bltlist[i].surfaceNumber == surfNum) { // increment the usage count bltlist[i].boltUsed++; return i; } } // look through entire list - see if we can re-use one for (size_t i = 0; i<bltlist.size(); i++) { // if this surface entry has info in it, bounce over it if (bltlist[i].boneNumber == -1 && bltlist[i].surfaceNumber == -1) { // if we found an entry that had a -1 for the bone / surface number, then we hit a surface / bone slot that was empty bltlist[i].surfaceNumber = surfNum; bltlist[i].boltUsed = 1; bltlist[i].surfaceType = 0; return i; } } // ok, we didn't find an existing surface of that name, or an empty slot. Lets add an entry tempBolt.surfaceNumber = surfNum; tempBolt.boneNumber = -1; tempBolt.boltUsed = 1; tempBolt.surfaceType = 0; bltlist.push_back(tempBolt); return bltlist.size()-1; } // no, check to see if it's a bone then offsets = (mdxaSkelOffsets_t *)((byte *)mod_a->mdxa + sizeof(mdxaHeader_t)); // walk the entire list of bones in the gla file for this model and see if any match the name of the bone we want to find for (x=0; x< mod_a->mdxa->numBones; x++) { skel = (mdxaSkel_t *)((byte *)mod_a->mdxa + sizeof(mdxaHeader_t) + offsets->offsets[x]); // if name is the same, we found it if (!Q_stricmp(skel->name, boneName)) { break; } } // check to see we did actually make a match with a bone in the model if (x == mod_a->mdxa->numBones) { // didn't find it? Error //assert(0&&x == mod_a->mdxa->numBones); #ifdef _DEBUG // Com_Printf("WARNING: %s not found on skeleton\n", boneName); #endif return -1; } // look through entire list - see if it's already there first for (size_t i = 0; i<bltlist.size(); i++) { // already there?? if (bltlist[i].boneNumber == x) { // increment the usage count bltlist[i].boltUsed++; return i; } } // look through entire list - see if we can re-use it for (size_t i = 0; i<bltlist.size(); i++) { // if this bone entry has info in it, bounce over it if (bltlist[i].boneNumber == -1 && bltlist[i].surfaceNumber == -1) { // if we found an entry that had a -1 for the bonenumber, then we hit a bone slot that was empty bltlist[i].boneNumber = x; bltlist[i].boltUsed = 1; bltlist[i].surfaceType = 0; return i; } } // ok, we didn't find an existing bone of that name, or an empty slot. Lets add an entry tempBolt.boneNumber = x; tempBolt.surfaceNumber = -1; tempBolt.boltUsed = 1; tempBolt.surfaceType = 0; bltlist.push_back(tempBolt); return bltlist.size()-1; }
int G2_IsSurfaceRendered(CGhoul2Info *ghlInfo, const char *surfaceName, surfaceInfo_v &slist) { int flags = 0;//, surfFlags = 0; int surfIndex = 0; assert(ghlInfo->currentModel); assert(ghlInfo->currentModel->mdxm); if (!ghlInfo->currentModel->mdxm) { return -1; } // now travel up the skeleton to see if any of it's ancestors have a 'no descendants' turned on // find the original surface in the surface list int surfNum = G2_IsSurfaceLegal(ghlInfo->currentModel, surfaceName, &flags); if ( surfNum != -1 ) {//must be legal const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)ghlInfo->currentModel->mdxm + sizeof(mdxmHeader_t)); const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surfNum]); surfNum = surfInfo->parentIndex; // walk the surface hierarchy up until we hit the root while (surfNum != -1) { const mdxmSurface_t *parentSurf; int parentFlags; const mdxmSurfHierarchy_t *parentSurfInfo; parentSurfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surfNum]); // find the original surface in the surface list //G2 was bug, above comment was accurate, but we don't want the original flags, we want the parent flags G2_IsSurfaceLegal(ghlInfo->currentModel, parentSurfInfo->name, &parentFlags); // now see if we already have overriden this surface in the slist parentSurf = G2_FindSurface(ghlInfo, slist, parentSurfInfo->name, &surfIndex); if (parentSurf) { // set descendants value parentFlags = slist[surfIndex].offFlags; } // now we have the parent flags, lets see if any have the 'no descendants' flag set if (parentFlags & G2SURFACEFLAG_NODESCENDANTS) { flags |= G2SURFACEFLAG_OFF; break; } // set up scan of next parent surfNum = parentSurfInfo->parentIndex; } } else { return -1; } if ( flags == 0 ) {//it's not being overridden by a parent // now see if we already have overriden this surface in the slist const mdxmSurface_t *surf = G2_FindSurface(ghlInfo, slist, surfaceName, &surfIndex); if (surf) { // set descendants value flags = slist[surfIndex].offFlags; } // ok, at this point in flags we have what this surface is set to, and the index of the surface itself } return flags; }
int G2_GetSurfaceIndex(CGhoul2Info *ghlInfo, const char *surfaceName) { int flags; assert(ghlInfo->currentModel); return G2_IsSurfaceLegal(ghlInfo->currentModel, surfaceName, &flags); }