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; }
/* ================= ServerLoadMDXM - load a Ghoul 2 Mesh file ================= */ qboolean ServerLoadMDXM( model_t *mod, void *buffer, const char *mod_name, qboolean &bAlreadyCached ) { int i,l, j; mdxmHeader_t *pinmodel, *mdxm; mdxmLOD_t *lod; mdxmSurface_t *surf; int version; int size; //shader_t *sh; mdxmSurfHierarchy_t *surfInfo; #ifdef Q3_BIG_ENDIAN int k; mdxmTriangle_t *tri; mdxmVertex_t *v; int *boneRef; mdxmLODSurfOffset_t *indexes; mdxmVertexTexCoord_t *pTexCoords; mdxmHierarchyOffsets_t *surfIndexes; #endif pinmodel= (mdxmHeader_t *)buffer; // // read some fields from the binary, but only LittleLong() them when we know this wasn't an already-cached model... // version = (pinmodel->version); size = (pinmodel->ofsEnd); if (!bAlreadyCached) { LL(version); LL(size); } if (version != MDXM_VERSION) { return qfalse; } mod->type = MOD_MDXM; mod->dataSize += size; qboolean bAlreadyFound = qfalse; mdxm = mod->mdxm = (mdxmHeader_t*) //Hunk_Alloc( size ); RE_RegisterServerModels_Malloc(size, buffer, mod_name, &bAlreadyFound, TAG_MODEL_GLM); assert(bAlreadyCached == bAlreadyFound); // I should probably eliminate 'bAlreadyFound', but wtf? if (!bAlreadyFound) { // horrible new hackery, if !bAlreadyFound then we've just done a tag-morph, so we need to set the // bool reference passed into this function to true, to tell the caller NOT to do an ri->FS_Freefile since // we've hijacked that memory block... // // Aaaargh. Kill me now... // bAlreadyCached = qtrue; assert( mdxm == buffer ); // memcpy( mdxm, buffer, size ); // and don't do this now, since it's the same thing LL(mdxm->ident); LL(mdxm->version); LL(mdxm->numBones); LL(mdxm->numLODs); LL(mdxm->ofsLODs); LL(mdxm->numSurfaces); LL(mdxm->ofsSurfHierarchy); LL(mdxm->ofsEnd); } // first up, go load in the animation file we need that has the skeletal animation info for this model mdxm->animIndex = RE_RegisterServerModel(va ("%s.gla",mdxm->animName)); if (!mdxm->animIndex) { return qfalse; } mod->numLods = mdxm->numLODs -1 ; //copy this up to the model for ease of use - it wil get inced after this. if (bAlreadyFound) { return qtrue; // All done. Stop, go no further, do not LittleLong(), do not pass Go... } surfInfo = (mdxmSurfHierarchy_t *)( (byte *)mdxm + mdxm->ofsSurfHierarchy); #ifdef Q3_BIG_ENDIAN surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)mdxm + sizeof(mdxmHeader_t)); #endif for ( i = 0 ; i < mdxm->numSurfaces ; i++) { LL(surfInfo->numChildren); LL(surfInfo->parentIndex); // do all the children indexs for (j=0; j<surfInfo->numChildren; j++) { LL(surfInfo->childIndexes[j]); } // We will not be using shaders on the server. //sh = 0; // insert it in the surface list surfInfo->shaderIndex = 0; RE_RegisterModels_StoreShaderRequest(mod_name, &surfInfo->shader[0], &surfInfo->shaderIndex); #ifdef Q3_BIG_ENDIAN // swap the surface offset LL(surfIndexes->offsets[i]); assert(surfInfo == (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[i])); #endif // find the next surface surfInfo = (mdxmSurfHierarchy_t *)( (byte *)surfInfo + (intptr_t)( &((mdxmSurfHierarchy_t *)0)->childIndexes[ surfInfo->numChildren ] )); } // swap all the LOD's (we need to do the middle part of this even for intel, because of shader reg and err-check) lod = (mdxmLOD_t *) ( (byte *)mdxm + mdxm->ofsLODs ); for ( l = 0 ; l < mdxm->numLODs ; l++) { int triCount = 0; LL(lod->ofsEnd); // swap all the surfaces surf = (mdxmSurface_t *) ( (byte *)lod + sizeof (mdxmLOD_t) + (mdxm->numSurfaces * sizeof(mdxmLODSurfOffset_t)) ); for ( i = 0 ; i < mdxm->numSurfaces ; i++) { 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); triCount += surf->numTriangles; if ( surf->numVerts > SHADER_MAX_VERTEXES ) { return qfalse; } if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { return qfalse; } // change to surface identifier surf->ident = SF_MDX; // register the shaders #ifdef Q3_BIG_ENDIAN // swap the LOD offset indexes = (mdxmLODSurfOffset_t *)((byte *)lod + sizeof(mdxmLOD_t)); LL(indexes->offsets[surf->thisSurfaceIndex]); // do all the bone reference data boneRef = (int *) ( (byte *)surf + surf->ofsBoneReferences ); for ( j = 0 ; j < surf->numBoneReferences ; j++ ) { LL(boneRef[j]); } // swap all the triangles tri = (mdxmTriangle_t *) ( (byte *)surf + surf->ofsTriangles ); for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { LL(tri->indexes[0]); LL(tri->indexes[1]); LL(tri->indexes[2]); } // swap all the vertexes v = (mdxmVertex_t *) ( (byte *)surf + surf->ofsVerts ); pTexCoords = (mdxmVertexTexCoord_t *) &v[surf->numVerts]; for ( j = 0 ; j < surf->numVerts ; j++ ) { LF(v->normal[0]); LF(v->normal[1]); LF(v->normal[2]); LF(v->vertCoords[0]); LF(v->vertCoords[1]); LF(v->vertCoords[2]); LF(pTexCoords[j].texCoords[0]); LF(pTexCoords[j].texCoords[1]); LL(v->uiNmWeightsAndBoneIndexes); v++; } #endif // find the next surface surf = (mdxmSurface_t *)( (byte *)surf + surf->ofsEnd ); } // find the next LOD lod = (mdxmLOD_t *)( (byte *)lod + lod->ofsEnd ); } return qtrue; }