diff --git a/LEGO1/tgl/d3drm/group.cpp b/LEGO1/tgl/d3drm/group.cpp index f676dd7c..f2b1f3bc 100644 --- a/LEGO1/tgl/d3drm/group.cpp +++ b/LEGO1/tgl/d3drm/group.cpp @@ -97,8 +97,7 @@ Result GroupImpl::Add(const Mesh* pMesh) Result GroupImpl::Remove(const Unk* pUnk) { const UnkImpl* pUnkImpl = static_cast(pUnk); - // TODO: Incorrect structure - return ResultVal(m_data->DeleteVisual((IDirect3DRMMesh*) pUnkImpl->ImplementationData())); + return ResultVal(m_data->DeleteVisual(pUnkImpl->ImplementationData())); } // FUNCTION: LEGO1 0x100a3480 diff --git a/LEGO1/tgl/d3drm/impl.h b/LEGO1/tgl/d3drm/impl.h index e66aca74..cc6e99c4 100644 --- a/LEGO1/tgl/d3drm/impl.h +++ b/LEGO1/tgl/d3drm/impl.h @@ -285,12 +285,15 @@ class MeshImpl : public Mesh { D3DRMGROUPINDEX groupIndex; }; - inline MeshData* ImplementationData() const { return m_data; } + typedef MeshData* MeshDataType; + + inline const MeshDataType& ImplementationData() const { return m_data; } + inline MeshDataType& ImplementationData() { return m_data; } friend class RendererImpl; private: - MeshData* m_data; + MeshDataType m_data; }; // VTABLE: LEGO1 0x100dba68 @@ -349,7 +352,7 @@ class UnkImpl : public Unk { void* ImplementationDataPtr() override; // vtable+0x08 - Tgl::Mesh* CreateMesh( + Mesh* CreateMesh( unsigned long faceCount, unsigned long vertexCount, float (*pPositions)[3], @@ -357,7 +360,7 @@ class UnkImpl : public Unk { float (*pTextureCoordinates)[2], unsigned long (*pFaceIndices)[3], unsigned long (*pTextureIndices)[3], - Tgl::ShadingModel shadingModel + ShadingModel shadingModel ) override; Result GetBoundingBox(float min[3], float max[3]) override; @@ -369,6 +372,18 @@ class UnkImpl : public Unk { friend class RendererImpl; private: + inline Result CreateMeshImpl( + MeshImpl* mesh, + unsigned long faceCount, + unsigned long vertexCount, + float (*pPositions)[3], + float (*pNormals)[3], + float (*pTextureCoordinates)[2], + unsigned long (*pFaceIndices)[3], + unsigned long (*pTextureIndices)[3], + ShadingModel shadingModel + ); + IDirect3DRMMesh* m_data; }; diff --git a/LEGO1/tgl/d3drm/unk.cpp b/LEGO1/tgl/d3drm/unk.cpp index eb73eb00..3e2053fa 100644 --- a/LEGO1/tgl/d3drm/unk.cpp +++ b/LEGO1/tgl/d3drm/unk.cpp @@ -11,8 +11,8 @@ void* UnkImpl::ImplementationDataPtr() return reinterpret_cast(&m_data); } -// STUB: LEGO1 0x100a3840 -Tgl::Mesh* UnkImpl::CreateMesh( +// FUNCTION: LEGO1 0x100a3840 +Mesh* UnkImpl::CreateMesh( unsigned long faceCount, unsigned long vertexCount, float (*pPositions)[3], @@ -20,10 +20,144 @@ Tgl::Mesh* UnkImpl::CreateMesh( float (*pTextureCoordinates)[2], unsigned long (*pFaceIndices)[3], unsigned long (*pTextureIndices)[3], - Tgl::ShadingModel shadingModel + ShadingModel shadingModel ) { - return NULL; + MeshImpl* mesh = new MeshImpl(); + if (CreateMeshImpl( + mesh, + faceCount, + vertexCount, + pPositions, + pNormals, + pTextureCoordinates, + pFaceIndices, + pTextureIndices, + shadingModel + ) == Error) { + delete mesh; + mesh = NULL; + } + + return mesh; +} + +inline Result MeshSetTextureMappingMode(MeshImpl::MeshData* pMesh, TextureMappingMode mode) +{ + if (mode == PerspectiveCorrect) { + return ResultVal(pMesh->groupMesh->SetGroupMapping(pMesh->groupIndex, D3DRMMAP_PERSPCORRECT)); + } + else { + return ResultVal(pMesh->groupMesh->SetGroupMapping(pMesh->groupIndex, 0)); + } +} + +inline Result CreateMesh( + IDirect3DRMMesh* pD3DRM, + unsigned long faceCount, + unsigned long vertexCount, + float (*pPositions)[3], + float (*pNormals)[3], + float (*pTextureCoordinates)[2], + unsigned long (*pFaceIndices)[3], + unsigned long (*pTextureIndices)[3], + ShadingModel shadingModel, + MeshImpl::MeshDataType& rpMesh +) +{ + unsigned long* faceIndices = (unsigned long*) pFaceIndices; + D3DRMGROUPINDEX groupIndex = 0; + int count = faceCount * 3; + int index = 0; + + unsigned int* fData = new unsigned int[count]; + + D3DRMVERTEX* vertices = new D3DRMVERTEX[vertexCount]; + memset(vertices, 0, sizeof(*vertices) * vertexCount); + + rpMesh = new MeshImpl::MeshData; + rpMesh->groupMesh = pD3DRM; + + for (int i = 0; i < count; i++) { + if (*((unsigned char*) &faceIndices[i] + 3) & 0x80) { + unsigned long j = *(unsigned short*) &faceIndices[i]; + vertices[index].position.x = pPositions[j][0]; + vertices[index].position.y = pPositions[j][1]; + vertices[index].position.z = pPositions[j][2]; + j = *((unsigned short*) &faceIndices[i] + 1) & MAXSHORT; + vertices[index].normal.x = pNormals[j][0]; + vertices[index].normal.y = pNormals[j][1]; + vertices[index].normal.z = pNormals[j][2]; + + if (pTextureIndices != NULL && pTextureCoordinates != NULL) { + j = ((unsigned long*) pTextureIndices)[i]; + vertices[index].tu = pTextureCoordinates[j][0]; + vertices[index].tv = pTextureCoordinates[j][1]; + } + + fData[i] = index; + index++; + } + else { + fData[i] = *(unsigned short*) &faceIndices[i]; + } + } + + Result result; + result = ResultVal(pD3DRM->AddGroup(vertexCount, faceCount, 3, fData, &groupIndex)); + + if (Succeeded(result)) { + rpMesh->groupIndex = groupIndex; + result = ResultVal(pD3DRM->SetVertices(groupIndex, 0, vertexCount, vertices)); + } + + if (!Succeeded(result)) { + delete rpMesh->groupMesh; + rpMesh->groupMesh = NULL; + } + else { + result = MeshSetTextureMappingMode(rpMesh, PerspectiveCorrect); + } + + if (fData != NULL) { + delete[] fData; + } + + if (vertices != NULL) { + delete[] vertices; + } + + if (!Succeeded(result)) { + delete rpMesh; + } + + return result; +} + +inline Result UnkImpl::CreateMeshImpl( + MeshImpl* mesh, + unsigned long faceCount, + unsigned long vertexCount, + float (*pPositions)[3], + float (*pNormals)[3], + float (*pTextureCoordinates)[2], + unsigned long (*pFaceIndices)[3], + unsigned long (*pTextureIndices)[3], + ShadingModel shadingModel +) +{ + return ::CreateMesh( + m_data, + faceCount, + vertexCount, + pPositions, + pNormals, + pTextureCoordinates, + pFaceIndices, + pTextureIndices, + shadingModel, + mesh->ImplementationData() + ); } // FUNCTION: LEGO1 0x100a3ae0 diff --git a/LEGO1/tgl/tgl.h b/LEGO1/tgl/tgl.h index 2cd4d6f7..46df4d72 100644 --- a/LEGO1/tgl/tgl.h +++ b/LEGO1/tgl/tgl.h @@ -269,6 +269,9 @@ class Light : public Object { // VTABLE: LEGO1 0x100dbbb0 class Mesh : public Object { public: + // SYNTHETIC: LEGO1 0x100a3e10 + // Tgl::Mesh::~Mesh + virtual Result SetColor(float r, float g, float b, float a) = 0; virtual Result SetTexture(const Texture*) = 0; virtual Result GetTexture(Texture*&) = 0; @@ -317,7 +320,7 @@ class Group : public Object { // VTABLE: LEGO1 0x100dbb30 class Unk : public Object { public: - virtual Tgl::Mesh* CreateMesh( + virtual Mesh* CreateMesh( unsigned long faceCount, unsigned long vertexCount, float (*pPositions)[3], @@ -325,7 +328,7 @@ class Unk : public Object { float (*pTextureCoordinates)[2], unsigned long (*pFaceIndices)[3], unsigned long (*pTextureIndices)[3], - Tgl::ShadingModel shadingModel + ShadingModel shadingModel ) = 0; virtual Result GetBoundingBox(float min[3], float max[3]) = 0; virtual Unk* Clone() = 0;