diff --git a/CMakeLists.txt b/CMakeLists.txt index 7371bb69..3d6890a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,9 +94,9 @@ add_library(tglrl STATIC LEGO1/tgl/d3drm/group.cpp LEGO1/tgl/d3drm/light.cpp LEGO1/tgl/d3drm/mesh.cpp + LEGO1/tgl/d3drm/meshbuilder.cpp LEGO1/tgl/d3drm/renderer.cpp LEGO1/tgl/d3drm/texture.cpp - LEGO1/tgl/d3drm/unk.cpp LEGO1/tgl/d3drm/view.cpp ) register_lego1_target(tglrl) diff --git a/LEGO1/lego/sources/roi/legolod.cpp b/LEGO1/lego/sources/roi/legolod.cpp index f14e206a..ee1006ac 100644 --- a/LEGO1/lego/sources/roi/legolod.cpp +++ b/LEGO1/lego/sources/roi/legolod.cpp @@ -72,7 +72,7 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text return SUCCESS; } - m_unk0x04 = p_renderer->CreateUnk(); + m_meshBuilder = p_renderer->CreateMeshBuilder(); if (p_storage->Read(&m_numMeshes, sizeof(m_numMeshes)) != SUCCESS) { goto done; @@ -188,7 +188,7 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text meshUnd2++; } - m_meshes[meshIndex].m_tglMesh = m_unk0x04->CreateMesh( + m_meshes[meshIndex].m_tglMesh = m_meshBuilder->CreateMesh( numPolys & MAXWORD, numVertices & MAXWORD, vertices, diff --git a/LEGO1/tgl/d3drm/group.cpp b/LEGO1/tgl/d3drm/group.cpp index f676dd7c..74c988f8 100644 --- a/LEGO1/tgl/d3drm/group.cpp +++ b/LEGO1/tgl/d3drm/group.cpp @@ -94,11 +94,10 @@ Result GroupImpl::Add(const Mesh* pMesh) } // FUNCTION: LEGO1 0x100a3450 -Result GroupImpl::Remove(const Unk* pUnk) +Result GroupImpl::Remove(const MeshBuilder* pMeshBuilder) { - const UnkImpl* pUnkImpl = static_cast(pUnk); - // TODO: Incorrect structure - return ResultVal(m_data->DeleteVisual((IDirect3DRMMesh*) pUnkImpl->ImplementationData())); + const MeshBuilderImpl* pMeshBuilderImpl = static_cast(pMeshBuilder); + return ResultVal(m_data->DeleteVisual(pMeshBuilderImpl->ImplementationData())); } // FUNCTION: LEGO1 0x100a3480 diff --git a/LEGO1/tgl/d3drm/impl.h b/LEGO1/tgl/d3drm/impl.h index e66aca74..6fcce72f 100644 --- a/LEGO1/tgl/d3drm/impl.h +++ b/LEGO1/tgl/d3drm/impl.h @@ -34,7 +34,7 @@ class CameraImpl; class GroupImpl; class MeshImpl; class TextureImpl; -class UnkImpl; +class MeshBuilderImpl; // VTABLE: LEGO1 0x100db910 class RendererImpl : public Renderer { @@ -62,7 +62,7 @@ public: Group* CreateGroup(const Group* pParent) override; // vtable+0x20 - Unk* CreateUnk() override; + MeshBuilder* CreateMeshBuilder() override; Texture* CreateTexture( int width, int height, @@ -273,24 +273,27 @@ public: // vtable+0x10 Result GetTexture(Texture*&) override; - Result SetTextureMappingMode(ProjectionType) override; + Result SetTextureMappingMode(TextureMappingMode) override; Result SetShadingModel(ShadingModel) override; - Mesh* DeepClone(Unk*) override; + Mesh* DeepClone(MeshBuilder*) override; // vtable+0x20 - Mesh* ShallowClone(Unk*) override; + Mesh* ShallowClone(MeshBuilder*) override; struct MeshData { IDirect3DRMMesh* groupMesh; 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 @@ -320,7 +323,7 @@ public: // vtable+0x20 Result Add(const Mesh*) override; Result Remove(const Group*) override; - Result Remove(const Unk*) override; + Result Remove(const MeshBuilder*) override; Result RemoveAll() override; // vtable+0x30 @@ -335,10 +338,10 @@ private: }; // VTABLE: LEGO1 0x100dbb18 -class UnkImpl : public Unk { +class MeshBuilderImpl : public MeshBuilder { public: - UnkImpl() : m_data(0) {} - ~UnkImpl() override + MeshBuilderImpl() : m_data(0) {} + ~MeshBuilderImpl() override { if (m_data) { m_data->Release(); @@ -349,7 +352,7 @@ public: void* ImplementationDataPtr() override; // vtable+0x08 - Tgl::Mesh* CreateMesh( + Mesh* CreateMesh( unsigned long faceCount, unsigned long vertexCount, float (*pPositions)[3], @@ -357,18 +360,30 @@ public: 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; // vtable+0x10 - Unk* Clone() override; + MeshBuilder* Clone() override; inline IDirect3DRMMesh* ImplementationData() const { return m_data; } friend class RendererImpl; private: + inline Result CreateMeshImpl( + MeshImpl* pMeshImpl, + 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; }; @@ -514,7 +529,7 @@ inline D3DRMMATRIX4D* Translate(FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DR // TglImpl::LightImpl::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100a2720 -// TglImpl::UnkImpl::`scalar deleting destructor' +// TglImpl::MeshBuilderImpl::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100a2800 // TglImpl::TextureImpl::`scalar deleting destructor' diff --git a/LEGO1/tgl/d3drm/mesh.cpp b/LEGO1/tgl/d3drm/mesh.cpp index ceaf7079..9c3f32b4 100644 --- a/LEGO1/tgl/d3drm/mesh.cpp +++ b/LEGO1/tgl/d3drm/mesh.cpp @@ -38,9 +38,9 @@ Result MeshImpl::SetTexture(const Texture* pTexture) } // FUNCTION: LEGO1 0x100a3f80 -Result MeshImpl::SetTextureMappingMode(ProjectionType projType) +Result MeshImpl::SetTextureMappingMode(TextureMappingMode mode) { - if (projType == Perspective) { + if (mode == PerspectiveCorrect) { return ResultVal(m_data->groupMesh->SetGroupMapping(m_data->groupIndex, D3DRMMAP_PERSPCORRECT)); } else { @@ -73,7 +73,7 @@ Result MeshImpl::SetShadingModel(ShadingModel model) } // FUNCTION: LEGO1 0x100a4030 -Mesh* MeshImpl::DeepClone(Unk* pUnk) +Mesh* MeshImpl::DeepClone(MeshBuilder* pMeshBuilder) { // Create group MeshImpl* newMesh = new MeshImpl(); @@ -96,7 +96,7 @@ Mesh* MeshImpl::DeepClone(Unk* pUnk) D3DCOLOR color = m_data->groupMesh->GetGroupColor(m_data->groupIndex); // Push information to new group - UnkImpl* target = static_cast(pUnk); + MeshBuilderImpl* target = static_cast(pMeshBuilder); D3DRMGROUPINDEX index; target->ImplementationData()->AddGroup(vcount, fcount, vperface, faceBuffer, &index); newMesh->m_data->groupIndex = index; @@ -118,14 +118,14 @@ Mesh* MeshImpl::DeepClone(Unk* pUnk) } // FUNCTION: LEGO1 0x100a4240 -Mesh* MeshImpl::ShallowClone(Unk* pUnk) +Mesh* MeshImpl::ShallowClone(MeshBuilder* pMeshBuilder) { MeshImpl* newGroup = new MeshImpl(); MeshData* newData = new MeshData(); newGroup->m_data = newData; if (newData) { newData->groupIndex = m_data->groupIndex; - newData->groupMesh = static_cast(pUnk)->ImplementationData(); + newData->groupMesh = static_cast(pMeshBuilder)->ImplementationData(); } else { delete newGroup; diff --git a/LEGO1/tgl/d3drm/meshbuilder.cpp b/LEGO1/tgl/d3drm/meshbuilder.cpp new file mode 100644 index 00000000..2693e500 --- /dev/null +++ b/LEGO1/tgl/d3drm/meshbuilder.cpp @@ -0,0 +1,187 @@ +#include "impl.h" + +using namespace TglImpl; + +DECOMP_SIZE_ASSERT(MeshBuilder, 0x04); +DECOMP_SIZE_ASSERT(MeshBuilderImpl, 0x08); + +// FUNCTION: LEGO1 0x100a3830 +void* MeshBuilderImpl::ImplementationDataPtr() +{ + return reinterpret_cast(&m_data); +} + +// FUNCTION: LEGO1 0x100a3840 +Mesh* MeshBuilderImpl::CreateMesh( + 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* pMeshImpl = new MeshImpl; + if (CreateMeshImpl( + pMeshImpl, + faceCount, + vertexCount, + pPositions, + pNormals, + pTextureCoordinates, + pFaceIndices, + pTextureIndices, + shadingModel + ) == Error) { + delete pMeshImpl; + pMeshImpl = NULL; + } + + return pMeshImpl; +} + +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 short*) &faceIndices[i] + 1) >> 0x0f) & 0x01) { + 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)) { + if (rpMesh) { + delete rpMesh; + } + rpMesh = NULL; + } + else { + result = MeshSetTextureMappingMode(rpMesh, PerspectiveCorrect); + } + + if (fData != NULL) { + delete[] fData; + } + + if (vertices != NULL) { + delete[] vertices; + } + + return result; +} + +inline Result MeshBuilderImpl::CreateMeshImpl( + MeshImpl* pMeshImpl, + 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, + pMeshImpl->ImplementationData() + ); +} + +// FUNCTION: LEGO1 0x100a3ae0 +Result MeshBuilderImpl::GetBoundingBox(float min[3], float max[3]) +{ + D3DRMBOX box; + Result result = ResultVal(m_data->GetBox(&box)); + if (result == Success) { + min[0] = box.min.x; + min[1] = box.min.y; + min[2] = box.min.z; + max[0] = box.max.x; + max[1] = box.max.y; + max[2] = box.max.z; + } + return result; +} + +// FUNCTION: LEGO1 0x100a3b40 +MeshBuilder* MeshBuilderImpl::Clone() +{ + MeshBuilderImpl* mesh = new MeshBuilderImpl(); + int ret = m_data->Clone(0, IID_IDirect3DRMMeshBuilder, (void**) &mesh->m_data); + if (ret < 0) { + delete mesh; + mesh = NULL; + } + return mesh; +} diff --git a/LEGO1/tgl/d3drm/renderer.cpp b/LEGO1/tgl/d3drm/renderer.cpp index c3669e05..6a20053a 100644 --- a/LEGO1/tgl/d3drm/renderer.cpp +++ b/LEGO1/tgl/d3drm/renderer.cpp @@ -209,20 +209,14 @@ Light* RendererImpl::CreateLight(LightType type, float r, float g, float b) } // FUNCTION: LEGO1 0x100a1e90 -Unk* RendererImpl::CreateUnk() +MeshBuilder* RendererImpl::CreateMeshBuilder() { - // Note: I'm fairly certain that Unknown is not what Tgl calls a - // "Mesh", because the methods on Mesh in the Tgl leak line up much - // more closely with a different vtable than the one assigned in - // this method (meaning this method is not creating a Mesh). - // Maybe this method is something like CreateMeshBuilder where the - // Mesh data type in the Tgl leak was split into builder/result? - UnkImpl* unknown = new UnkImpl(); - if (FAILED(m_data->CreateMesh(&unknown->m_data))) { - delete unknown; - unknown = NULL; + MeshBuilderImpl* meshBuilder = new MeshBuilderImpl(); + if (FAILED(m_data->CreateMesh(&meshBuilder->m_data))) { + delete meshBuilder; + meshBuilder = NULL; } - return unknown; + return meshBuilder; } inline Result RendererCreateTexture( diff --git a/LEGO1/tgl/d3drm/unk.cpp b/LEGO1/tgl/d3drm/unk.cpp deleted file mode 100644 index eb73eb00..00000000 --- a/LEGO1/tgl/d3drm/unk.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "impl.h" - -using namespace TglImpl; - -DECOMP_SIZE_ASSERT(Unk, 0x04); -DECOMP_SIZE_ASSERT(UnkImpl, 0x08); - -// FUNCTION: LEGO1 0x100a3830 -void* UnkImpl::ImplementationDataPtr() -{ - return reinterpret_cast(&m_data); -} - -// STUB: LEGO1 0x100a3840 -Tgl::Mesh* UnkImpl::CreateMesh( - unsigned long faceCount, - unsigned long vertexCount, - float (*pPositions)[3], - float (*pNormals)[3], - float (*pTextureCoordinates)[2], - unsigned long (*pFaceIndices)[3], - unsigned long (*pTextureIndices)[3], - Tgl::ShadingModel shadingModel -) -{ - return NULL; -} - -// FUNCTION: LEGO1 0x100a3ae0 -Result UnkImpl::GetBoundingBox(float min[3], float max[3]) -{ - D3DRMBOX box; - Result result = ResultVal(m_data->GetBox(&box)); - if (result == Success) { - min[0] = box.min.x; - min[1] = box.min.y; - min[2] = box.min.z; - max[0] = box.max.x; - max[1] = box.max.y; - max[2] = box.max.z; - } - return result; -} - -// FUNCTION: LEGO1 0x100a3b40 -Unk* UnkImpl::Clone() -{ - UnkImpl* mesh = new UnkImpl(); - int ret = m_data->Clone(0, IID_IDirect3DRMMeshBuilder, (void**) &mesh->m_data); - if (ret < 0) { - delete mesh; - mesh = NULL; - } - return mesh; -} diff --git a/LEGO1/tgl/tgl.h b/LEGO1/tgl/tgl.h index 2cd4d6f7..4a087c14 100644 --- a/LEGO1/tgl/tgl.h +++ b/LEGO1/tgl/tgl.h @@ -96,7 +96,7 @@ class Camera; class Group; class Mesh; class Texture; -class Unk; +class MeshBuilder; // VTABLE: LEGO1 0x100db980 class Object { @@ -131,7 +131,7 @@ public: virtual Group* CreateGroup(const Group* pParent = 0) = 0; // vtable+0x20 - virtual Unk* CreateUnk() = 0; + virtual MeshBuilder* CreateMeshBuilder() = 0; virtual Texture* CreateTexture( int width, int height, @@ -269,18 +269,21 @@ public: // 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; - virtual Result SetTextureMappingMode(ProjectionType) = 0; + virtual Result SetTextureMappingMode(TextureMappingMode) = 0; virtual Result SetShadingModel(ShadingModel) = 0; // Clone data in underlying group - virtual Mesh* DeepClone(Unk*) = 0; + virtual Mesh* DeepClone(MeshBuilder*) = 0; // Just get another Group pointing to the same underlying data - virtual Mesh* ShallowClone(Unk*) = 0; + virtual Mesh* ShallowClone(MeshBuilder*) = 0; // SYNTHETIC: LEGO1 0x100a3e60 // Tgl::Mesh::`scalar deleting destructor' @@ -297,7 +300,7 @@ public: virtual Result Add(const Group*) = 0; virtual Result Add(const Mesh*) = 0; virtual Result Remove(const Group*) = 0; - virtual Result Remove(const Unk*) = 0; + virtual Result Remove(const MeshBuilder*) = 0; virtual Result RemoveAll() = 0; // This is TransformLocalToWorld in the leak, however it seems @@ -315,9 +318,9 @@ public: // was not in the leaked Tgl code. My suspicion is that it's // some kind of builder class for creating meshes. // VTABLE: LEGO1 0x100dbb30 -class Unk : public Object { +class MeshBuilder : public Object { public: - virtual Tgl::Mesh* CreateMesh( + virtual Mesh* CreateMesh( unsigned long faceCount, unsigned long vertexCount, float (*pPositions)[3], @@ -325,16 +328,16 @@ public: 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; + virtual MeshBuilder* Clone() = 0; // SYNTHETIC: LEGO1 0x100a27b0 - // Tgl::Unk::~Unk + // Tgl::MeshBuilder::~MeshBuilder // SYNTHETIC: LEGO1 0x100a2b10 - // Tgl::Unk::`scalar deleting destructor' + // Tgl::MeshBuilder::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dbb68 diff --git a/LEGO1/viewmanager/viewlod.cpp b/LEGO1/viewmanager/viewlod.cpp index afafe61a..aa04813e 100644 --- a/LEGO1/viewmanager/viewlod.cpp +++ b/LEGO1/viewmanager/viewlod.cpp @@ -3,5 +3,5 @@ // FUNCTION: LEGO1 0x100a5e40 ViewLOD::~ViewLOD() { - delete m_unk0x04; + delete m_meshBuilder; } diff --git a/LEGO1/viewmanager/viewlod.h b/LEGO1/viewmanager/viewlod.h index a92b52f9..a9aa9ac9 100644 --- a/LEGO1/viewmanager/viewlod.h +++ b/LEGO1/viewmanager/viewlod.h @@ -17,7 +17,7 @@ public: c_bit4 = 0x10 }; - ViewLOD(Tgl::Renderer* pRenderer) : m_unk0x04(NULL), m_unk0x08(3) {} + ViewLOD(Tgl::Renderer* pRenderer) : m_meshBuilder(NULL), m_unk0x08(3) {} ~ViewLOD() override; // FUNCTION: LEGO1 0x100a6f30 @@ -26,8 +26,8 @@ public: // FUNCTION: LEGO1 0x100a6f50 int NVerts() const override { return NumPolys() * 2; } // vtable+0x08 - Tgl::Unk* GetUnknown0x04() { return m_unk0x04; } - const Tgl::Unk* GetUnknown0x04() const { return m_unk0x04; } + Tgl::MeshBuilder* GetMeshBuilder() { return m_meshBuilder; } + const Tgl::MeshBuilder* GetMeshBuilder() const { return m_meshBuilder; } unsigned char GetUnknown0x08Test4() { return m_unk0x08 & 0xffffff04; } unsigned char GetUnknown0x08Test8() { return m_unk0x08 & 0xffffff08; } @@ -38,8 +38,8 @@ public: // ViewLOD::`scalar deleting destructor' protected: - Tgl::Unk* m_unk0x04; // 0x04 - undefined4 m_unk0x08; // 0x08 + Tgl::MeshBuilder* m_meshBuilder; // 0x04 + undefined4 m_unk0x08; // 0x08 }; #endif // VIEWLOD_H diff --git a/LEGO1/viewmanager/viewmanager.cpp b/LEGO1/viewmanager/viewmanager.cpp index aa2f4fb4..894e5fb5 100644 --- a/LEGO1/viewmanager/viewmanager.cpp +++ b/LEGO1/viewmanager/viewmanager.cpp @@ -93,13 +93,13 @@ void ViewManager::FUN_100a66a0(ViewROI* p_roi) const ViewLOD* lod = (const ViewLOD*) p_roi->GetLOD(p_roi->GetUnknown0xe0()); if (lod != NULL) { - const Tgl::Unk* unk = NULL; + const Tgl::MeshBuilder* meshBuilder = NULL; Tgl::Group* roiGeometry = p_roi->GetGeometry(); - unk = lod->GetUnknown0x04(); + meshBuilder = lod->GetMeshBuilder(); - if (unk != NULL) { - roiGeometry->Remove(unk); + if (meshBuilder != NULL) { + roiGeometry->Remove(meshBuilder); } scene->Remove(roiGeometry);