static CRenderModel *FindQ2Model(const char *name, const char *part) { TString<MAX_QPATH> Filename; Filename.sprintf("players/%s/%s", name, part); if (!strchr(part, '.')) Filename += ".md2"; return RE_RegisterModel(Filename); }
int G2_Get_Bone_Index(CGhoul2Info *ghoul2, const char *boneName) { model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(ghoul2->mFileName)); model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); return (G2_Find_Bone(mod_a, ghoul2->mBlist, boneName)); }
// given a model, bonelist and bonename, lets pause an anim if it's playing. qboolean G2_Pause_Bone_Anim(const char *fileName, boneInfo_v &blist, const char *boneName, const int currentTime) { model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int index = G2_Find_Bone(mod_a, blist, boneName); // did we find it? if (index != -1) { // are we pausing or un pausing? if (blist[index].pauseTime) { int startFrame, endFrame, flags; float currentFrame, animSpeed; // figure out what frame we are on now G2_Get_Bone_Anim(fileName, blist, boneName, blist[index].pauseTime, ¤tFrame, &startFrame, &endFrame, &flags, &animSpeed, NULL, 0); // reset start time so we are actually on this frame right now G2_Set_Bone_Anim(fileName, blist, boneName, startFrame, endFrame, flags, animSpeed, currentTime, currentFrame, 0); // no pausing anymore blist[index].pauseTime = 0; } // ahh, just pausing, the easy bit else { blist[index].pauseTime = currentTime; } return qtrue; } assert(0); return qfalse; }
// Given a model handle, and a bone name, we want to remove this bone from the bone override list qboolean G2_Remove_Bone (const char *fileName, boneInfo_v &blist, const char *boneName) { model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int index = G2_Find_Bone(mod_a, blist, boneName); return G2_Remove_Bone_Index(blist, index); }
char *G2API_GetGLAName(CGhoul2Info_v &ghoul2, int modelIndex) { if (((int)&ghoul2) && (ghoul2.size() > modelIndex)) { model_t *mod = R_GetModelByHandle(RE_RegisterModel(ghoul2[modelIndex].mFileName)); return mod->mdxm->animName; } return NULL; }
// Given a model handle, and a bone name, we want to set angles specifically for overriding qboolean G2_Set_Bone_Angles(const char *fileName, boneInfo_v &blist, const char *boneName, const float *angles, const int flags, const Eorientations up, const Eorientations left, const Eorientations forward, qhandle_t *modelList, const int modelIndex, const int blendTime, const int currentTime) { model_t *mod_m; if (!fileName[0]) { mod_m = R_GetModelByHandle(modelList[modelIndex]); } else { mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); } model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int index = G2_Find_Bone(mod_a, blist, boneName); // did we find it? if (index != -1) { // yes, so set the angles and flags correctly blist[index].flags &= ~(BONE_ANGLES_TOTAL); blist[index].flags |= flags; blist[index].boneBlendStart = currentTime; blist[index].boneBlendTime = blendTime; #if DEBUG_PCJ OutputDebugString(va("%2d %6d (%6.2f,%6.2f,%6.2f) %d %d %d %d\n",index,currentTime,angles[0],angles[1],angles[2],up,left,forward,flags)); #endif G2_Generate_Matrix(mod_a, blist, index, angles, flags, up, left, forward); return qtrue; } // no - lets try and add this bone in index = G2_Add_Bone(mod_a, blist, boneName); // did we find a free one? if (index != -1) { // yes, so set the angles and flags correctly blist[index].flags &= ~(BONE_ANGLES_TOTAL); blist[index].flags |= flags; blist[index].boneBlendStart = currentTime; blist[index].boneBlendTime = blendTime; #if DEBUG_PCJ OutputDebugString(va("%2d %6d (%6.2f,%6.2f,%6.2f) %d %d %d %d\n",index,currentTime,angles[0],angles[1],angles[2],up,left,forward,flags)); #endif G2_Generate_Matrix(mod_a, blist, index, angles, flags, up, left, forward); return qtrue; } assert(0); // no return qfalse; }
static void Gun_Model_f(int argc, char **argv) { if (argc != 2) { gun_model = NULL; return; } gun_model = RE_RegisterModel(va("models/%s/tris.md2", argv[1])); }
char *G2API_GetGLAName(g2handle_t g2h, int modelIndex) { CGhoul2Info_v *ghoul2 = G2API_GetGhoul2Model(g2h); if (ghoul2 && (unsigned)modelIndex < ghoul2->size()) { model_t *mod = R_GetModelByHandle(RE_RegisterModel((*ghoul2)[modelIndex].mFileName)); return mod->mdxm->animName; } return NULL; }
/************************************************************************************************ * G2_GetAnimFileName * obtain the .gla filename for a model * * Input * filename of model * * Output * true if we successfully obtained a filename, false otherwise * ************************************************************************************************/ qboolean G2_GetAnimFileName(const char *fileName, char **filename) { // find the model we want model_t *mod = R_GetModelByHandle(RE_RegisterModel(fileName)); if (mod && mod->mdxm && (mod->mdxm->animName[0] != 0)) { *filename = mod->mdxm->animName; return qtrue; } return qfalse; }
//similarly, pre-cache funstuff static void PreCache_UT_Models (void) { char* dirptr; char dirlist[8192],filename[1024]; int numdirs,dirlen, i; numdirs = FS_GetFileList("models/players/funstuff/", ".md3", dirlist, 8192 ); dirptr = dirlist; for (i = 0; i < numdirs; i++, dirptr += dirlen+1) { dirlen = strlen(dirptr); strcpy(filename, "models/players/funstuff/"); strcat(filename, dirptr); RE_RegisterModel (filename); } }
// given a model, bonelist and bonename, lets stop an anim if it's playing. qboolean G2_Stop_Bone_Angles(const char *fileName, boneInfo_v &blist, const char *boneName) { model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int index = G2_Find_Bone(mod_a, blist, boneName); // did we find it? if (index != -1) { blist[index].flags &= ~(BONE_ANGLES_TOTAL); // try and remove this bone if we can return G2_Remove_Bone_Index(blist, index); } assert(0); return qfalse; }
// Given a model handle, and a bone name, we want to set angles specifically for overriding - using a matrix directly qboolean G2_Set_Bone_Angles_Matrix(const char *fileName, boneInfo_v &blist, const char *boneName, const mdxaBone_t &matrix, const int flags, qhandle_t *modelList, const int modelIndex, const int blendTime, const int currentTime) { model_t *mod_m; if (!fileName[0]) { mod_m = R_GetModelByHandle(modelList[modelIndex]); } else { mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); } model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int index = G2_Find_Bone(mod_a, blist, boneName); // did we find it? if (index != -1) { // yes, so set the angles and flags correctly blist[index].flags &= ~(BONE_ANGLES_TOTAL); blist[index].flags |= flags; memcpy(&blist[index].matrix, &matrix, sizeof(mdxaBone_t)); memcpy(&blist[index].newMatrix, &matrix, sizeof(mdxaBone_t)); return qtrue; } // no - lets try and add this bone in index = G2_Add_Bone(mod_a, blist, boneName); // did we find a free one? if (index != -1) { // yes, so set the angles and flags correctly blist[index].flags &= ~(BONE_ANGLES_TOTAL); blist[index].flags |= flags; memcpy(&blist[index].matrix, &matrix, sizeof(mdxaBone_t)); memcpy(&blist[index].newMatrix, &matrix, sizeof(mdxaBone_t)); return qtrue; } assert(0); // no return qfalse; }
char *G2API_GetSurfaceName(CGhoul2Info *ghlInfo, int surfNumber) { static char noSurface[1] = ""; model_t *mod = R_GetModelByHandle(RE_RegisterModel(ghlInfo->mFileName)); mdxmSurface_t *surf = 0; mdxmSurfHierarchy_t *surfInfo = 0; surf = (mdxmSurface_t *)G2_FindSurface((void *)mod, surfNumber, 0); if (surf) { mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)mod->mdxm + sizeof(mdxmHeader_t)); surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surf->thisSurfaceIndex]); return surfInfo->name; } return noSurface; }
/* @@@@@@@@@@@@@@@@@@@@@ RE_BeginRegistration Specifies the model that will be used as the world @@@@@@@@@@@@@@@@@@@@@ */ void RE_BeginRegistration(char *model) { char fullname[MAX_QPATH]; cvar_t *flushmap; registration_sequence++; r_oldviewcluster = -1; // force markleafs Com_sprintf(fullname, sizeof(fullname), "maps/%s.bsp", model); D_FlushCaches(); // explicitly free the old map if different // this guarantees that mod_known[0] is the world map flushmap = Cvar_Get("flushmap", "0", 0); if (strcmp(mod_known[0].name, fullname) || flushmap->value) Mod_Free(&mod_known[0]); r_worldmodel = RE_RegisterModel(fullname); R_NewMap(); }
qboolean G2_Get_Bone_Anim_Range(const char *fileName, boneInfo_v &blist, const char *boneName, int *startFrame, int *endFrame) { model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int index = G2_Find_Bone(mod_a, blist, boneName); // did we find it? if (index != -1) { // are we an animating bone? if (blist[index].flags & (BONE_ANIM_OVERRIDE_LOOP | BONE_ANIM_OVERRIDE)) { *startFrame = blist[index].startFrame; *endFrame = blist[index].endFrame; return qtrue; } } return qfalse; }
qboolean G2_IsPaused(const char *fileName, boneInfo_v &blist, const char *boneName) { model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int index = G2_Find_Bone(mod_a, blist, boneName); // did we find it? if (index != -1) { // are we paused? if (blist[index].pauseTime) { // yup. paused. return qtrue; } return qfalse; } return qfalse; }
// list all bones associated with a model void G2_List_Model_Bones(const char *fileName, int frame) { int x, i; mdxaSkel_t *skel; mdxaSkelOffsets_t *offsets; model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); // mdxaFrame_t *aframe=0; // int frameSize; mdxaHeader_t *header = mod_a->mdxa; // figure out where the offset list is offsets = (mdxaSkelOffsets_t *)((byte *)header + sizeof(mdxaHeader_t)); // frameSize = (int)( &((mdxaFrame_t *)0)->boneIndexes[ header->numBones ] ); // aframe = (mdxaFrame_t *)((byte *)header + header->ofsFrames + (frame * frameSize)); // walk each bone and list it's name for (x=0; x< mod_a->mdxa->numBones; x++) { skel = (mdxaSkel_t *)((byte *)header + sizeof(mdxaHeader_t) + offsets->offsets[x]); Com_Printf("Bone %i Name %s\n", x, skel->name); Com_Printf("X pos %f, Y pos %f, Z pos %f\n", skel->BasePoseMat.matrix[0][3], skel->BasePoseMat.matrix[1][3], skel->BasePoseMat.matrix[2][3]); // if we are in verbose mode give us more details if (r_verbose->value) { Com_Printf("Num Descendants %i\n", skel->numChildren); for (i=0; i<skel->numChildren; i++) { Com_Printf("Num Descendants %i\n", skel->numChildren); } } } }
// given a model, bone name, a bonelist, a start/end frame number, a anim speed and some anim flags, set up or modify an existing bone entry for a new set of anims qboolean G2_Set_Bone_Anim(const char *fileName, boneInfo_v &blist, const char *boneName, const int startFrame, const int endFrame, const int flags, const float animSpeed, const int currentTime, const float setFrame, const int blendTime) { model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int index = G2_Find_Bone(mod_a, blist, boneName); if (index == -1) { index = G2_Add_Bone(mod_a, blist, boneName); } if (index != -1) { return G2_Set_Bone_Anim_Index(blist,index,startFrame,endFrame,flags,animSpeed,currentTime,setFrame,blendTime); } return qfalse; }
static void TestEntities() { r_numentities = 32; memset(r_entities, 0, sizeof(r_entities)); for (int i = 0; i < r_numentities; i++) { entity_t &ent = r_entities[i]; float r = 64 * (i % 4) - (1*64+32); float f = 64 * (i / 4) - (3*64+32); VectorMA(cl.refdef.vieworg, 192, cl.v_forward, ent.pos.origin); ent.pos.origin[0] += r; ent.pos.origin[1] += f; ent.pos.axis = identAxis; // animate frames #if 0 #define FIRST_FRAME 0 #define LAST_FRAME 39 #else #define FIRST_FRAME 40 #define LAST_FRAME 45 #endif ent.frame = (cl.time + 99) / 100 % (LAST_FRAME-FIRST_FRAME+1) + FIRST_FRAME; ent.oldframe = ent.frame - 1; if (ent.oldframe < FIRST_FRAME) ent.oldframe = LAST_FRAME; ent.backlerp = 1.0f - (cl.time % 100) / 100.0f; if (ent.backlerp == 1) ent.backlerp = 0; ent.model = RE_RegisterModel("players/male/tris.md2"); ent.skin = NULL; //?? } #undef FIRST_FRAME #undef LAST_FRAME }
static CRenderModel *FindQ3Model(const char *name, const char *part) { TString<MAX_QPATH> Filename; Filename.sprintf("models/players/%s/%s.md3", name, part); return RE_RegisterModel(Filename); }
int G2API_InitGhoul2Model(g2handle_t *g2hPtr, const char *fileName, int modelIndex, qhandle_t customSkin, qhandle_t customShader, int modelFlags, int lodBias) { CGhoul2Info newModel; g2handle_t g2h = *g2hPtr; // are we actually asking for a model to be loaded. if (!(strlen(fileName))) { assert(0); return -1; } if (g2h == 0) { *g2hPtr = g2h = nextGhoul2Handle++; } CGhoul2Info_v &ghoul2 = ghoultable[RicksCrazyOnServer][g2h]; // find a free spot in the list for (CGhoul2Info_v::iterator it = ghoul2.begin(); it != ghoul2.end(); ++it) { if (it->mModelindex == -1) { // this is only valid and used on the game side. Client side ignores this it->mModelindex = modelIndex; if (maxModelIndex[RicksCrazyOnServer] < modelIndex) maxModelIndex[RicksCrazyOnServer] = modelIndex; // on the game side this is valid. On the client side it is valid only after it has been filled in by trap_G2_SetGhoul2ModelIndexes it->mModel = RE_RegisterModel(fileName); model_t *mod_m = R_GetModelByHandle(it->mModel); if (mod_m->type == MOD_BAD) { return -1; } // init what is necessary for this ghoul2 model // fau - what about remaining fields? G2_Init_Bone_List(it->mBlist); G2_Init_Bolt_List(it->mBltlist); it->mCustomShader = customShader; it->mCustomSkin = customSkin; Q_strncpyz(it->mFileName, fileName, sizeof(it->mFileName)); it->mCreationID = modelFlags; it->mLodBias = lodBias; it->mAnimFrameDefault = 0; it->mFlags = 0; it->mSkelFrameNum = -1; it->mMeshFrameNum = -1; // we aren't attached to anyone upfront it->mModelBoltLink = -1; return it - ghoul2.begin(); } } // if we got this far, then we didn't find a spare position, so lets insert a new one newModel.mModelindex = modelIndex; if (maxModelIndex[RicksCrazyOnServer] < modelIndex) maxModelIndex[RicksCrazyOnServer] = modelIndex; // on the game side this is valid. On the client side it is valid only after it has been filled in by trap_G2_SetGhoul2ModelIndexes if (customShader <= -20) { //This means the server is making the function call. And the server does not like registering models. newModel.mModel = RE_RegisterServerModel(fileName); customShader = 0; } else { newModel.mModel = RE_RegisterModel(fileName); } model_t *mod_m = R_GetModelByHandle(newModel.mModel); if (mod_m->type == MOD_BAD) { if (ghoul2.size() == 0)//very first model created {//you can't have an empty vector, so let's not give it one G2API_CleanGhoul2Models(g2hPtr); } return -1; } // init what is necessary for this ghoul2 model G2_Init_Bone_List(newModel.mBlist); G2_Init_Bolt_List(newModel.mBltlist); newModel.mCustomShader = customShader; newModel.mCustomSkin = customSkin; Q_strncpyz(newModel.mFileName, fileName, sizeof(newModel.mFileName)); newModel.mCreationID = modelFlags; newModel.mLodBias = lodBias; newModel.mAnimFrameDefault = 0; newModel.mFlags = 0; // we aren't attached to anyone upfront newModel.mModelBoltLink = -1; // insert into list. ghoul2.push_back(newModel); return ghoul2.size() - 1; }
// initialise all that needs to be on a new Ghoul II model int G2API_InitGhoul2Model(CGhoul2Info_v **ghoul2Ptr, const char *fileName, int modelIndex, qhandle_t customSkin, qhandle_t customShader, int modelFlags, int lodBias) { int model = -1; CGhoul2Info newModel; // are we actually asking for a model to be loaded. if (!(strlen(fileName))) { assert(0); return -1; } if (!(*ghoul2Ptr)) { *ghoul2Ptr = new CGhoul2Info_v; if (RicksCrazyOnServer) { OkLetsFixTheLeaksTheEasyWay[1].insert(*ghoul2Ptr); } else { OkLetsFixTheLeaksTheEasyWay[0].insert(*ghoul2Ptr); } } CGhoul2Info_v &ghoul2 = *(*ghoul2Ptr); // find a free spot in the list for (model=0; model< ghoul2.size(); model++) { if (ghoul2[model].mModelindex == -1) { // this is only valid and used on the game side. Client side ignores this ghoul2[model].mModelindex = modelIndex; // on the game side this is valid. On the client side it is valid only after it has been filled in by trap_G2_SetGhoul2ModelIndexes ghoul2[model].mModel = RE_RegisterModel((char *)fileName); model_t *mod_m = R_GetModelByHandle(ghoul2[model].mModel); if (mod_m->type == MOD_BAD) { return -1; } // init what is necessary for this ghoul2 model G2_Init_Bone_List(ghoul2[model].mBlist); G2_Init_Bolt_List(ghoul2[model].mBltlist); ghoul2[model].mCustomShader = customShader; ghoul2[model].mCustomSkin = customSkin; strcpy(ghoul2[model].mFileName, fileName); ghoul2[model].mCreationID = modelFlags; ghoul2[model].mLodBias = lodBias; ghoul2[model].mAnimFrameDefault = 0; ghoul2[model].mFlags = 0; // we aren't attached to anyone upfront ghoul2[model].mModelBoltLink = -1; return model; } } // if we got this far, then we didn't find a spare position, so lets insert a new one newModel.mModelindex = modelIndex; // on the game side this is valid. On the client side it is valid only after it has been filled in by trap_G2_SetGhoul2ModelIndexes if (customShader <= -20) { //This means the server is making the function call. And the server does not like registering models. newModel.mModel = RE_RegisterServerModel((char *)fileName); customShader = 0; } else { newModel.mModel = RE_RegisterModel((char *)fileName); } model_t *mod_m = R_GetModelByHandle(newModel.mModel); if (mod_m->type == MOD_BAD) { if (ghoul2.size() == 0)//very first model created {//you can't have an empty vector, so let's not give it one G2API_CleanGhoul2Models(ghoul2Ptr); delete *ghoul2Ptr; *ghoul2Ptr = 0; } return -1; } // init what is necessary for this ghoul2 model G2_Init_Bone_List(newModel.mBlist); G2_Init_Bolt_List(newModel.mBltlist); newModel.mCustomShader = customShader; newModel.mCustomSkin = customSkin; strcpy(newModel.mFileName, fileName); newModel.mCreationID = modelFlags; newModel.mLodBias = lodBias; newModel.mAnimFrameDefault = 0; newModel.mFlags = 0; // we aren't attached to anyone upfront newModel.mModelBoltLink = -1; // insert into list. model = ghoul2.size(); ghoul2.push_back(newModel); return model; }
// given a model, bonelist and bonename, return the current frame, startframe and endframe of the current animation // NOTE if we aren't running an animation, then qfalse is returned qboolean G2_Get_Bone_Anim(const char *fileName, boneInfo_v &blist, const char *boneName, const int currentTime, float *currentFrame, int *startFrame, int *endFrame, int *flags, float *retAnimSpeed, qhandle_t *modelList, int modelIndex) { model_t *mod_m; if (!fileName[0]) { mod_m = R_GetModelByHandle(modelList[modelIndex]); } else { mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); } model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int index = G2_Find_Bone(mod_a, blist, boneName); // did we find it? if (index != -1) { // are we an animating bone? if (blist[index].flags & (BONE_ANIM_OVERRIDE_LOOP | BONE_ANIM_OVERRIDE)) { // yes - add in animation speed to current frame float animSpeed = blist[index].animSpeed; float time = (currentTime - blist[index].startTime) / 50.0f; float mendFrame = (float)blist[index].endFrame ; // are we a paused anim? if (blist[index].pauseTime) { time = (blist[index].pauseTime - blist[index].startTime) / 50.0f; } if (time<0) { time=0; } float newFrame_g = blist[index].startFrame + (time * animSpeed); *currentFrame = newFrame_g; int animSize = blist[index].endFrame - blist[index].startFrame; // we are supposed to be animating right? if (animSize) { // did we run off the end? if (((animSpeed > 0.0f) && (newFrame_g > mendFrame-1)) || ((animSpeed < 0.0f) && (newFrame_g < mendFrame+1))) { // yep - decide what to do if (blist[index].flags & BONE_ANIM_OVERRIDE_LOOP) { // get our new animation frame back within the bounds of the animation set if (animSpeed < 0.0f) { if (newFrame_g <= mendFrame+1) { newFrame_g=mendFrame+fmod(newFrame_g-mendFrame,animSize)-animSize; } } else { if (newFrame_g >= mendFrame) { newFrame_g=mendFrame+fmod(newFrame_g-mendFrame,animSize)-animSize; } } *currentFrame = newFrame_g; } else { // nope, we ran off the end of the current anim if (blist[index].flags & BONE_ANIM_OVERRIDE_FREEZE) { if (animSpeed > 0.0f) { *currentFrame = blist[index].endFrame -1; } else { *currentFrame = blist[index].endFrame +1; } } else { *currentFrame = 0; } } } } else { *currentFrame = blist[index].startFrame; } *startFrame = blist[index].startFrame; *endFrame = blist[index].endFrame; *flags = blist[index].flags; *retAnimSpeed = animSpeed; return qtrue; } } *startFrame =0; *endFrame =1 ; *currentFrame = 0; *flags = 0; //hmmmm this used to be -1 *retAnimSpeed = 1.0f; return qfalse; }
void V_InitRenderer() { guard(V_InitRenderer); int i; if (!cl.configstrings[CS_MODELS+1][0]) return; // no map loaded SCR_SetLevelshot(); // wait a small time to let server complete initialization // allow map to be changed before initializing renderer, when loading savegames, // saved at point of changing map; this situation is possible because: // - server frame#1: // - loading savegame, will create configstrings + may be insert command string "gamemap <newmap>" // - send configstrings#1 // - server frame#2: // - exec "gamemap" command from previous frame, change map etc. // - send configstrings#2 // in some circumstances, client will receive configstrings#1 after server frame#2 - this will load // client map#1 after loading server map#2 (out-of-sync client/server maps -- fatal error) static int startTime = 0; static int serverCount = 0; if (serverCount != cl.servercount) { serverCount = cl.servercount; startTime = cls.realtime; return; } if (cls.realtime < startTime + 300) return; CL_ClearEffects(); // can use shaders ... CL_ClearTEnts(); // temp entities linked to models, which are invalid after vid_restart // let the render dll load the map char mapname[MAX_QPATH]; strcpy(mapname, cl.configstrings[CS_MODELS+1] + 5); // skip "maps/" mapname[strlen(mapname)-4] = 0; // cut off ".bsp" // compute total loading weight float totalWeight = W_MAP + W_TEXTURES + W_SKY; for (i = 1; i < MAX_MODELS && cl.configstrings[CS_MODELS+i][0]; i++) // models if (cl.configstrings[CS_MODELS+i][0] != '*') totalWeight += W_MODEL; for (i = 0; i < MAX_CLIENTS; i++) // clients if (cl.configstrings[CS_PLAYERSKINS+i][0]) totalWeight += W_CLIENT; // register models, pics, and skins float loadingFrac = 0; SCR_LoadingNotify(va("map: %s", mapname), 0); loadingFrac += W_MAP / totalWeight; RE_LoadNewWorld(); // precache status bar pics SCR_TouchPics(); CL_RegisterTEntModels(); RegisterShaders(); strcpy(cl_weaponmodels[0], "weapon.md2"); // default weapon model num_cl_weaponmodels = 1; for (i = 1; i < MAX_MODELS && cl.configstrings[CS_MODELS+i][0]; i++) { const char *name = cl.configstrings[CS_MODELS+i]; if (name[0] != '*') { SCR_LoadingNotify(name, loadingFrac); loadingFrac += W_MODEL / totalWeight; } if (name[0] == '#') { // special player weapon model if (num_cl_weaponmodels < MAX_CLIENTWEAPONMODELS) strncpy(cl_weaponmodels[num_cl_weaponmodels++], cl.configstrings[CS_MODELS+i]+1, sizeof(cl_weaponmodels[0])-1); } else { const char *mdl = cl.configstrings[CS_MODELS + i]; const char *ext = strrchr(name, '.'); // load model, but do not reload BSP file: cl.model_draw[i] = (!ext || stricmp(ext, ".bsp")) ? RE_RegisterModel(mdl) : NULL; cl.model_clip[i] = (name[0] == '*') ? CM_InlineModel(mdl) : NULL; } } SCR_LoadingNotify("textures", loadingFrac); loadingFrac += W_TEXTURES / totalWeight; for (i = 1; i < MAX_IMAGES && cl.configstrings[CS_IMAGES+i][0]; i++) cl.image_precache[i] = RE_RegisterPic(va("pics/%s", cl.configstrings[CS_IMAGES+i])); for (i = 0; i < MAX_CLIENTS; i++) { if (!cl.configstrings[CS_PLAYERSKINS+i][0]) continue; SCR_LoadingNotify(va("client %d: %s", i, cl.configstrings[CS_PLAYERSKINS+i]), loadingFrac); loadingFrac += W_CLIENT / totalWeight; CL_ParseClientinfo(i); } if (!cl.configstrings[CS_PLAYERSKINS+cl.playernum][0]) { // in a singleplayer mode, server will not send clientinfo - generate it by // ourself for correct third-person view // Com_DPrintf("Fixing CI[playernum]\n"); CL_UpdatePlayerClientInfo(); } // setup sky SCR_LoadingNotify("sky", loadingFrac); float rotate = atof(cl.configstrings[CS_SKYROTATE]); CVec3 axis; sscanf(cl.configstrings[CS_SKYAXIS], "%f %f %f", &axis[0], &axis[1], &axis[2]); RE_SetSky(cl.configstrings[CS_SKY], rotate, axis); // the renderer can now free unneeded stuff RE_FinishLoadingWorld(); Con_ClearNotify(); SCR_EndLoadingPlaque(true); cl.rendererReady = true; cl.forceViewFrame = true; // start the cd track CDAudio_Play(atoi(cl.configstrings[CS_CDTRACK]), true); unguard; }
int G2_Add_Bolt(const char *fileName, boltInfo_v &bltlist, surfaceInfo_v &slist, const char *boneName) { model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); model_t *mod_a = R_GetModelByHandle(mod_m->mdxm->animIndex); int i, 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(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(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 (int)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 (!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); return -1; } // look through entire list - see if it's already there first for(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(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 (int)bltlist.size()-1; }
int RE_InitGhoul2Model( void **ptr, const char *filename, int modelIndex, qhandle_t customSkin, qhandle_t customShader, int modelFlags, int lodBias ) { if( ptr ) { CGhoul2Info_v *g2; qhandle_t hG2, hModel; model_t *model; int k; if ( !filename || !filename[0] ) { ri.Printf( PRINT_ALL, "RE_InitGhoul2Model: NULL name\n" ); *ptr = NULL; return 0; } if ( strlen( filename ) >= MAX_QPATH ) { ri.Printf( PRINT_ALL, "Model name exceeds MAX_QPATH\n" ); *ptr = NULL; return 0; } if ( modelIndex < 0 || modelIndex > 3 ) { ri.Printf( PRINT_ALL, "Modelindex out of bounds\n" ); *ptr = NULL; return 0; } // // search the currently loaded models // for ( hG2 = 1 ; hG2 < tr.numG2Instances; hG2++ ) { g2 = tr.g2Instances[hG2]; for ( k = 0; k < 4 ; k++ ) { if ( k == modelIndex && &g2->anims[k] && !Q_stricmp( g2->anims[k].meshName, filename ) ) { //if( g2->anims[k]->ent_owner == -1 ) { // *ptr = NULL; // return 0; //} *ptr = g2; return hG2; } } } // allocate a new model_t if ( ( g2 = R_InitGhoul2Instance() ) == NULL ) { ri.Printf( PRINT_WARNING, "RE_InitGhoul2Model: R_InitGhoul2Instance() failed for '%s'\n", filename); *ptr = NULL; return 0; } hModel = RE_RegisterModel(filename); model = R_GetModelByHandle(hModel); if(hModel > 0 && model) { glmHeader_t *glm = (glmHeader_t *)model->modelData; if(glm) { g2->anims[modelIndex].meshHandle = hModel; Q_strncpyz(g2->anims[modelIndex].meshName, filename, sizeof(g2->anims[modelIndex].meshName)); g2->anims[modelIndex].animHandle = glm->animIndex; Q_strncpyz(g2->anims[modelIndex].animName, glm->animName, sizeof(g2->anims[modelIndex].animName)); } } else { *ptr = NULL; return 0; } *ptr = g2; return hG2; } return 0; }
qboolean R_LoadGLM( model_t *mod, void *buffer, int filesize, const char *mod_name ) { int i, j, lodindex, surfindex; glmHeader_t *header, *glm; glmLOD_t *lod; glmLODSurfOffset_t *lod_surf_ofs; glmSurfHierarchy_t *surfh; glmVertexTexCoord_t *vcor; glmSurface_t *surf; glmTriangle_t *tri; glmVertex_t *v; int version; int size; shader_t *sh; vec3_t tempVert; vec3_t tempNorm; //int frameSize; float zrots[3][4]; qboolean do_zrot = qfalse; 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; if( filesize < sizeof( glmHeader_t ) ) { return qfalse; } header = (glmHeader_t *)buffer; version = LittleLong( header->version ); if( version != GLM_VERSION ) { ri.Printf( PRINT_WARNING, "R_LoadGLM: %s has wrong version (%i should be %i)\n", mod_name, version, GLM_VERSION ); return qfalse; } size = LittleLong( header->ofsEnd ); if( size > filesize ) { ri.Printf( PRINT_WARNING, "R_LoadGLM: Header of %s is broken. Wrong filesize declared!\n", mod_name ); return qfalse; } mod->type = MOD_GLM; size = LittleLong(header->ofsEnd); mod->dataSize += size; //ri.Printf( PRINT_WARNING, "R_LoadGLM: %s alloc %d\n", mod_name, size ); mod->modelData = ri.Hunk_Alloc( size, h_low ); glm = (glmHeader_t *)mod->modelData; Com_Memcpy( glm, buffer, size ); LL( glm->ident ); LL( glm->animIndex ); LL( glm->numBones ); LL( glm->numLODs ); LL( glm->ofsLODs ); LL( glm->numSurfaces ); LL( glm->ofsSurfHierarchy ); if ( GLM_CheckRange( glm, glm->ofsSurfHierarchy, glm->numSurfaces, sizeof( glmSurfHierarchy_t ) ) ) { return qfalse; } // swap the surf Hierarchy! surfh = (glmSurfHierarchy_t *) ( (byte *)glm + glm->ofsSurfHierarchy ); for( surfindex = 0; surfindex < glm->numSurfaces; surfindex++ ) { Q_strlwr( surfh->name ); LL(surfh->flags); Q_strlwr( surfh->shader ); //ri.Printf( PRINT_ALL, "surf %d, name '%s' shader '%s'\n", surfindex, surfh->name, surfh->shader ); sh = R_FindShader( surfh->shader, LIGHTMAP_NONE, qtrue ); if ( sh->defaultShader ) { surfh->shaderIndex = 0; } else { LL(surfh->shaderIndex); surfh->shaderIndex = sh->index; } LL(surfh->parentIndex); LL(surfh->numChildren); for( i = 0; i < surfh->numChildren; i++ ) { LL(surfh->childIndexes[i]); } surfh = (glmSurfHierarchy_t *) ( (byte *)&surfh->childIndexes[surfh->numChildren] ); } if ( GLM_CheckRange( glm, glm->ofsLODs, glm->numLODs, sizeof( glmLOD_t ) ) ) { return qfalse; } // swap all the LOD's lod = (glmLOD_t *) ( (byte *)glm + glm->ofsLODs ); LL( lod->ofsEnd ); //ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name); //ri.Printf (PRINT_WARNING,"lod ofsEnd is 0x%08x\n", lod->ofsEnd ); for ( lodindex = 0 ; lodindex < glm->numLODs ; lodindex++ ) { lod_surf_ofs = ( glmLODSurfOffset_t *) ((byte *)lod + 4 ); for( i = 0; i < glm->numSurfaces; i++ ) { LL(lod_surf_ofs->offsets[i]); //lod_surf_ofs->offsets[i] += 4; //printf( "lod %d surf ofs %d is 0x%08x\n", lodindex, lod_surf_ofs->offsets[i] ); } // swap all the surfaces for ( i = 0 ; i < glm->numSurfaces ; i++) { surf = (glmSurface_t *) ( (byte *)lod_surf_ofs + lod_surf_ofs->offsets[i] ); LL(surf->ident); LL(surf->thisSurfaceIndex); LL(surf->ofsHeader); LL(surf->numVerts); LL(surf->ofsVerts); LL(surf->numTriangles); LL(surf->ofsTriangles); LL(surf->numBoneReferences); LL(surf->ofsBoneReferences); LL(surf->ofsEnd); if(0) ri.Printf( PRINT_ALL, "surf %d, ident %d, index %d, numverts %d, numtris %d, num bone refs %d\n", i, surf->ident, surf->thisSurfaceIndex, surf->numVerts, surf->numTriangles, surf->numBoneReferences ); // change to surface identifier surf->ident = SF_GLM; tri = (glmTriangle_t *) ( (byte *)surf + surf->ofsBoneReferences ); for( j=0; j<surf->numBoneReferences; j++ ) { LL(tri->indexes[j]); if(0) ri.Printf( PRINT_ALL, "j is %d\n", j ); if(0) ri.Printf( PRINT_ALL, "surf %d, boneref %d is %d\n", i, j, tri->indexes[j] ); } if(0) ri.Printf( PRINT_ALL, "swap the triangles!\n" ); // swap all the triangles tri = (glmTriangle_t *) ( (byte *)surf + surf->ofsTriangles ); for ( j = 0 ; j < surf->numTriangles ; j++ ) { LL(tri->indexes[0]); LL(tri->indexes[1]); LL(tri->indexes[2]); tri = (glmTriangle_t *)((byte *)tri + 12 ); } v = (glmVertex_t *) ( (byte *)surf + surf->ofsVerts); for ( j = 0 ; j < surf->numVerts ; j++ ) { v->normal[0] = LittleFloat( v->normal[0] ); v->normal[1] = LittleFloat( v->normal[1] ); v->normal[2] = LittleFloat( v->normal[2] ); v->vertCoords[0] = LittleFloat( v->vertCoords[0] ); v->vertCoords[1] = LittleFloat( v->vertCoords[1] ); v->vertCoords[2] = LittleFloat( v->vertCoords[2] ); if( do_zrot ) { VectorCopy( v->normal, tempNorm ); VectorCopy( v->vertCoords, tempVert ); Matrix34VectorRotate( zrots, tempVert, v->vertCoords ); Matrix34VectorRotate( zrots, tempNorm, v->normal ); } LL(v->uiNmWeightsAndBoneIndexes); //v->texCoords[0] = LittleFloat( v->texCoords[0] ); //v->texCoords[1] = LittleFloat( v->texCoords[1] ); /* v->numWeights = LittleLong( v->numWeights ); for ( k = 0 ; k < v->numWeights ; k++ ) { v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex ); v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight ); v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] ); v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] ); v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] ); } */ v = (glmVertex_t *)( ( byte *)v + 32 ); } vcor = (glmVertexTexCoord_t *)( ( byte *)v ); for ( j = 0 ; j < surf->numVerts ; j++ ) { vcor->texCoords[0] = LittleFloat( vcor->texCoords[0] ); vcor->texCoords[1] = LittleFloat( vcor->texCoords[1] ); vcor = (glmVertexTexCoord_t *)( ( byte *)vcor + 8 ); } } lod = (glmLOD_t *)( (byte *)lod + lod->ofsEnd ); } glm->animIndex = 0; if(0) ri.Printf( PRINT_DEVELOPER, "glm (%s) animname is '%s'\n", mod_name, glm->animName ); if( Q_strncmp( glm->animName, sDEFAULT_GLA_NAME, strlen(sDEFAULT_GLA_NAME) ) ) //if there's a difference { Q_strcat( glm->animName, MAX_QPATH, ".gla" ); //Com_DPrintf ( "glm: trying to load animfile: '%s'\n", glm->animName ); //ri.Printf( PRINT_ALL, "glm: trying to load animfile: '%s'\n", glm->animName ); glm->animIndex = RE_RegisterModel( glm->animName ); } else { glm->animIndex = 0; } return qtrue; }
qhandle_t G2API_PrecacheGhoul2Model(const char *fileName) { return RE_RegisterModel((char *)fileName); }
static void cWeapModel(int argc, char **argv) { loadingWeap->model = RE_RegisterModel(argv[1]); }