diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2f3cf6bb4..23cdb04bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1134,6 +1134,7 @@ set (PCH_SOURCES r_data/models/models_md3.cpp r_data/models/models_md2.cpp r_data/models/models_voxel.cpp + r_data/models/models_ue1.cpp scripting/symbols.cpp scripting/types.cpp scripting/thingdef.cpp diff --git a/src/r_data/models/models.cpp b/src/r_data/models/models.cpp index b49be91c3..20036f116 100644 --- a/src/r_data/models/models.cpp +++ b/src/r_data/models/models.cpp @@ -39,6 +39,7 @@ #include "g_levellocals.h" #include "r_utility.h" #include "r_data/models/models.h" +#include "r_data/models/models_ue1.h" #include "i_time.h" #ifdef _MSC_VER @@ -426,6 +427,10 @@ static unsigned FindModel(const char * path, const char * modelfile) { model = new FMD3Model; } + else if (!memcmp(buffer, "UMSH", 4)) + { + model = new FUE1Model; + } if (model != nullptr) { diff --git a/src/r_data/models/models_ue1.cpp b/src/r_data/models/models_ue1.cpp new file mode 100644 index 000000000..1f215cefc --- /dev/null +++ b/src/r_data/models/models_ue1.cpp @@ -0,0 +1,248 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2018 Marisa Kirisame +// 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/ +// +//-------------------------------------------------------------------------- +// + +#include "w_wad.h" +#include "cmdlib.h" +#include "r_data/models/models_ue1.h" + +double unpackuvert( uint32_t n, int c ) +{ + switch( c ) + { + case 2: + return ((int16_t)((n&0x7ff)<<5))/127.; + case 1: + return ((int16_t)(((n>>11)&0x7ff)<<5))/127.; + case 0: + return ((int16_t)(((n>>22)&0x3ff)<<6))/127.; + default: + return 0.; + } +} + +bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int length ) +{ + mLumpNum = lumpnum; + // read signature + if ( memcmp(buffer,"UMSH",4) ) + return false; + // map structures + int ofs = 4; + dhead = (d3dhead*)(buffer+ofs); + ofs += sizeof(d3dhead); + dpolys = (d3dpoly*)(buffer+ofs); + ofs += sizeof(d3dpoly)*dhead->numpolys; + ahead = (a3dhead*)(buffer+ofs); + ofs += sizeof(a3dhead); + averts = (uint32_t*)(buffer+ofs); + // set counters + numVerts = dhead->numverts; + numFrames = ahead->numframes; + numPolys = dhead->numpolys; + numGroups = 0; + uint8_t used[256] = {0}; + for ( int i=0; i= numFrames) || (frame2 >= numFrames) ) return; + renderer->SetInterpolation(inter); + int vsize, fsize = 0, vofs = 0; + for ( int i=0; isurfaceskinIDs[curMDLIndex][i].isValid() ) + sskin = TexMan(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i]); + if ( !sskin ) + { + continue; + vofs += vsize; + } + } + renderer->SetMaterial(sskin,false,translation); + mVBuf->SetupFrame(renderer,vofs+frame*fsize,vofs+frame2*fsize,vsize); + renderer->DrawArrays(0,vsize); + vofs += vsize; + } + renderer->SetInterpolation(0.f); +} + +void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer ) +{ + if ( mVBuf != NULL ) + return; + int vsize = 0; + for ( int i=0; iCreateVertexBuffer(false,numFrames==1); + FModelVertex *vptr = mVBuf->LockVertexBuffer(vsize); + int vidx = 0; + for ( int i=0; iSet(V.Pos.X,V.Pos.Y,V.Pos.Z,C.S,C.T); + vert->SetNormal(V.Normal.X,V.Normal.Y,V.Normal.Z); + } + } + } + } + mVBuf->UnlockVertexBuffer(); +} + +void FUE1Model::AddSkins( uint8_t *hitlist ) +{ + for ( int i=0; isurfaceskinIDs[curMDLIndex][i].isValid() ) + hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].GetIndex()] |= FTextureManager::HIT_Flat; +} + +FUE1Model::~FUE1Model() +{ + UnloadGeometry(); +} diff --git a/src/r_data/models/models_ue1.h b/src/r_data/models/models_ue1.h new file mode 100644 index 000000000..9637ea99d --- /dev/null +++ b/src/r_data/models/models_ue1.h @@ -0,0 +1,91 @@ +#pragma once + +#include "models.h" + +class FUE1Model : public FModel +{ +public: + bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; + int FindFrame(const char * name) override; + void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0) override; + void BuildVertexBuffer(FModelRenderer *renderer) override; + void AddSkins(uint8_t *hitlist) override; + void LoadGeometry(); + void UnloadGeometry(); + FUE1Model() + { + mLumpNum = -1; + dhead = NULL; + dpolys = NULL; + ahead = NULL; + averts = NULL; + numVerts = 0; + numFrames = 0; + numPolys = 0; + numGroups = 0; + } + ~FUE1Model(); + +private: + int mLumpNum; + + // raw data structures + struct d3dhead + { + uint16_t numpolys, numverts; + uint16_t bogusrot, bogusframe; + uint32_t bogusnorm[3]; + uint32_t fixscale; + uint32_t unused[3]; + uint8_t padding[12]; + }; + struct d3dpoly + { + uint16_t vertices[3]; + uint8_t type, color; + uint8_t uv[3][2]; + uint8_t texnum, flags; + }; + struct a3dhead + { + uint16_t numframes, framesize; + }; + d3dhead * dhead; + d3dpoly * dpolys; + a3dhead * ahead; + uint32_t * averts; + + // converted data structures + struct UE1Coord + { + float S, T; + }; + struct UE1Vector + { + float X, Y, Z; + }; + struct UE1Vertex + { + UE1Vector Pos, Normal; + }; + struct UE1Poly + { + int V[3]; + UE1Coord C[3]; + int texNum; + }; + struct UE1Group + { + TArray P; + int numPolys; + }; + + int numVerts; + int numFrames; + int numPolys; + int numGroups; + + TArray verts; + TArray polys; + TArray groups; +};