// //--------------------------------------------------------------------------- // // 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 "filesystem.h" #include "cmdlib.h" #include "model_ue1.h" #include "texturemanager.h" #include "modelrenderer.h" float unpackuvert( uint32_t n, int c ) { switch( c ) { case 0: return ((int16_t)((n&0x7ff)<<5))/128.f; case 1: return ((int16_t)(((n>>11)&0x7ff)<<5))/128.f; case 2: return ((int16_t)(((n>>22)&0x3ff)<<6))/128.f; default: return 0.f; } } bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int length ) { int lumpnum2; FString realfilename = fileSystem.GetFileFullName(lumpnum); if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 ) { realfilename.Substitute("_d.3d","_a.3d"); lumpnum2 = fileSystem.CheckNumForFullName(realfilename); mDataLump = lumpnum; mAnivLump = lumpnum2; } else { realfilename.Substitute("_a.3d","_d.3d"); lumpnum2 = fileSystem.CheckNumForFullName(realfilename); mAnivLump = lumpnum; mDataLump = lumpnum2; } return true; } void FUE1Model::LoadGeometry() { FileData lump, lump2; const char *buffer, *buffer2; lump = fileSystem.ReadFile(mDataLump); buffer = (char*)lump.GetMem(); lump2 = fileSystem.ReadFile(mAnivLump); buffer2 = (char*)lump2.GetMem(); // map structures dhead = (d3dhead*)(buffer); dpolys = (d3dpoly*)(buffer+sizeof(d3dhead)); ahead = (a3dhead*)(buffer2); // detect deus ex format if ( (ahead->framesize/dhead->numverts) == 8 ) { averts = NULL; dxverts = (dxvert*)(buffer2+sizeof(a3dhead)); } else { averts = (uint32_t*)(buffer2+sizeof(a3dhead)); dxverts = NULL; } // set counters numVerts = dhead->numverts; numFrames = ahead->numframes; numPolys = dhead->numpolys; numGroups = 0; // populate vertex arrays for ( int i=0; i= numFrames) || (frame2 >= numFrames) ) return; renderer->SetInterpolation(inter); int vsize, fsize = 0, vofs = 0; for ( int i=0; isurfaceskinIDs[ssIndex].isValid()) sskin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); 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); renderer->SetupFrame(this, vofs+frame*fsize,vofs+frame2*fsize,vsize); renderer->DrawArrays(0,vsize); vofs += vsize; } renderer->SetInterpolation(0.f); } void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer ) { if (GetVertexBuffer(renderer->GetType())) return; if ( !mDataLoaded ) LoadGeometry(); int vsize = 0; for ( int i=0; iCreateVertexBuffer(false,numFrames==1); SetVertexBuffer(renderer->GetType(), vbuf); FModelVertex *vptr = vbuf->LockVertexBuffer(vsize); int vidx = 0; for ( int i=0; iSet(V.Pos.X,V.Pos.Y,V.Pos.Z,C.X,C.Y); if ( groups[j].type&PT_Curvy ) // use facet normal { vert->SetNormal(polys[groups[j].P[k]].Normals[i].X, polys[groups[j].P[k]].Normals[i].Y, polys[groups[j].P[k]].Normals[i].Z); } else vert->SetNormal(V.Normal.X,V.Normal.Y,V.Normal.Z); } } } } vbuf->UnlockVertexBuffer(); } void FUE1Model::AddSkins( uint8_t *hitlist ) { for (int i = 0; i < numGroups; i++) { int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES; if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; } } FUE1Model::~FUE1Model() { UnloadGeometry(); }