diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9ad52a7bd..18acfc036 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -783,7 +783,6 @@ set( FASTMATH_SOURCES rendering/hwrenderer/scene/hw_walls.cpp rendering/hwrenderer/scene/hw_walls_vertex.cpp rendering/hwrenderer/scene/hw_weapon.cpp - r_data/models/models.cpp common/utility/matrix.cpp ) @@ -1007,6 +1006,8 @@ set (PCH_SOURCES r_data/models/models_voxel.cpp r_data/models/models_ue1.cpp r_data/models/models_obj.cpp + r_data/models/models.cpp + r_data/models/model.cpp scripting/vmiterators.cpp scripting/vmthunks.cpp scripting/vmthunks_actors.cpp diff --git a/src/r_data/models/model.cpp b/src/r_data/models/model.cpp new file mode 100644 index 000000000..8c5ce7a80 --- /dev/null +++ b/src/r_data/models/model.cpp @@ -0,0 +1,236 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2005-2016 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// +/* +** gl_models.cpp +** +** General model handling code +** +**/ + +#include "filesystem.h" +#include "cmdlib.h" +#include "sc_man.h" +#include "m_crc32.h" +#include "printf.h" +#include "r_data/models/models.h" +#include "r_data/models/model_ue1.h" +#include "r_data/models/model_obj.h" +#include "r_data/models/model_md2.h" +#include "r_data/models/model_md3.h" +#include "r_data/models/model_kvx.h" +#include "i_time.h" +#include "texturemanager.h" +#include "modelrenderer.h" + + +TDeletingArray Models; +TArray SpriteModelFrames; + + +///////////////////////////////////////////////////////////////////////////// + +void FlushModels() +{ + for (int i = Models.Size() - 1; i >= 0; i--) + { + Models[i]->DestroyVertexBuffer(); + } +} + +///////////////////////////////////////////////////////////////////////////// + +FModel::FModel() +{ + for (int i = 0; i < NumModelRendererTypes; i++) + mVBuf[i] = nullptr; +} + +FModel::~FModel() +{ + DestroyVertexBuffer(); +} + +void FModel::DestroyVertexBuffer() +{ + for (int i = 0; i < NumModelRendererTypes; i++) + { + delete mVBuf[i]; + mVBuf[i] = nullptr; + } +} + +//=========================================================================== +// +// FindGFXFile +// +//=========================================================================== + +static int FindGFXFile(FString & fn) +{ + int lump = fileSystem.CheckNumForFullName(fn); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below. + if (lump != -1) return lump; + + int best = -1; + int dot = fn.LastIndexOf('.'); + int slash = fn.LastIndexOf('/'); + if (dot > slash) fn.Truncate(dot); + + static const char * extensions[] = { ".png", ".jpg", ".tga", ".pcx", nullptr }; + + for (const char ** extp=extensions; *extp; extp++) + { + int lump = fileSystem.CheckNumForFullName(fn + *extp); + if (lump >= best) best = lump; + } + return best; +} + + +//=========================================================================== +// +// LoadSkin +// +//=========================================================================== + +FTextureID LoadSkin(const char * path, const char * fn) +{ + FString buffer; + + buffer.Format("%s%s", path, fn); + + int texlump = FindGFXFile(buffer); + const char * const texname = texlump < 0 ? fn : fileSystem.GetFileFullName(texlump); + return TexMan.CheckForTexture(texname, ETextureType::Any, FTextureManager::TEXMAN_TryAny); +} + +//=========================================================================== +// +// ModelFrameHash +// +//=========================================================================== + +int ModelFrameHash(FSpriteModelFrame * smf) +{ + const uint32_t *table = GetCRCTable (); + uint32_t hash = 0xffffffff; + + const char * s = (const char *)(&smf->type); // this uses type, sprite and frame for hashing + const char * se= (const char *)(&smf->hashnext); + + for (; smFileName.CompareNoCase(fullname)) return i; + } + + int len = fileSystem.FileLength(lump); + FileData lumpd = fileSystem.ReadFile(lump); + char * buffer = (char*)lumpd.GetMem(); + + if ( (size_t)fullname.LastIndexOf("_d.3d") == fullname.Len()-5 ) + { + FString anivfile = fullname.GetChars(); + anivfile.Substitute("_d.3d","_a.3d"); + if ( fileSystem.CheckNumForFullName(anivfile) > 0 ) + { + model = new FUE1Model; + } + } + else if ( (size_t)fullname.LastIndexOf("_a.3d") == fullname.Len()-5 ) + { + FString datafile = fullname.GetChars(); + datafile.Substitute("_a.3d","_d.3d"); + if ( fileSystem.CheckNumForFullName(datafile) > 0 ) + { + model = new FUE1Model; + } + } + else if ( (size_t)fullname.LastIndexOf(".obj") == fullname.Len() - 4 ) + { + model = new FOBJModel; + } + else if (!memcmp(buffer, "DMDM", 4)) + { + model = new FDMDModel; + } + else if (!memcmp(buffer, "IDP2", 4)) + { + model = new FMD2Model; + } + else if (!memcmp(buffer, "IDP3", 4)) + { + model = new FMD3Model; + } + + if (model != nullptr) + { + if (!model->Load(path, lump, buffer, len)) + { + delete model; + return -1; + } + } + else + { + // try loading as a voxel + FVoxel *voxel = R_LoadKVX(lump); + if (voxel != nullptr) + { + model = new FVoxelModel(voxel, true); + } + else + { + Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars()); + return -1; + } + } + // The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized + model->mFileName = fullname; + return Models.Push(model); +} + diff --git a/src/r_data/models/model.h b/src/r_data/models/model.h index 1daf7c8c6..a8e14d2e2 100644 --- a/src/r_data/models/model.h +++ b/src/r_data/models/model.h @@ -7,10 +7,12 @@ class FModelRenderer; class FGameTexture; class IModelVertexBuffer; class FModel; +struct FSpriteModelFrame; FTextureID LoadSkin(const char* path, const char* fn); void FlushModels(); extern TDeletingArray Models; +extern TArray SpriteModelFrames; #define MAX_MODELS_PER_FRAME 4 #define MD3_MAX_SURFACES 32 @@ -75,3 +77,6 @@ private: IModelVertexBuffer *mVBuf[NumModelRendererTypes]; }; +int ModelFrameHash(FSpriteModelFrame* smf); +unsigned FindModel(const char* path, const char* modelfile); + diff --git a/src/r_data/models/model_md2.h b/src/r_data/models/model_md2.h index 163631532..c04445535 100644 --- a/src/r_data/models/model_md2.h +++ b/src/r_data/models/model_md2.h @@ -3,6 +3,7 @@ #define MD2_MAGIC 0x32504449 #define DMD_MAGIC 0x4D444D44 +#define MAX_LODS 4 class FDMDModel : public FModel { diff --git a/src/r_data/models/models.cpp b/src/r_data/models/models.cpp index 918af38fb..7e8b963a8 100644 --- a/src/r_data/models/models.cpp +++ b/src/r_data/models/models.cpp @@ -39,11 +39,7 @@ #include "g_levellocals.h" #include "r_utility.h" #include "r_data/models/models.h" -#include "r_data/models/model_ue1.h" -#include "r_data/models/model_obj.h" -#include "r_data/models/model_md2.h" -#include "r_data/models/model_md3.h" -#include "r_data/models/model_kvx.h" +#include "model_kvx.h" #include "i_time.h" #include "texturemanager.h" #include "modelrenderer.h" @@ -59,8 +55,6 @@ EXTERN_CVAR (Bool, r_drawvoxels) extern TDeletingArray Voxels; extern TDeletingArray VoxelDefs; -TDeletingArray Models; - void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame* smf, const FState* curState, const int curTics, const PClass* ti, int translation); @@ -290,198 +284,10 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr } } -///////////////////////////////////////////////////////////////////////////// -void FlushModels() -{ - for (int i = Models.Size() - 1; i >= 0; i--) - { - Models[i]->DestroyVertexBuffer(); - } -} - -///////////////////////////////////////////////////////////////////////////// - -FModel::FModel() -{ - for (int i = 0; i < NumModelRendererTypes; i++) - mVBuf[i] = nullptr; -} - -FModel::~FModel() -{ - DestroyVertexBuffer(); -} - -void FModel::DestroyVertexBuffer() -{ - for (int i = 0; i < NumModelRendererTypes; i++) - { - delete mVBuf[i]; - mVBuf[i] = nullptr; - } -} - -static TArray SpriteModelFrames; static TArray SpriteModelHash; //TArray StateModelFrames; -//=========================================================================== -// -// FindGFXFile -// -//=========================================================================== - -static int FindGFXFile(FString & fn) -{ - int lump = fileSystem.CheckNumForFullName(fn); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below. - if (lump != -1) return lump; - - int best = -1; - int dot = fn.LastIndexOf('.'); - int slash = fn.LastIndexOf('/'); - if (dot > slash) fn.Truncate(dot); - - static const char * extensions[] = { ".png", ".jpg", ".tga", ".pcx", nullptr }; - - for (const char ** extp=extensions; *extp; extp++) - { - int lump = fileSystem.CheckNumForFullName(fn + *extp); - if (lump >= best) best = lump; - } - return best; -} - - -//=========================================================================== -// -// LoadSkin -// -//=========================================================================== - -FTextureID LoadSkin(const char * path, const char * fn) -{ - FString buffer; - - buffer.Format("%s%s", path, fn); - - int texlump = FindGFXFile(buffer); - const char * const texname = texlump < 0 ? fn : fileSystem.GetFileFullName(texlump); - return TexMan.CheckForTexture(texname, ETextureType::Any, FTextureManager::TEXMAN_TryAny); -} - -//=========================================================================== -// -// ModelFrameHash -// -//=========================================================================== - -static int ModelFrameHash(FSpriteModelFrame * smf) -{ - const uint32_t *table = GetCRCTable (); - uint32_t hash = 0xffffffff; - - const char * s = (const char *)(&smf->type); // this uses type, sprite and frame for hashing - const char * se= (const char *)(&smf->hashnext); - - for (; smFileName.CompareNoCase(fullname)) return i; - } - - int len = fileSystem.FileLength(lump); - FileData lumpd = fileSystem.ReadFile(lump); - char * buffer = (char*)lumpd.GetMem(); - - if ( (size_t)fullname.LastIndexOf("_d.3d") == fullname.Len()-5 ) - { - FString anivfile = fullname.GetChars(); - anivfile.Substitute("_d.3d","_a.3d"); - if ( fileSystem.CheckNumForFullName(anivfile) > 0 ) - { - model = new FUE1Model; - } - } - else if ( (size_t)fullname.LastIndexOf("_a.3d") == fullname.Len()-5 ) - { - FString datafile = fullname.GetChars(); - datafile.Substitute("_a.3d","_d.3d"); - if ( fileSystem.CheckNumForFullName(datafile) > 0 ) - { - model = new FUE1Model; - } - } - else if ( (size_t)fullname.LastIndexOf(".obj") == fullname.Len() - 4 ) - { - model = new FOBJModel; - } - else if (!memcmp(buffer, "DMDM", 4)) - { - model = new FDMDModel; - } - else if (!memcmp(buffer, "IDP2", 4)) - { - model = new FMD2Model; - } - else if (!memcmp(buffer, "IDP3", 4)) - { - model = new FMD3Model; - } - - if (model != nullptr) - { - if (!model->Load(path, lump, buffer, len)) - { - delete model; - return -1; - } - } - else - { - // try loading as a voxel - FVoxel *voxel = R_LoadKVX(lump); - if (voxel != nullptr) - { - model = new FVoxelModel(voxel, true); - } - else - { - Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars()); - return -1; - } - } - // The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized - model->mFileName = fullname; - return Models.Push(model); -} - //=========================================================================== // // InitModels