From e5249f302afa80db44f0f685d2ea1e45b52d21c1 Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Sat, 16 Jun 2018 19:24:08 +0200 Subject: [PATCH] UE1: Clean up and restructure model class. UE1: Add support for Deus Ex format vertex data. UE1: Group triangles by skin index AND type/flags (preparation for per-surface render style support). UE1: Add handling of Weapon Triangle (preparation for model attachment support). UE1: Support flat shaded triangle flag. --- src/r_data/models/models_ue1.cpp | 178 ++++++++++++++++++++----------- src/r_data/models/models_ue1.h | 35 +++++- 2 files changed, 145 insertions(+), 68 deletions(-) diff --git a/src/r_data/models/models_ue1.cpp b/src/r_data/models/models_ue1.cpp index 682b5c37e..2b763077f 100644 --- a/src/r_data/models/models_ue1.cpp +++ b/src/r_data/models/models_ue1.cpp @@ -28,11 +28,11 @@ float unpackuvert( uint32_t n, int c ) { switch( c ) { - case 2: + case 0: return ((int16_t)((n&0x7ff)<<5))/128.f; case 1: return ((int16_t)(((n>>11)&0x7ff)<<5))/128.f; - case 0: + case 2: return ((int16_t)(((n>>22)&0x3ff)<<6))/128.f; default: return 0.f; @@ -41,66 +41,74 @@ float unpackuvert( uint32_t n, int c ) bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int length ) { - mLumpNum = lumpnum; int lumpnum2; - FMemLump lump2; - const char *buffer2; FString realfilename = Wads.GetLumpFullName(lumpnum); if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 ) { realfilename.Substitute("_d.3d","_a.3d"); lumpnum2 = Wads.CheckNumForFullName(realfilename); - lump2 = Wads.ReadLump(lumpnum2); - buffer2 = (char*)lump2.GetMem(); - // map structures - dhead = (d3dhead*)(buffer); - dpolys = (d3dpoly*)(buffer+sizeof(d3dhead)); - ahead = (a3dhead*)(buffer2); - averts = (uint32_t*)(buffer2+sizeof(a3dhead)); + mDataLump = lumpnum; + mAnivLump = lumpnum2; } else { realfilename.Substitute("_a.3d","_d.3d"); lumpnum2 = Wads.CheckNumForFullName(realfilename); - lump2 = Wads.ReadLump(lumpnum2); - buffer2 = (char*)lump2.GetMem(); - // map structures - dhead = (d3dhead*)(buffer2); - dpolys = (d3dpoly*)(buffer2+sizeof(d3dhead)); - ahead = (a3dhead*)(buffer); - averts = (uint32_t*)(buffer+sizeof(a3dhead)); + mAnivLump = lumpnum; + mDataLump = lumpnum2; } - // set counters - numVerts = dhead->numverts; - numFrames = ahead->numframes; - numPolys = dhead->numpolys; - numGroups = 0; - groupIndices.Reset(); - uint8_t used[256] = {0}; - for ( int i=0; iframesize/dhead->numverts) == 8 ) + { + averts = NULL; + dxverts = (dxvert*)(buffer2+sizeof(a3dhead)); + } + else + { + averts = (uint32_t*)(buffer2+sizeof(a3dhead)); + dxverts = NULL; + } + weaponPoly = -1; + // set counters + numVerts = dhead->numverts; + numFrames = ahead->numframes; + numPolys = dhead->numpolys; + numGroups = 0; // populate vertex arrays for ( int i=0; isurfaceskinIDs[curMDLIndex][i].isValid() ) - sskin = TexMan(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i]); + if ( curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() ) + sskin = TexMan(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum]); if ( !sskin ) { vofs += vsize; continue; } } + // TODO: Handle per-group render styles and other flags once functions for it are implemented + // Future note: poly renderstyles should always be enforced unless the actor itself has a style other than Normal renderer->SetMaterial(sskin,false,translation); GetVertexBuffer(renderer)->SetupFrame(renderer,vofs+frame*fsize,vofs+frame2*fsize,vsize); renderer->DrawArrays(0,vsize); @@ -207,6 +251,8 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer ) { if (GetVertexBuffer(renderer)) return; + if ( !mDataLoaded ) + LoadGeometry(); int vsize = 0; for ( int i=0; iSet(V.Pos.X,V.Pos.Y,V.Pos.Z,C.X,C.Y); - vert->SetNormal(V.Normal.X,V.Normal.Y,V.Normal.Z); + if ( groups[j].type&PT_Curvy ) // use facet normal + { + vert->SetNormal(polys[groups[j].P[k]].Normal.X, + polys[groups[j].P[k]].Normal.Y, + polys[groups[j].P[k]].Normal.Z); + } + else vert->SetNormal(V.Normal.X,V.Normal.Y,V.Normal.Z); } } } @@ -238,8 +290,8 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer ) void FUE1Model::AddSkins( uint8_t *hitlist ) { for ( int i=0; isurfaceskinIDs[curMDLIndex][i].isValid() ) - hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].GetIndex()] |= FTextureManager::HIT_Flat; + if ( curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() ) + hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].GetIndex()] |= FTextureManager::HIT_Flat; } FUE1Model::~FUE1Model() diff --git a/src/r_data/models/models_ue1.h b/src/r_data/models/models_ue1.h index dc6209fa2..fb67758f7 100644 --- a/src/r_data/models/models_ue1.h +++ b/src/r_data/models/models_ue1.h @@ -5,6 +5,23 @@ class FUE1Model : public FModel { public: + enum EPolyType + { + PT_Normal = 0, // normal renderstyle + PT_TwoSided = 1, // like normal, but don't cull backfaces + PT_Translucent = 2, // additive blending + PT_Masked = 3, // draw with alpha testing + PT_Modulated = 4, // overlay-like blending (rgb values below 128 darken, 128 is unchanged, and above 128 lighten) + // types mask + PT_Type = 7, + // flags + PT_WeaponTriangle = 0x08, // this poly is used for positioning a weapon attachment and should not be drawn + PT_Unlit = 0x10, // this poly is fullbright + PT_Curvy = 0x20, // this poly uses the facet normal + PT_EnvironmentMap = 0x40, // vertex UVs are remapped to their view-space X and Z normals, fake cubemap look + PT_NoSmooth = 0x80 // this poly forcibly uses nearest filtering + }; + 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; @@ -14,7 +31,9 @@ public: void UnloadGeometry(); FUE1Model() { - mLumpNum = -1; + mDataLump = -1; + mAnivLump = -1; + mDataLoaded = false; dhead = NULL; dpolys = NULL; ahead = NULL; @@ -27,7 +46,8 @@ public: ~FUE1Model(); private: - int mLumpNum; + int mDataLump, mAnivLump; + bool mDataLoaded; // raw data structures struct d3dhead @@ -54,6 +74,11 @@ private: d3dpoly * dpolys; a3dhead * ahead; uint32_t * averts; + struct dxvert + { + int16_t x, y, z, pad; + }; + dxvert * dxverts; // converted data structures struct UE1Vertex @@ -64,21 +89,21 @@ private: { int V[3]; FVector2 C[3]; - int texNum; + FVector3 Normal; }; struct UE1Group { TArray P; - int numPolys; + int numPolys, texNum, type; }; int numVerts; int numFrames; int numPolys; int numGroups; + int weaponPoly; // for future model attachment support, unused for now TArray verts; TArray polys; TArray groups; - TArray groupIndices; };