From c5b349ddb0704ecad826d8d5b15c04ecffc278b4 Mon Sep 17 00:00:00 2001 From: cutealien Date: Thu, 14 Apr 2022 16:54:06 +0000 Subject: [PATCH] Add IMeshBufffer::clone for buffer copies, use it in CMeshManipulator::createMeshCopy CMeshManipulator::createMeshCopy creates new meshes which have copies of the actual meshbuffers instead of copying everything into SMeshBuffers (which didn't support 32 bit or any of the other special features). git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6335 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 1 + include/CDynamicMeshBuffer.h | 34 ++++++++++++++ include/CMeshBuffer.h | 28 +++++++++++- include/IMeshBuffer.h | 10 +++++ include/IMeshManipulator.h | 4 +- include/IVertexBuffer.h | 10 +++++ include/SSharedMeshBuffer.h | 35 ++++++++++++++- include/SSkinMeshBuffer.h | 29 ++++++++++++ source/Irrlicht/CMeshManipulator.cpp | 67 +++------------------------- source/Irrlicht/COBJMeshWriter.cpp | 2 +- tests/tests-last-passed-at.txt | 2 +- 11 files changed, 151 insertions(+), 71 deletions(-) diff --git a/changes.txt b/changes.txt index 67985d8..92b9cd7 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,6 @@ -------------------------- Changes in 1.9 (not yet released) +- Add IMeshBufffer::clone function to create buffer copies. CMeshManipulator::createMeshCopy uses that now and works now with all types of meshbuffers. - obj writer can now write 32 bit buffers - obj meshloader can now load 32 bit buffers when setPreferredIndexType is set to EIT_32BIT. It's 16 bit meshes use now also an IDynamicMeshbuffer instead of an SMeshBuffer. diff --git a/include/CDynamicMeshBuffer.h b/include/CDynamicMeshBuffer.h index 3989b3e..2eed836 100644 --- a/include/CDynamicMeshBuffer.h +++ b/include/CDynamicMeshBuffer.h @@ -120,6 +120,40 @@ namespace scene return EMBT_DYNAMIC; } + //! Create copy of the meshbuffer + virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE + { + CDynamicMeshBuffer* clone = new CDynamicMeshBuffer(VertexBuffer->getType(), IndexBuffer->getType()); + + if (cloneFlags & ECF_VERTICES) + { + const u32 numVertices = VertexBuffer->size(); + clone->VertexBuffer->reallocate(numVertices); + for ( u32 i=0; iVertexBuffer->push_back((*VertexBuffer)[i]); + } + clone->BoundingBox = BoundingBox; + } + + if (cloneFlags & ECF_INDICES) + { + const u32 numIndices = IndexBuffer->size(); + clone->IndexBuffer->reallocate(numIndices); + for ( u32 i=0; iIndexBuffer->push_back((*IndexBuffer)[i]); + } + } + + clone->VertexBuffer->setHardwareMappingHint(VertexBuffer->getHardwareMappingHint()); + clone->IndexBuffer->setHardwareMappingHint(clone->IndexBuffer->getHardwareMappingHint()); + clone->Material = Material; + clone->PrimitiveType = PrimitiveType; + + return clone; + } + video::SMaterial Material; core::aabbox3d BoundingBox; //! Primitive type used for rendering (triangles, lines, ...) diff --git a/include/CMeshBuffer.h b/include/CMeshBuffer.h index ca48c16..bc66df7 100644 --- a/include/CMeshBuffer.h +++ b/include/CMeshBuffer.h @@ -292,9 +292,33 @@ namespace scene return getTypeT(); } + //! Create copy of the meshbuffer + virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE + { + CMeshBuffer * clone = new CMeshBuffer(); + + if (cloneFlags & ECF_VERTICES) + { + clone->Vertices = Vertices; + clone->BoundingBox = BoundingBox; + } + + if (cloneFlags & ECF_INDICES) + { + clone->Indices = Indices; + } + + clone->PrimitiveType = PrimitiveType; + clone->Material = getMaterial(); + clone->MappingHint_Vertex = MappingHint_Vertex; + clone->MappingHint_Index = MappingHint_Index; + + return clone; + } + //! Returns type of the class implementing the IMeshBuffer for template specialization - // Minor note: Some compilers (VS) allow directly specializating the virtual function, - // but this will fail on other compilers (GCC). + // Minor note: Some compilers (VS) allow directly specializing the virtual function, + // but this will fail on other compilers (GCC). So using a helper function. EMESH_BUFFER_TYPE getTypeT() const; u32 ChangedID_Vertex; diff --git a/include/IMeshBuffer.h b/include/IMeshBuffer.h index eff92dc..6ecbb76 100644 --- a/include/IMeshBuffer.h +++ b/include/IMeshBuffer.h @@ -190,6 +190,16 @@ namespace scene return EMBT_UNKNOWN; } + //! Bitflags with options for cloning + enum ECloneFlags + { + ECF_VERTICES = 1, //! clone the vertices (or copy pointer for SSharedMeshBuffer) + ECF_INDICES = 2 //! clone the indices + }; + + //! Create a new object with a copy of the meshbuffer + //\param cloneFlags A combination of ECloneFlags + virtual IMeshBuffer* createClone(int cloneFlags=ECF_VERTICES|ECF_INDICES) const = 0; }; diff --git a/include/IMeshManipulator.h b/include/IMeshManipulator.h index f53a651..1b30730 100644 --- a/include/IMeshManipulator.h +++ b/include/IMeshManipulator.h @@ -229,9 +229,7 @@ namespace scene u8 axis, const core::vector3df& offset) const=0; //! Clones a static IMesh into a modifiable SMesh. - /** All meshbuffers in the returned SMesh - are of type SMeshBuffer or SMeshBufferLightMap. - \param mesh Mesh to copy. + /** \param mesh Mesh to copy. \return Cloned mesh. If you no longer need the cloned mesh, you should call SMesh::drop(). See IReferenceCounted::drop() for more information. */ diff --git a/include/IVertexBuffer.h b/include/IVertexBuffer.h index 5c51354..1a8c6fb 100644 --- a/include/IVertexBuffer.h +++ b/include/IVertexBuffer.h @@ -18,17 +18,27 @@ namespace scene class IVertexBuffer : public virtual IReferenceCounted { public: + //! Pointer to first element of vertex data virtual void* getData() =0; + virtual video::E_VERTEX_TYPE getType() const =0; virtual void setType(video::E_VERTEX_TYPE vertexType) =0; + + //! Number of bytes per element virtual u32 stride() const =0; + + //! Number of elements virtual u32 size() const =0; + + //! Add vertex to end. Note that depending on vertex type this will be one of the types derived from video::S3DVertex. virtual void push_back(const video::S3DVertex &element) =0; virtual video::S3DVertex& operator [](const u32 index) const =0; virtual video::S3DVertex& getLast() =0; virtual void set_used(u32 usedNow) =0; virtual void reallocate(u32 new_size) =0; virtual u32 allocated_size() const =0; + + //! Same as getData() - not sure why we got 2, should probably deprecate (and we don't always have video::S3DVertex*, so just confusing) virtual video::S3DVertex* pointer() =0; //! get the current hardware mapping hint diff --git a/include/SSharedMeshBuffer.h b/include/SSharedMeshBuffer.h index b9d82e6..aac563d 100644 --- a/include/SSharedMeshBuffer.h +++ b/include/SSharedMeshBuffer.h @@ -172,9 +172,16 @@ namespace scene } //! append the vertices and indices to the current buffer - virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) IRR_OVERRIDE {} + virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) IRR_OVERRIDE + { + // can't do that as it doesn't own the vertex memory + } + //! append the meshbuffer to the current buffer - virtual void append(const IMeshBuffer* const other) IRR_OVERRIDE {} + virtual void append(const IMeshBuffer* const other) IRR_OVERRIDE + { + // can't do that as it doesn't own the vertex memory + } //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const IRR_OVERRIDE @@ -232,6 +239,30 @@ namespace scene return EMBT_SHARED; } + //! Create copy of the meshbuffer + virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE + { + SSharedMeshBuffer * clone = new SSharedMeshBuffer(); + + if (cloneFlags & ECF_VERTICES) + { + clone->Vertices = Vertices; + clone->BoundingBox = BoundingBox; + } + + if (cloneFlags & ECF_INDICES) + { + clone->Indices = Indices; + } + + clone->Material = Material; + clone->MappingHintVertex = MappingHintVertex; + clone->MappingHintIndex = MappingHintIndex; + clone->PrimitiveType = PrimitiveType; + + return clone; + } + //! Material of this meshBuffer video::SMaterial Material; diff --git a/include/SSkinMeshBuffer.h b/include/SSkinMeshBuffer.h index 1e29889..52d480c 100644 --- a/include/SSkinMeshBuffer.h +++ b/include/SSkinMeshBuffer.h @@ -389,6 +389,35 @@ struct SSkinMeshBuffer : public IMeshBuffer return EMBT_SKIN; } + //! Create copy of the meshbuffer + virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE + { + SSkinMeshBuffer* clone = new SSkinMeshBuffer(VertexType); + + if (cloneFlags & ECF_VERTICES) + { + clone->Vertices_Tangents = Vertices_Tangents; + clone->Vertices_2TCoords = Vertices_2TCoords; + clone->Vertices_Standard = Vertices_Standard; + + clone->BoundingBox = BoundingBox; + clone->BoundingBoxNeedsRecalculated = BoundingBoxNeedsRecalculated; + } + + if (cloneFlags & ECF_INDICES) + { + clone->Indices = Indices; + } + + clone->Transformation = Transformation; + clone->Material = getMaterial(); + clone->PrimitiveType = PrimitiveType; + clone->MappingHint_Vertex = MappingHint_Vertex; + clone->MappingHint_Index = MappingHint_Index; + + return clone; + } + //! Call this after changing the positions of any vertex. void boundingBoxNeedsRecalculated(void) { BoundingBoxNeedsRecalculated = true; } diff --git a/source/Irrlicht/CMeshManipulator.cpp b/source/Irrlicht/CMeshManipulator.cpp index f177fc2..093ad23 100644 --- a/source/Irrlicht/CMeshManipulator.cpp +++ b/source/Irrlicht/CMeshManipulator.cpp @@ -577,8 +577,7 @@ void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resoluti } -//! Clones a static IMesh into a modifyable SMesh. -// not yet 32bit +//! Clones a static IMesh into a modifiable SMesh. SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const { if (!mesh) @@ -590,66 +589,10 @@ SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const for ( u32 b=0; bgetMeshBuffer(b); - switch(mb->getVertexType()) - { - case video::EVT_STANDARD: - { - SMeshBuffer* buffer = new SMeshBuffer(); - buffer->Material = mb->getMaterial(); - const u32 vcount = mb->getVertexCount(); - buffer->Vertices.reallocate(vcount); - video::S3DVertex* vertices = (video::S3DVertex*)mb->getVertices(); - for (u32 i=0; i < vcount; ++i) - buffer->Vertices.push_back(vertices[i]); - const u32 icount = mb->getIndexCount(); - buffer->Indices.reallocate(icount); - const u16* indices = mb->getIndices(); - for (u32 i=0; i < icount; ++i) - buffer->Indices.push_back(indices[i]); - clone->addMeshBuffer(buffer); - buffer->drop(); - } - break; - case video::EVT_2TCOORDS: - { - SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); - buffer->Material = mb->getMaterial(); - const u32 vcount = mb->getVertexCount(); - buffer->Vertices.reallocate(vcount); - video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)mb->getVertices(); - for (u32 i=0; i < vcount; ++i) - buffer->Vertices.push_back(vertices[i]); - const u32 icount = mb->getIndexCount(); - buffer->Indices.reallocate(icount); - const u16* indices = mb->getIndices(); - for (u32 i=0; i < icount; ++i) - buffer->Indices.push_back(indices[i]); - clone->addMeshBuffer(buffer); - buffer->drop(); - } - break; - case video::EVT_TANGENTS: - { - SMeshBufferTangents* buffer = new SMeshBufferTangents(); - buffer->Material = mb->getMaterial(); - const u32 vcount = mb->getVertexCount(); - buffer->Vertices.reallocate(vcount); - video::S3DVertexTangents* vertices = (video::S3DVertexTangents*)mb->getVertices(); - for (u32 i=0; i < vcount; ++i) - buffer->Vertices.push_back(vertices[i]); - const u32 icount = mb->getIndexCount(); - buffer->Indices.reallocate(icount); - const u16* indices = mb->getIndices(); - for (u32 i=0; i < icount; ++i) - buffer->Indices.push_back(indices[i]); - clone->addMeshBuffer(buffer); - buffer->drop(); - } - break; - }// end switch - - }// end for all mesh buffers + IMeshBuffer* bufferClone = mesh->getMeshBuffer(b)->createClone(); + clone->addMeshBuffer(bufferClone); + bufferClone->drop(); + } clone->BoundingBox = mesh->getBoundingBox(); return clone; diff --git a/source/Irrlicht/COBJMeshWriter.cpp b/source/Irrlicht/COBJMeshWriter.cpp index 7f5bfab..7c1232e 100644 --- a/source/Irrlicht/COBJMeshWriter.cpp +++ b/source/Irrlicht/COBJMeshWriter.cpp @@ -127,10 +127,10 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla file->write(num.c_str(), num.size()); file->write("\n",1); + unsigned int idx2=0, idx1=0, idx0 = 0; const u32 indexCount = buffer->getIndexCount(); for (j=0; jgetIndexType()) { case video::EIT_16BIT: diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt index 28eb413..b2e7b88 100644 --- a/tests/tests-last-passed-at.txt +++ b/tests/tests-last-passed-at.txt @@ -1,4 +1,4 @@ Tests finished. 72 tests of 72 passed. Compiled as DEBUG -Test suite pass at GMT Thu Apr 14 13:52:29 2022 +Test suite pass at GMT Thu Apr 14 16:41:11 2022