#include #include #include "res/tex.h" #include "Renderer.h" #include "TransparencyRenderer.h" #include "ModelRData.h" #include "terrain/Model.h" CModelRData::CModelRData(CModel* model) : m_Model(model), m_Vertices(0), m_Normals(0), m_Indices(0), m_VB(0) { assert(model); // build all data now Build(); } CModelRData::~CModelRData() { } void CModelRData::Build() { BuildVertices(); BuildIndices(); } void CModelRData::BuildIndices() { CModelDef* mdef=m_Model->GetModelDef(); // allocate indices if we haven't got any already if (!m_Indices) { m_Indices=new u16[mdef->GetNumFaces()*3]; } // build indices u32 indices=0; SModelFace* faces=mdef->GetFaces(); for (int j=0; jGetNumFaces(); j++) { SModelFace& face=faces[j]; m_Indices[indices++]=face.m_Verts[0]; m_Indices[indices++]=face.m_Verts[1]; m_Indices[indices++]=face.m_Verts[2]; } } inline int clamp(int x,int min,int max) { if (xmax) return max; else return x; } static SColor4ub ConvertColor(const RGBColor& src) { SColor4ub result; result.R=clamp(int(src.X*255),0,255); result.G=clamp(int(src.Y*255),0,255); result.B=clamp(int(src.Z*255),0,255); result.A=0xff; return result; } static CVector3D SkinPoint(const SModelVertex& vertex,const CMatrix3D* matrices) { CVector3D result(0,0,0),tmp; for (u32 i=0;vertex.m_Blend.m_Bone[i]!=0xff && iGetModelDef(); // allocate vertices if we haven't got any already if (!m_Vertices) { m_Vertices=new SVertex[mdef->GetNumVertices()]; m_Normals=new CVector3D[mdef->GetNumVertices()]; } // build vertices u32 numVertices=mdef->GetNumVertices(); SModelVertex* vertices=mdef->GetVertices(); if (m_Model->GetBoneMatrices()) { // boned model - calculate skinned vertex positions/normals for (uint j=0; jGetBoneMatrices()); m_Normals[j]=SkinNormal(vertices[j],m_Model->GetInvBoneMatrices()); } } else { // just copy regular positions for (uint j=0; jGetNumVertices()*sizeof(SVertex),0,mdef->GetNumBones() ? GL_DYNAMIC_DRAW_ARB : GL_STATIC_DRAW_ARB); } glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VB); glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,0,mdef->GetNumVertices()*sizeof(SVertex),m_Vertices); } } void CModelRData::RenderStreams(u32 streamflags,const CMatrix3D& transform,bool transparentPass) { // ignore transparent passes if (!transparentPass && g_Renderer.IsTextureTransparent(m_Model->GetTexture())) { return; } CModelDef* mdldef=(CModelDef*) m_Model->GetModelDef(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); CMatrix3D tmp; glMultMatrixf(&transform._11); if (streamflags & STREAM_UV0) g_Renderer.SetTexture(0,m_Model->GetTexture(),GL_CLAMP_TO_EDGE); u8* base; if (g_Renderer.m_Caps.m_VBO) { glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VB); base=0; } else { base=(u8*) &m_Vertices[0]; } // set vertex pointers u32 stride=sizeof(SVertex); glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Position)); if (streamflags & STREAM_COLOR) glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SVertex,m_Color)); if (streamflags & STREAM_UV0) glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SVertex,m_UVs)); // render the lot u32 numFaces=mdldef->GetNumFaces(); glDrawElements(GL_TRIANGLES,numFaces*3,GL_UNSIGNED_SHORT,m_Indices); // bump stats g_Renderer.m_Stats.m_DrawCalls++; if (transparentPass) { g_Renderer.m_Stats.m_TransparentTris+=numFaces; } else { g_Renderer.m_Stats.m_ModelTris+=numFaces; } glPopMatrix(); } void CModelRData::Update() { if (m_UpdateFlags!=0) { // renderdata changed : rebuild necessary portions if (m_UpdateFlags & RENDERDATA_UPDATE_VERTICES) { BuildVertices(); } if (m_UpdateFlags & RENDERDATA_UPDATE_INDICES) { BuildIndices(); } m_UpdateFlags=0; } } typedef std::pair IntFloatPair; static std::vector IndexSorter; struct SortFacesByDist { bool operator()(const IntFloatPair& lhs,const IntFloatPair& rhs) { return lhs.second>rhs.second ? true : false; } }; float CModelRData::BackToFrontIndexSort(CMatrix3D& objToCam) { float mindist=1.0e30f; CVector3D osvtx,csvtx; CModelDef* mdldef=(CModelDef*) m_Model->GetModelDef(); SModelVertex* vtxs=mdldef->GetVertices(); u32 numFaces=mdldef->GetNumFaces(); SModelFace* faces=mdldef->GetFaces(); IndexSorter.reserve(numFaces); SModelFace* facePtr=faces; u32 i; for (i=0;im_Verts[0]].m_Coords; osvtx+=vtxs[facePtr->m_Verts[1]].m_Coords; osvtx+=vtxs[facePtr->m_Verts[2]].m_Coords; osvtx*=1.0f/3.0f; csvtx=objToCam.Transform(osvtx); float distsqrd=SQR(csvtx.X)+SQR(csvtx.Y)+SQR(csvtx.Z); if (distsqrd