// ----------------------------------------------------------------------------------------------------------- //given an CObject and a gun number, return position in 3-space of gun //fills in gun_point int CalcGunPoint (CFixVector *vGunPoint, CObject *objP, int nGun) { CPolyModel* pm = gameData.models.polyModels [0] + objP->rType.polyObjInfo.nModel; tRobotInfo* botInfoP; CFixVector* vGunPoints, vGunPos, vRot; CFixMatrix m; int nSubModel; //submodel number Assert(objP->info.renderType == RT_POLYOBJ || objP->info.renderType == RT_MORPH); //Assert(objP->info.nId < gameData.bots.nTypes [gameStates.app.bD1Data]); botInfoP = &ROBOTINFO (objP->info.nId); if (!(vGunPoints = GetGunPoints (objP, nGun))) return 0; vGunPos = vGunPoints [nGun]; nSubModel = botInfoP->gunSubModels [nGun]; //instance up the tree for this gun while (nSubModel != 0) { m = CFixMatrix::Create (objP->rType.polyObjInfo.animAngles [nSubModel]); CFixMatrix::Transpose (m); vRot = m * vGunPos; vGunPos = vRot + pm->SubModels ().offsets [nSubModel]; nSubModel = pm->SubModels ().parents [nSubModel]; } //now instance for the entire CObject //VmVecInc (&vGunPos, gameData.models.offsets + botInfoP->nModel); *vGunPoint = *objP->View () * vGunPos; *vGunPoint += objP->info.position.vPos; return 1; }
void OglCachePolyModelTextures (int nModel) { CPolyModel* modelP = GetPolyModel (NULL, NULL, nModel, 0); if (modelP) modelP->LoadTextures (NULL); }
CPolyModel* GetPolyModel (CObject *objP, CFixVector *pos, int nModel, int flags) { CPolyModel *modelP = NULL; int bHaveAltModel, bIsDefModel; #if DBG if (nModel == nDbgModel) nDbgModel = nDbgModel; #endif if (gameStates.app.bEndLevelSequence && ((nModel == gameData.endLevel.exit.nModel) || (nModel == gameData.endLevel.exit.nDestroyedModel))) { bHaveAltModel = 0; bIsDefModel = 1; } else { bHaveAltModel = gameData.models.polyModels [2][nModel].Data () != NULL; bIsDefModel = IsDefaultModel (nModel); } #if DBG if (nModel == nDbgModel) nDbgModel = nDbgModel; #endif if ((nModel >= gameData.models.nPolyModels) && !(modelP = gameData.models.modelToPOL [nModel])) return NULL; // only render shadows for custom models and for standard models with a shadow proof alternative model if (!objP) modelP = ((gameStates.app.bAltModels && bIsDefModel && bHaveAltModel) ? gameData.models.polyModels [2] : gameData.models.polyModels [0]) + nModel; else if (!modelP) { if (!(bIsDefModel && bHaveAltModel)) { if (gameStates.app.bFixModels && (objP->info.nType == OBJ_ROBOT) && (gameStates.render.nShadowPass == 2)) return NULL; modelP = gameData.models.polyModels [0] + nModel; } else if (gameStates.render.nShadowPass != 2) { if ((gameStates.app.bAltModels || (objP->info.nType == OBJ_PLAYER)) && bHaveAltModel) modelP = gameData.models.polyModels [2] + nModel; else modelP = gameData.models.polyModels [0] + nModel; } else if (bHaveAltModel) modelP = gameData.models.polyModels [2] + nModel; else return NULL; if ((gameStates.render.nShadowPass == 2) && (objP->info.nType == OBJ_REACTOR) && !(nModel & 1)) // use the working reactor model for rendering destroyed reactors' shadows modelP--; } //check if should use simple model (depending on detail level chosen) if (!(SHOW_DYN_LIGHT || SHOW_SHADOWS) && modelP->SimplerModel () && !flags && pos) { int cnt = 1; fix depth = G3CalcPointDepth (*pos); //gets 3d depth while (modelP->SimplerModel () && (depth > cnt++ * gameData.models.nSimpleModelThresholdScale * modelP->Rad ())) modelP = gameData.models.polyModels [0] + modelP->SimplerModel () - 1; } return modelP; }
void LoadModelTextures (int nModel) { CPolyModel* modelP = gameData.models.polyModels [0] + nModel; ushort* pi = gameData.pig.tex.objBmIndexP + modelP->FirstTexture (); int j; for (int i = modelP->TextureCount (); i; i--, pi++) { j = *pi; LoadBitmap (gameData.pig.tex.objBmIndex [j].index, 0); LoadObjectEffectTextures (j); } }
int DrawPolygonObject (CObject *objP, int bDepthSort, int bForce) { fix xLight; int imSave = 0; fix xEngineGlow [2]; //element 0 is for engine glow, 1 for headlight int bBlendPolys = 0; int bBrightPolys = 0; int bGatling = 0; int bCloaked = ObjectIsCloaked (objP); int bEnergyWeapon; int i, id, bOk = 0; if (objP->info.nType == 255) return 0; id = (int) objP->info.nId; if ((id < 0) || (id == 255)) bEnergyWeapon = id = 0; else { #if 0 bGatling = ((objP->info.nType == OBJ_WEAPON) && ((id == VULCAN_ID) || (id == GAUSS_ID))); #endif bEnergyWeapon = (objP->info.nType == OBJ_WEAPON) && gameData.objs.bIsWeapon [id] && !gameData.objs.bIsMissile [id]; } #if SHADOWS if (!bForce && FAST_SHADOWS && !gameOpts->render.shadows.bSoft && (gameStates.render.nShadowPass == 3)) return 1; #endif if (gameStates.render.bBuildModels) xLight = I2X (1); else { xLight = CalcObjectLight (objP, xEngineGlow); if ((bCloaked || bEnergyWeapon) && bDepthSort && (gameStates.render.nShadowPass != 2)) { transparencyRenderer.AddObject (objP); return 1; } if (DrawHiresObject (objP, xLight, xEngineGlow)) return 1; gameStates.render.bBrightObject = bEnergyWeapon; gameOpts->render.bDepthSort = -gameOpts->render.bDepthSort; imSave = gameStates.render.nInterpolationMethod; if (bLinearTMapPolyObjs) gameStates.render.nInterpolationMethod = 1; } if (objP->rType.polyObjInfo.nTexOverride != -1) { #if DBG CPolyModel* pm = gameData.models.polyModels [0] + objP->rType.polyObjInfo.nModel; #endif tBitmapIndex bm = gameData.pig.tex.bmIndex [0][objP->rType.polyObjInfo.nTexOverride], bmiP [MAX_MODEL_TEXTURES]; #if DBG Assert (pm->TextureCount () <= 12); #endif for (i = 0; i < MAX_MODEL_TEXTURES; i++) //fill whole array, in case simple model needs more bmiP [i] = bm; bOk = DrawPolyModel (objP, &objP->info.position.vPos, &objP->info.position.mOrient, reinterpret_cast<CAngleVector*> ( &objP->rType.polyObjInfo.animAngles), objP->rType.polyObjInfo.nModel, objP->rType.polyObjInfo.nSubObjFlags, xLight, xEngineGlow, bmiP, NULL); } else { if (bCloaked) { if (objP->info.nType == OBJ_PLAYER) bOk = DrawCloakedObject (objP, xLight, xEngineGlow, gameData.multiplayer.players [id].cloakTime, gameData.multiplayer.players [id].cloakTime + CLOAK_TIME_MAX); else if (objP->info.nType == OBJ_ROBOT) { if (!ROBOTINFO (id).bossFlag) bOk = DrawCloakedObject (objP, xLight, xEngineGlow, gameData.time.xGame - I2X (10), gameData.time.xGame + I2X (10)); else if (0 <= (i = gameData.bosses.Find (objP->Index ()))) bOk = DrawCloakedObject (objP, xLight, xEngineGlow, gameData.bosses [i].m_nCloakStartTime, gameData.bosses [i].m_nCloakEndTime); } } else { tBitmapIndex *bmiAltTex = (objP->rType.polyObjInfo.nAltTextures > 0) ? mpTextureIndex [objP->rType.polyObjInfo.nAltTextures - 1] : NULL; // Snipers get bright when they fire. if (!gameStates.render.bBuildModels) { if ((objP->info.nType == OBJ_ROBOT) && (gameData.ai.localInfo [objP->Index ()].nextPrimaryFire < I2X (1) / 8) && (objP->cType.aiInfo.behavior == AIB_SNIPE)) xLight = 2 * xLight + I2X (1); bBlendPolys = bEnergyWeapon && (gameData.weapons.info [id].nInnerModel > -1); bBrightPolys = bGatling || (bBlendPolys && WI_energy_usage (id)); if (bEnergyWeapon) { if (gameOpts->legacy.bRender) gameStates.render.grAlpha = GrAlpha (FADE_LEVELS - 2); else ogl.BlendFunc (GL_ONE, GL_ONE); } if (bBlendPolys) { #if 0 fix xDistToEye = CFixVector::Dist(gameData.objs.viewerP->info.position.vPos, objP->info.position.vPos); if (xDistToEye < gameData.models.nSimpleModelThresholdScale * I2X (2)) #endif bOk = DrawPolyModel (objP, &objP->info.position.vPos, &objP->info.position.mOrient, objP->rType.polyObjInfo.animAngles, gameData.weapons.info [id].nInnerModel, objP->rType.polyObjInfo.nSubObjFlags, bBrightPolys ? I2X (1) : xLight, xEngineGlow, bmiAltTex, NULL); } if (bEnergyWeapon) gameStates.render.grAlpha = GrAlpha (4 * FADE_LEVELS / 5); else if (!bBlendPolys) gameStates.render.grAlpha = 1.0f; } bOk = DrawPolyModel (objP, &objP->info.position.vPos, &objP->info.position.mOrient, objP->rType.polyObjInfo.animAngles, objP->rType.polyObjInfo.nModel, objP->rType.polyObjInfo.nSubObjFlags, (bGatling || bBrightPolys) ? I2X (1) : xLight, xEngineGlow, bmiAltTex, (bGatling || bEnergyWeapon) ? gameData.weapons.color + id : NULL); if (!gameStates.render.bBuildModels) { if (!gameOpts->legacy.bRender) ogl.BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gameStates.render.grAlpha = 1.0f; } } } if (!gameStates.render.bBuildModels) { gameStates.render.nInterpolationMethod = imSave; gameStates.render.bBrightObject = 0; gameOpts->render.bDepthSort = -gameOpts->render.bDepthSort; } return bOk; }
//draw a polygon model int DrawPolyModel ( CObject* objP, CFixVector* pos, CFixMatrix* orient, CAngleVector* animAngles, int nModel, int flags, fix light, fix* glowValues, tBitmapIndex altTextures [], tRgbaColorf* colorP) { CPolyModel* modelP; int nTextures, bHires = 0; if ((gameStates.render.nShadowPass == 2) && !ObjectHasShadow (objP)) return 1; if (!(modelP = GetPolyModel (objP, pos, nModel, flags))) { if (!flags && (gameStates.render.nShadowPass != 2) && HaveHiresModel (nModel)) bHires = 1; else return gameStates.render.nShadowPass == 2; } if (gameStates.render.nShadowPass == 2) { if (!bHires) { G3SetModelPoints (gameData.models.polyModelPoints.Buffer ()); G3DrawPolyModelShadow (objP, modelP->Data (), animAngles, nModel); } return 1; } #if 1//def _DEBUG if (nModel == nDbgModel) nDbgModel = nDbgModel; #endif nTextures = bHires ? 0 : modelP->LoadTextures (altTextures); gameStates.ogl.bUseTransform = 1; G3SetModelPoints (gameData.models.polyModelPoints.Buffer ()); gameData.render.vertP = gameData.models.fPolyModelVerts.Buffer (); if (!flags) { //draw entire CObject if (gameStates.app.bNostalgia || !G3RenderModel (objP, nModel, -1, modelP, gameData.models.textures, animAngles, NULL, light, glowValues, colorP)) { if (bHires) { gameStates.ogl.bUseTransform = 0; return 0; } if (objP && (objP->info.nType == OBJ_POWERUP)) { if ((objP->info.nId == POW_SMARTMINE) || (objP->info.nId == POW_PROXMINE)) gameData.models.vScale.Set (I2X (2), I2X (2), I2X (2)); else gameData.models.vScale.Set (I2X (3) / 2, I2X (3) / 2, I2X (3) / 2); } gameStates.ogl.bUseTransform = (gameStates.app.bEndLevelSequence < EL_OUTSIDE) && !(SHOW_DYN_LIGHT && (gameOpts->ogl.bObjLighting || gameOpts->ogl.bLightObjects)); transformation.Begin (*pos, *orient); G3DrawPolyModel (objP, modelP->Data (), gameData.models.textures, animAngles, NULL, light, glowValues, colorP, NULL, nModel); transformation.End (); } } else { CFixVector vOffset; for (int i = 0; flags > 0; flags >>= 1, i++) { if ((flags & 1) && (i < modelP->ModelCount ())) { //if submodel, rotate around its center point, not pivot point vOffset = CFixVector::Avg (modelP->SubModels ().mins [i], modelP->SubModels ().maxs [i]); vOffset.Neg (); if (!G3RenderModel (objP, nModel, i, modelP, gameData.models.textures, animAngles, &vOffset, light, glowValues, colorP)) { if (bHires) { gameStates.ogl.bUseTransform = 0; return 0; } #if DBG G3RenderModel (objP, nModel, i, modelP, gameData.models.textures, animAngles, &vOffset, light, glowValues, colorP); #endif transformation.Begin (vOffset); G3DrawPolyModel (objP, modelP->Data () + modelP->SubModels ().ptrs [i], gameData.models.textures, animAngles, NULL, light, glowValues, colorP, NULL, nModel); transformation.End (); } } } } gameStates.ogl.bUseTransform = 0; gameData.render.vertP = NULL; #if 0 { g3sPoint p0, p1; transformation.Transform (&p0.p3_vec, &objP->info.position.vPos); VmVecSub (&p1.p3_vec, &objP->info.position.vPos, &objP->mType.physInfo.velocity); transformation.Transform (&p1.p3_vec, &p1.p3_vec); glLineWidth (20); glDisable (GL_TEXTURE_2D); glBegin (GL_LINES); glColor4d (1.0, 0.5, 0.0, 0.3); OglVertex3x (p0.p3_vec [X], p0.p3_vec [Y], p0.p3_vec [Z]); glColor4d (1.0, 0.5, 0.0, 0.1); OglVertex3x (p1.p3_vec [X], p1.p3_vec [Y], p1.p3_vec [Z]); glEnd (); glLineWidth (1); } #endif return 1; }
void BMReadGameDataD1 (CFile& cf) { int h, i, j, v10DataOffset; #if 1 tD1WallClip w; D1_tmap_info t; //D1Robot_info r; #endif tWallClip *pw; tTexMapInfo *pt; tRobotInfo *pr; CPolyModel model; ubyte tmpSounds [D1_MAX_SOUNDS]; v10DataOffset = cf.ReadInt (); cf.Read (&gameData.pig.tex.nTextures [1], sizeof (int), 1); j = (gameData.pig.tex.nTextures [1] == 70) ? 70 : D1_MAX_TEXTURES; /*---*/PrintLog (" Loading %d texture indices\n", j); //cf.Read (gameData.pig.tex.bmIndex [1], sizeof (tBitmapIndex), D1_MAX_TEXTURES); ReadBitmapIndices (gameData.pig.tex.bmIndex [1], D1_MAX_TEXTURES, cf); BuildTextureIndex (1, D1_MAX_TEXTURES); /*---*/PrintLog (" Loading %d texture descriptions\n", j); for (i = 0, pt = &gameData.pig.tex.tMapInfo [1][0]; i < j; i++, pt++) { #if DBG cf.Read (t.filename, sizeof (t.filename), 1); #else cf.Seek (sizeof (t.filename), SEEK_CUR); #endif pt->flags = (ubyte) cf.ReadByte (); pt->lighting = cf.ReadFix (); pt->damage = cf.ReadFix (); pt->nEffectClip = cf.ReadInt (); pt->slide_u = pt->slide_v = 0; pt->destroyed = -1; } cf.Read (Sounds [1], sizeof (ubyte), D1_MAX_SOUNDS); cf.Read (AltSounds [1], sizeof (ubyte), D1_MAX_SOUNDS); /*---*/PrintLog (" Initializing %d sounds\n", D1_MAX_SOUNDS); if (gameOpts->sound.bUseD1Sounds) { memcpy (Sounds [1] + D1_MAX_SOUNDS, Sounds [0] + D1_MAX_SOUNDS, MAX_SOUNDS - D1_MAX_SOUNDS); memcpy (AltSounds [1] + D1_MAX_SOUNDS, AltSounds [0] + D1_MAX_SOUNDS, MAX_SOUNDS - D1_MAX_SOUNDS); } else { memcpy (Sounds [1], Sounds [0], MAX_SOUNDS); memcpy (AltSounds [1], AltSounds [0], MAX_SOUNDS); } for (i = 0; i < D1_MAX_SOUNDS; i++) { if (Sounds [1][i] == 255) Sounds [1][i] = Sounds [0][i]; if (AltSounds [1][i] == 255) AltSounds [1][i] = AltSounds [0][i]; } gameData.eff.nClips [1] = cf.ReadInt (); /*---*/PrintLog (" Loading %d animation clips\n", gameData.eff.nClips [1]); ReadVideoClips (gameData.eff.vClips [1], D1_VCLIP_MAXNUM, cf); gameData.eff.nEffects [1] = cf.ReadInt (); /*---*/PrintLog (" Loading %d animation descriptions\n", gameData.eff.nClips [1]); ReadEffectClips (gameData.eff.effects [1], D1_MAX_EFFECTS, cf); gameData.walls.nAnims [1] = cf.ReadInt (); /*---*/PrintLog (" Loading %d CWall animations\n", gameData.walls.nAnims [1]); for (i = 0, pw = &gameData.walls.anims [1][0]; i < D1_MAX_WALL_ANIMS; i++, pw++) { //cf.Read (&w, sizeof (w), 1); pw->xTotalTime = cf.ReadFix (); pw->nFrameCount = cf.ReadShort (); for (j = 0; j < D1_MAX_CLIP_FRAMES; j++) pw->frames [j] = cf.ReadShort (); pw->openSound = cf.ReadShort (); pw->closeSound = cf.ReadShort (); pw->flags = cf.ReadShort (); cf.Read (pw->filename, sizeof (w.filename), 1); pw->pad = (char) cf.ReadByte (); } cf.Read (&gameData.bots.nTypes [1], sizeof (int), 1); /*---*/PrintLog (" Loading %d robot descriptions\n", gameData.bots.nTypes [1]); gameData.bots.info [1] = gameData.bots.info [0]; if (!gameOpts->sound.bUseD1Sounds) return; for (i = 0, pr = &gameData.bots.info [1][0]; i < D1_MAX_ROBOT_TYPES; i++, pr++) { //cf.Read (&r, sizeof (r), 1); cf.Seek ( sizeof (int) * 3 + (sizeof (CFixVector) + sizeof (ubyte)) * MAX_GUNS + sizeof (short) * 5 + sizeof (sbyte) * 7 + sizeof (fix) * 4 + sizeof (fix) * 7 * NDL + sizeof (sbyte) * 2 * NDL, SEEK_CUR); pr->seeSound = (ubyte) cf.ReadByte (); pr->attackSound = (ubyte) cf.ReadByte (); pr->clawSound = (ubyte) cf.ReadByte (); cf.Seek ( JOINTLIST_SIZE * (MAX_GUNS + 1) * N_ANIM_STATES + sizeof (int), SEEK_CUR); pr->always_0xabcd = 0xabcd; } cf.Seek ( sizeof (int) + JOINTPOS_SIZE * D1_MAX_ROBOT_JOINTS + sizeof (int) + D1_WEAPON_INFO_SIZE * D1_MAX_WEAPON_TYPES + sizeof (int) + POWERUP_TYPE_INFO_SIZE * MAX_POWERUP_TYPES_D1, SEEK_CUR); i = cf.ReadInt (); /*---*/PrintLog (" Acquiring model data size of %d polymodels\n", i); for (h = 0; i; i--) { cf.Seek (MODEL_DATA_SIZE_OFFS, SEEK_CUR); model.SetDataSize (cf.ReadInt ()); h += model.DataSize (); cf.Seek (POLYMODEL_SIZE - MODEL_DATA_SIZE_OFFS - sizeof (int), SEEK_CUR); } cf.Seek ( h + sizeof (tBitmapIndex) * D1_MAX_GAUGE_BMS + sizeof (int) * 2 * D1_MAX_POLYGON_MODELS + sizeof (tBitmapIndex) * D1_MAX_OBJ_BITMAPS + sizeof (ushort) * D1_MAX_OBJ_BITMAPS + PLAYER_SHIP_SIZE + sizeof (int) + sizeof (tBitmapIndex) * D1_N_COCKPIT_BITMAPS, SEEK_CUR); /*---*/PrintLog (" Loading sound data\n", i); cf.Read (tmpSounds, sizeof (ubyte), D1_MAX_SOUNDS); //for (i = 0, pr = &gameData.bots.info [1][0]; i < gameData.bots.nTypes [1]; i++, pr++) pr = gameData.bots.info [1] + 17; /*---*/PrintLog (" Initializing sound data\n", i); for (i = 0; i < D1_MAX_SOUNDS; i++) { if (Sounds [1][i] == tmpSounds [pr->seeSound]) pr->seeSound = i; if (Sounds [1][i] == tmpSounds [pr->attackSound]) pr->attackSound = i; if (Sounds [1][i] == tmpSounds [pr->clawSound]) pr->clawSound = i; } pr = gameData.bots.info [1] + 23; for (i = 0; i < D1_MAX_SOUNDS; i++) { if (Sounds [1][i] == tmpSounds [pr->seeSound]) pr->seeSound = i; if (Sounds [1][i] == tmpSounds [pr->attackSound]) pr->attackSound = i; if (Sounds [1][i] == tmpSounds [pr->clawSound]) pr->clawSound = i; } cf.Read (tmpSounds, sizeof (ubyte), D1_MAX_SOUNDS); // for (i = 0, pr = &gameData.bots.info [1][0]; i < gameData.bots.nTypes [1]; i++, pr++) { pr = gameData.bots.info [1] + 17; for (i = 0; i < D1_MAX_SOUNDS; i++) { if (AltSounds [1][i] == tmpSounds [pr->seeSound]) pr->seeSound = i; if (AltSounds [1][i] == tmpSounds [pr->attackSound]) pr->attackSound = i; if (AltSounds [1][i] == tmpSounds [pr->clawSound]) pr->clawSound = i; } pr = gameData.bots.info [1] + 23; for (i = 0; i < D1_MAX_SOUNDS; i++) { if (AltSounds [1][i] == tmpSounds [pr->seeSound]) pr->seeSound = i; if (AltSounds [1][i] == tmpSounds [pr->attackSound]) pr->attackSound = i; if (AltSounds [1][i] == tmpSounds [pr->clawSound]) pr->clawSound = i; } #if 0 cf.Seek (v10DataOffset, SEEK_SET); i = cf.ReadInt (); j = cf.ReadInt (); cf.Seek (i * sizeof (tD1TextureHeader), SEEK_CUR); gameStates.app.bD1Mission = 1; for (i = 0; i < j; i++) { cf.Read (&gameData.pig.sound.sounds [1][i].szName, sizeof (gameData.pig.sound.sounds [1][i].szName), 1); cf.Seek (sizeof (tD1SoundHeader) - sizeof (gameData.pig.sound.sounds [1][i].szName), SEEK_CUR); } #endif }