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
This commit is contained in:
cutealien 2022-04-14 16:54:06 +00:00
parent 8447d3f531
commit c5b349ddb0
11 changed files with 151 additions and 71 deletions

@ -1,5 +1,6 @@
-------------------------- --------------------------
Changes in 1.9 (not yet released) 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 writer can now write 32 bit buffers
- obj meshloader can now load 32 bit buffers when setPreferredIndexType is set to EIT_32BIT. - 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. It's 16 bit meshes use now also an IDynamicMeshbuffer instead of an SMeshBuffer.

@ -120,6 +120,40 @@ namespace scene
return EMBT_DYNAMIC; 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; i<numVertices; ++i )
{
clone->VertexBuffer->push_back((*VertexBuffer)[i]);
}
clone->BoundingBox = BoundingBox;
}
if (cloneFlags & ECF_INDICES)
{
const u32 numIndices = IndexBuffer->size();
clone->IndexBuffer->reallocate(numIndices);
for ( u32 i=0; i<numIndices; ++i )
{
clone->IndexBuffer->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; video::SMaterial Material;
core::aabbox3d<f32> BoundingBox; core::aabbox3d<f32> BoundingBox;
//! Primitive type used for rendering (triangles, lines, ...) //! Primitive type used for rendering (triangles, lines, ...)

@ -292,9 +292,33 @@ namespace scene
return getTypeT(); return getTypeT();
} }
//! Create copy of the meshbuffer
virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE
{
CMeshBuffer<T> * clone = new CMeshBuffer<T>();
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 //! Returns type of the class implementing the IMeshBuffer for template specialization
// Minor note: Some compilers (VS) allow directly specializating the virtual function, // Minor note: Some compilers (VS) allow directly specializing the virtual function,
// but this will fail on other compilers (GCC). // but this will fail on other compilers (GCC). So using a helper function.
EMESH_BUFFER_TYPE getTypeT() const; EMESH_BUFFER_TYPE getTypeT() const;
u32 ChangedID_Vertex; u32 ChangedID_Vertex;

@ -190,6 +190,16 @@ namespace scene
return EMBT_UNKNOWN; 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;
}; };

@ -229,9 +229,7 @@ namespace scene
u8 axis, const core::vector3df& offset) const=0; u8 axis, const core::vector3df& offset) const=0;
//! Clones a static IMesh into a modifiable SMesh. //! Clones a static IMesh into a modifiable SMesh.
/** All meshbuffers in the returned SMesh /** \param mesh Mesh to copy.
are of type SMeshBuffer or SMeshBufferLightMap.
\param mesh Mesh to copy.
\return Cloned mesh. If you no longer need the \return Cloned mesh. If you no longer need the
cloned mesh, you should call SMesh::drop(). See cloned mesh, you should call SMesh::drop(). See
IReferenceCounted::drop() for more information. */ IReferenceCounted::drop() for more information. */

@ -18,17 +18,27 @@ namespace scene
class IVertexBuffer : public virtual IReferenceCounted class IVertexBuffer : public virtual IReferenceCounted
{ {
public: public:
//! Pointer to first element of vertex data
virtual void* getData() =0; virtual void* getData() =0;
virtual video::E_VERTEX_TYPE getType() const =0; virtual video::E_VERTEX_TYPE getType() const =0;
virtual void setType(video::E_VERTEX_TYPE vertexType) =0; virtual void setType(video::E_VERTEX_TYPE vertexType) =0;
//! Number of bytes per element
virtual u32 stride() const =0; virtual u32 stride() const =0;
//! Number of elements
virtual u32 size() const =0; 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 void push_back(const video::S3DVertex &element) =0;
virtual video::S3DVertex& operator [](const u32 index) const =0; virtual video::S3DVertex& operator [](const u32 index) const =0;
virtual video::S3DVertex& getLast() =0; virtual video::S3DVertex& getLast() =0;
virtual void set_used(u32 usedNow) =0; virtual void set_used(u32 usedNow) =0;
virtual void reallocate(u32 new_size) =0; virtual void reallocate(u32 new_size) =0;
virtual u32 allocated_size() const =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; virtual video::S3DVertex* pointer() =0;
//! get the current hardware mapping hint //! get the current hardware mapping hint

@ -172,9 +172,16 @@ namespace scene
} }
//! append the vertices and indices to the current buffer //! 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 //! 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 //! get the current hardware mapping hint
virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const IRR_OVERRIDE virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const IRR_OVERRIDE
@ -232,6 +239,30 @@ namespace scene
return EMBT_SHARED; 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 //! Material of this meshBuffer
video::SMaterial Material; video::SMaterial Material;

@ -389,6 +389,35 @@ struct SSkinMeshBuffer : public IMeshBuffer
return EMBT_SKIN; 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. //! Call this after changing the positions of any vertex.
void boundingBoxNeedsRecalculated(void) { BoundingBoxNeedsRecalculated = true; } void boundingBoxNeedsRecalculated(void) { BoundingBoxNeedsRecalculated = true; }

@ -577,8 +577,7 @@ void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resoluti
} }
//! Clones a static IMesh into a modifyable SMesh. //! Clones a static IMesh into a modifiable SMesh.
// not yet 32bit
SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const
{ {
if (!mesh) if (!mesh)
@ -590,66 +589,10 @@ SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const
for ( u32 b=0; b<meshBufferCount; ++b) for ( u32 b=0; b<meshBufferCount; ++b)
{ {
const IMeshBuffer* const mb = mesh->getMeshBuffer(b); IMeshBuffer* bufferClone = mesh->getMeshBuffer(b)->createClone();
switch(mb->getVertexType()) clone->addMeshBuffer(bufferClone);
{ bufferClone->drop();
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
clone->BoundingBox = mesh->getBoundingBox(); clone->BoundingBox = mesh->getBoundingBox();
return clone; return clone;

@ -127,10 +127,10 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());
file->write("\n",1); file->write("\n",1);
unsigned int idx2=0, idx1=0, idx0 = 0;
const u32 indexCount = buffer->getIndexCount(); const u32 indexCount = buffer->getIndexCount();
for (j=0; j<indexCount; j+=3) for (j=0; j<indexCount; j+=3)
{ {
unsigned int idx2, idx1, idx0;
switch(buffer->getIndexType()) switch(buffer->getIndexType())
{ {
case video::EIT_16BIT: case video::EIT_16BIT:

@ -1,4 +1,4 @@
Tests finished. 72 tests of 72 passed. Tests finished. 72 tests of 72 passed.
Compiled as DEBUG 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