#include "basics.h" #include "model.h" #include "modeldata.h" #include "texturemanager.h" #include "hw_voxels.h" #include "gamefuncs.h" #include "tiletexture.h" #include "buildtiles.h" #include "build.h" int ModelManager::LoadModel(const char* fn) { unsigned modelid = FindModel(nullptr, fn, true); if (modelid == ~0u) return -1; // Note that the descriptor table may contain the same model multiple times! int mdid = modelDescs.Reserve(1); modelDescs.Last() = {}; modelDescs.Last().modelID = modelid; return mdid; } int ModelManager::SetMisc(int modelid, float scale, int shadeoff, float zadd, float yoffset, int flags) { if ((unsigned)modelid >= modelDescs.Size()) return -1; auto md = &modelDescs[modelid]; md->bscale = scale; md->shadeoff = shadeoff; md->zadd = zadd; md->yoffset = yoffset; md->flags = flags; return 0; } int ModelManager::DefineFrame(int modelid, const char* framename, int tilenum, int skinnum, float smoothduration, int pal) { if ((unsigned)modelid >= modelDescs.Size()) return -1; if ((uint32_t)tilenum >= MAXTILES) return -2; if (!framename) return -3; ModelTileFrame mframe; auto mdesc = &modelDescs[modelid]; auto model = Models[mdesc->modelID]; auto frm = model->FindFrame(framename, true); if (frm == FErr_NotFound) return -3; if (frm == FErr_Voxel) skinnum = 0; if (frm < 0) frm = 0; mframe.modelid = modelid; mframe.framenum = frm; mframe.skinnum = skinnum; mframe.smoothduration = smoothduration; auto key = FrameMapKey(tileGetTextureID(tilenum), pal); frameMap.Insert(key, mframe); return key; } int ModelManager::DefineAnimation(int modelid, const char* framestart, const char* frameend, int fpssc, int flags) { if ((unsigned)modelid >= modelDescs.Size()) return -1; if (!framestart) return -2; if (!frameend) return -3; auto mdesc = &modelDescs[modelid]; auto model = Models[mdesc->modelID]; auto frm = model->FindFrame(framestart, true); if (frm == FErr_NotFound) return -2; if (frm < 0) frm = 0; auto frme = model->FindFrame(frameend, true); if (frme == FErr_NotFound) return -3; if (frme < 0) frme = 0; ModelAnimation anm; anm.startframe = frm; anm.endframe = frme; anm.fpssc = fpssc; anm.flags = flags; mdesc->anims.Push(anm); return 0; } int ModelManager::DefineSkin(int modelid, const char* skinfn, int palnum, int skinnum, int surfnum, float param, float specpower, float specfactor, int flags) { if ((unsigned)modelid >= modelDescs.Size()) return -1; if (!skinfn) return -2; if ((unsigned)palnum >= (unsigned)MAXPALOOKUPS) return -3; auto mdesc = &modelDescs[modelid]; auto model = Models[mdesc->modelID]; if (model->FindFrame("", true) == FErr_Voxel) return 0; if (!model->hasSurfaces) surfnum = 0; ModelSkinDef* skdef = nullptr; for (auto& sk : mdesc->skins) { if (sk.palette == (uint8_t)palnum && skinnum == sk.skinnum && surfnum == sk.surfnum) { skdef = &sk; break; } } if (skdef == nullptr) { mdesc->skins.Reserve(1); skdef = &mdesc->skins.Last(); } skdef->palette = (uint8_t)palnum; skdef->flags = (uint8_t)flags; skdef->skinnum = skinnum; skdef->surfnum = surfnum; skdef->param = param; skdef->specpower = specpower; skdef->specfactor = specfactor; skdef->texture = TexMan.CheckForTexture(skinfn, ETextureType::Any, FTextureManager::TEXMAN_ForceLookup | FTextureManager::TEXMAN_TryAny); if (!skdef->texture.isValid()) return -2; return 0; } int ModelManager::DefineHud(int modelid, int tilex, FVector3 add, int angadd, int flags, int fov) { if ((unsigned)modelid >= modelDescs.Size()) return -1; if ((unsigned)tilex >= (unsigned)MAXTILES) return -1; auto mdesc = &modelDescs[modelid]; auto model = Models[mdesc->modelID]; // not implemented yet return 0; } int ModelManager::UndefineTile(int tile) { if ((unsigned)tile >= (unsigned)MAXTILES) return -1; // delete all entries from the map that reference this tile for (int i = 0; i < MAXPALOOKUPS; i++) { frameMap.Remove(FrameMapKey(tileGetTextureID(tile), i)); } return 0; } int ModelManager::UndefineModel(int modelid) { if ((unsigned)modelid >= modelDescs.Size()) return -1; auto mdesc = &modelDescs[modelid]; mdesc->deleted = true; mdesc->anims.Reset(); mdesc->skins.Reset(); if (modelid == (int)modelDescs.Size() - 1) modelDescs.Pop(); return 0; } #if 0 // kept as reminders for later. We still need the prioritization code in mdloadskin, the rest needs to be redone FGameTexture* mdloadskin(idmodel_t* m, int32_t number, int32_t pal, int32_t surf, bool* exact) { int32_t i; mdskinmap_t* sk, * skzero = NULL; if (m->mdnum == 2) surf = 0; if ((unsigned)pal >= (unsigned)MAXPALOOKUPS) return 0; i = -1; for (sk = m->skinmap; sk; sk = sk->next) { if (sk->palette == pal && sk->skinnum == number && sk->surfnum == surf) { if (exact) *exact = true; //Printf("Using exact match skin (pal=%d,skinnum=%d,surfnum=%d) %s\n",pal,number,surf,skinfile); return TexMan.GetGameTexture(sk->texture); } //If no match, give highest priority to number, then pal.. (Parkar's request, 02/27/2005) else if ((sk->palette == 0) && (sk->skinnum == number) && (sk->surfnum == surf) && (i < 5)) { i = 5; skzero = sk; } else if ((sk->palette == pal) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 4)) { i = 4; skzero = sk; } else if ((sk->palette == 0) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 3)) { i = 3; skzero = sk; } else if ((sk->palette == 0) && (sk->skinnum == number) && (i < 2)) { i = 2; skzero = sk; } else if ((sk->palette == pal) && (sk->skinnum == 0) && (i < 1)) { i = 1; skzero = sk; } else if ((sk->palette == 0) && (sk->skinnum == 0) && (i < 0)) { i = 0; skzero = sk; } } // Special palettes do not get replacements if (pal >= (MAXPALOOKUPS - RESERVEDPALS)) return 0; if (skzero) { //Printf("Using def skin 0,0 as fallback, pal=%d\n", pal); if (exact) *exact = false; return TexMan.GetGameTexture(skzero->texture); } else return nullptr; } void updateModelInterpolation() { // this never worked - only left as a reference to sprext stuff. omdtims = mdtims; mdtims = I_msTime(); TSpriteIterator it; while (auto actor = it.Next()) { if ((mdpause && actor->sprext.mdanimtims) || (actor->sprext.renderflags & SPREXT_NOMDANIM)) actor->sprext.mdanimtims += mdtims - omdtims; } } #endif