Merging r6337 through r6363 from trunk to ogl-es branch

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6379 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
cutealien 2022-05-04 21:26:18 +00:00
parent 2d63fdba3d
commit 993f990036
28 changed files with 439 additions and 328 deletions

@ -9,11 +9,28 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point)
-------------------------- --------------------------
Changes in 1.9 (not yet released) Changes in 1.9 (not yet released)
- Fix CVertexBuffer::setType switching types for non-empty arrays. Before we had some bad casts which could result in random initializing of some vertex data.
- IVertexBuffer interface changes: pointer() now returns void*. Adding a const version of getData(). Some set functions have now overload for all vertex types.
- S3DVertex now always initializes color to 0xffffff. That was previously the only uninitialized variable in there. Also both derived classes have now a constructor taking a const S3DVertex&.
- Fix deserialization in CGUITable. Use now getAttributeAsStringW instead of getAttributeAsString.
Thanks @chronologicaldot for report and patch: https://irrlicht.sourceforge.io/forum/viewtopic.php?f=7&t=52821
- IIndexBuffer interface changes: Adding a const version of getData(). Some set functions now copy by value instead of per reference, which shouldn't be slower for this and is safer to use.
- Fix CIndexBuffer::setType going from 16 to 32 bit. This had some casts which simply could mess up the results.
- Fix OSX nor resizing properly. Thanks @torleif, Jordach and sfan5 for patch and report: https://irrlicht.sourceforge.io/forum/viewtopic.php?f=2&t=52819
- X meshloader fixes bug with uninitialized normals. Thanks @sfan5 for patch: https://irrlicht.sourceforge.io/forum/viewtopic.php?f=2&t=52819
- stl meshloader now faster, especially with text format
- CMemoryReadFile::seek CMemoryWriteFile::seek and no longer allowed to go _before_ start.
Thanks @sfan5 for patch: https://irrlicht.sourceforge.io/forum/viewtopic.php?f=2&t=52819
- stl meshloader can now load 32 bit buffers.
Thanks @Foaly for the patch: https://irrlicht.sourceforge.io/forum/viewtopic.php?f=9&t=51441
- Add IMeshBufffer::clone function to create buffer copies. CMeshManipulator::createMeshCopy uses that now and works now with all types of meshbuffers. - 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 setIndexTypeHint is set correspondingly
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.
- Add IMeshLoader::setPreferredIndexType and getPreferredIndexType to allow setting hints for the loaders if users prefer 16 or 32 bit meshbuffers. Thanks @Wol101 for original patch proposal: https://irrlicht.sourceforge.io/forum/viewtopic.php?f=9&t=51441
- Add IMeshLoader::setIndexTypeHint and getIndexTypeHint to allow setting hints for the loaders if users prefer 16 or 32 bit meshbuffers.
Default is now to use optimal meshbuffer depending on number of vertices (if the loader supports it).
- Add IMeshBuffer::getType to allow finding out which class type a meshbuffer has (similar to ISceneNode::getType). - Add IMeshBuffer::getType to allow finding out which class type a meshbuffer has (similar to ISceneNode::getType).
- Add IGUIImage::flip to flip/mirror images - Add IGUIImage::flip to flip/mirror images
- IBillboardSceneNode got functions to access meshbuffers. So uv-coordinates can now be modified directly (previously only possible via texture matrix). - IBillboardSceneNode got functions to access meshbuffers. So uv-coordinates can now be modified directly (previously only possible via texture matrix).

@ -102,6 +102,26 @@ namespace scene
} }
} }
//! Append the vertices and indices to the current buffer
/** Only works for compatible vertex types.
\param vertices Pointer to a vertex array.
\param numVertices Number of vertices in the array.
\param indices Pointer to index array.
\param numIndices Number of indices in array. */
virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) IRR_OVERRIDE
{
// TODO
}
//! Append the meshbuffer to the current buffer
/** Only works for compatible vertex types
\param other Buffer to append to this one. */
virtual void append(const IMeshBuffer* const other) IRR_OVERRIDE
{
// TODO
}
//! Describe what kind of primitive geometry is used by the meshbuffer //! Describe what kind of primitive geometry is used by the meshbuffer
virtual void setPrimitiveType(E_PRIMITIVE_TYPE type) IRR_OVERRIDE virtual void setPrimitiveType(E_PRIMITIVE_TYPE type) IRR_OVERRIDE
{ {

@ -14,7 +14,7 @@ namespace scene
class CIndexBuffer : public IIndexBuffer class CIndexBuffer : public IIndexBuffer
{ {
// Virtual function wrapper around irr::core::array
class IIndexList class IIndexList
{ {
public: public:
@ -22,14 +22,15 @@ namespace scene
virtual u32 stride() const =0; virtual u32 stride() const =0;
virtual u32 size() const =0; virtual u32 size() const =0;
virtual void push_back(const u32 &element) =0; virtual void push_back(u32 value) =0;
virtual u32 operator [](u32 index) const =0; virtual u32 operator [](u32 index) const =0;
virtual u32 getLast() =0; virtual u32 getLast() =0;
virtual void setValue(u32 index, u32 value) =0; virtual void setValue(u32 index, u32 value) =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, bool canShrink=true) =0;
virtual u32 allocated_size() const =0; virtual u32 allocated_size() const =0;
virtual void* pointer() =0; virtual void* pointer() =0;
virtual const void* const_pointer() const =0;
virtual video::E_INDEX_TYPE getType() const =0; virtual video::E_INDEX_TYPE getType() const =0;
}; };
@ -43,10 +44,9 @@ namespace scene
virtual u32 size() const IRR_OVERRIDE {return Indices.size();} virtual u32 size() const IRR_OVERRIDE {return Indices.size();}
virtual void push_back(const u32 &element) IRR_OVERRIDE virtual void push_back(u32 value) IRR_OVERRIDE
{ {
// push const ref due to compiler problem with gcc 4.6, big endian Indices.push_back((T)value);
Indices.push_back((const T&)element);
} }
virtual u32 operator [](u32 index) const IRR_OVERRIDE virtual u32 operator [](u32 index) const IRR_OVERRIDE
@ -66,9 +66,9 @@ namespace scene
Indices.set_used(usedNow); Indices.set_used(usedNow);
} }
virtual void reallocate(u32 new_size) IRR_OVERRIDE virtual void reallocate(u32 new_size, bool canShrink) IRR_OVERRIDE
{ {
Indices.reallocate(new_size); Indices.reallocate(new_size, canShrink);
} }
virtual u32 allocated_size() const IRR_OVERRIDE virtual u32 allocated_size() const IRR_OVERRIDE
@ -77,6 +77,7 @@ namespace scene
} }
virtual void* pointer() IRR_OVERRIDE { return Indices.pointer(); } virtual void* pointer() IRR_OVERRIDE { return Indices.pointer(); }
virtual const void* const_pointer() const IRR_OVERRIDE { return Indices.const_pointer(); }
virtual video::E_INDEX_TYPE getType() const IRR_OVERRIDE virtual video::E_INDEX_TYPE getType() const IRR_OVERRIDE
{ {
@ -109,12 +110,14 @@ namespace scene
delete Indices; delete Indices;
} }
//virtual void setType(video::E_INDEX_TYPE IndexType); virtual void setType(video::E_INDEX_TYPE indexType) IRR_OVERRIDE
virtual void setType(video::E_INDEX_TYPE IndexType) IRR_OVERRIDE
{ {
if ( Indices && Indices->getType() == indexType )
return;
IIndexList *NewIndices=0; IIndexList *NewIndices=0;
switch (IndexType) switch (indexType)
{ {
case video::EIT_16BIT: case video::EIT_16BIT:
{ {
@ -142,6 +145,7 @@ namespace scene
} }
virtual void* getData() IRR_OVERRIDE {return Indices->pointer();} virtual void* getData() IRR_OVERRIDE {return Indices->pointer();}
virtual const void* getData() const IRR_OVERRIDE { return Indices->const_pointer(); }
virtual video::E_INDEX_TYPE getType() const IRR_OVERRIDE {return Indices->getType();} virtual video::E_INDEX_TYPE getType() const IRR_OVERRIDE {return Indices->getType();}
@ -152,9 +156,9 @@ namespace scene
return Indices->size(); return Indices->size();
} }
virtual void push_back(const u32 &element) IRR_OVERRIDE virtual void push_back(u32 value) IRR_OVERRIDE
{ {
Indices->push_back(element); Indices->push_back(value);
} }
virtual u32 operator [](u32 index) const IRR_OVERRIDE virtual u32 operator [](u32 index) const IRR_OVERRIDE
@ -177,9 +181,9 @@ namespace scene
Indices->set_used(usedNow); Indices->set_used(usedNow);
} }
virtual void reallocate(u32 new_size) IRR_OVERRIDE virtual void reallocate(u32 new_size, bool canShrink=true) IRR_OVERRIDE
{ {
Indices->reallocate(new_size); Indices->reallocate(new_size, canShrink);
} }
virtual u32 allocated_size() const IRR_OVERRIDE virtual u32 allocated_size() const IRR_OVERRIDE
@ -187,11 +191,6 @@ namespace scene
return Indices->allocated_size(); return Indices->allocated_size();
} }
virtual void* pointer() IRR_OVERRIDE
{
return Indices->pointer();
}
//! get the current hardware mapping hint //! get the current hardware mapping hint
virtual E_HARDWARE_MAPPING getHardwareMappingHint() const IRR_OVERRIDE virtual E_HARDWARE_MAPPING getHardwareMappingHint() const IRR_OVERRIDE
{ {

@ -25,12 +25,20 @@ namespace scene
virtual u32 size() const =0; virtual u32 size() const =0;
virtual void push_back (const video::S3DVertex &element) =0; virtual void push_back (const video::S3DVertex &element) =0;
virtual void push_back(const video::S3DVertex2TCoords &element) =0;
virtual void push_back(const video::S3DVertexTangents &element) =0;
virtual void setValue(u32 index, const video::S3DVertex &value) =0;
virtual void setValue(u32 index, const video::S3DVertex2TCoords &value) =0;
virtual void setValue(u32 index, const video::S3DVertexTangents &value) =0;
virtual video::S3DVertex& operator [](u32 index) = 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, bool canShrink=true) =0;
virtual u32 allocated_size() const =0; virtual u32 allocated_size() const =0;
virtual video::S3DVertex* pointer() =0; virtual void* pointer() =0;
virtual const void* const_pointer() const =0;
virtual video::E_VERTEX_TYPE getType() const =0; virtual video::E_VERTEX_TYPE getType() const =0;
}; };
@ -45,7 +53,21 @@ namespace scene
virtual u32 size() const IRR_OVERRIDE {return Vertices.size();} virtual u32 size() const IRR_OVERRIDE {return Vertices.size();}
virtual void push_back (const video::S3DVertex &element) IRR_OVERRIDE virtual void push_back (const video::S3DVertex &element) IRR_OVERRIDE
{Vertices.push_back((T&)element);} {Vertices.push_back(element);}
virtual void push_back(const video::S3DVertex2TCoords &element) IRR_OVERRIDE
{Vertices.push_back(element);}
virtual void push_back(const video::S3DVertexTangents &element) IRR_OVERRIDE
{Vertices.push_back(element);}
virtual void setValue(u32 index, const video::S3DVertex &value) IRR_OVERRIDE
{Vertices[index] = value;}
virtual void setValue(u32 index, const video::S3DVertex2TCoords &value) IRR_OVERRIDE
{Vertices[index] = value;}
virtual void setValue(u32 index, const video::S3DVertexTangents &value) IRR_OVERRIDE
{Vertices[index] = value;}
virtual video::S3DVertex& operator [](u32 index) IRR_OVERRIDE
{return (video::S3DVertex&)Vertices[index];}
virtual video::S3DVertex& operator [](const u32 index) const IRR_OVERRIDE virtual video::S3DVertex& operator [](const u32 index) const IRR_OVERRIDE
{return (video::S3DVertex&)Vertices[index];} {return (video::S3DVertex&)Vertices[index];}
@ -56,15 +78,16 @@ namespace scene
virtual void set_used(u32 usedNow) IRR_OVERRIDE virtual void set_used(u32 usedNow) IRR_OVERRIDE
{Vertices.set_used(usedNow);} {Vertices.set_used(usedNow);}
virtual void reallocate(u32 new_size) IRR_OVERRIDE virtual void reallocate(u32 new_size, bool canShrink) IRR_OVERRIDE
{Vertices.reallocate(new_size);} {Vertices.reallocate(new_size, canShrink);}
virtual u32 allocated_size() const IRR_OVERRIDE virtual u32 allocated_size() const IRR_OVERRIDE
{ {
return Vertices.allocated_size(); return Vertices.allocated_size();
} }
virtual video::S3DVertex* pointer() IRR_OVERRIDE {return Vertices.pointer();} virtual void* pointer() IRR_OVERRIDE {return Vertices.pointer();}
virtual const void* const_pointer() const IRR_OVERRIDE {return Vertices.const_pointer();}
virtual video::E_VERTEX_TYPE getType() const IRR_OVERRIDE {return T::getType();} virtual video::E_VERTEX_TYPE getType() const IRR_OVERRIDE {return T::getType();}
}; };
@ -94,9 +117,11 @@ namespace scene
delete Vertices; delete Vertices;
} }
virtual void setType(video::E_VERTEX_TYPE vertexType) IRR_OVERRIDE virtual void setType(video::E_VERTEX_TYPE vertexType) IRR_OVERRIDE
{ {
if ( Vertices && Vertices->getType() == vertexType )
return;
IVertexList *NewVertices=0; IVertexList *NewVertices=0;
switch (vertexType) switch (vertexType)
@ -121,8 +146,27 @@ namespace scene
{ {
NewVertices->reallocate( Vertices->size() ); NewVertices->reallocate( Vertices->size() );
switch (Vertices->getType()) // old type
{
case video::EVT_STANDARD:
{
for(u32 n=0;n<Vertices->size();++n) for(u32 n=0;n<Vertices->size();++n)
NewVertices->push_back((*Vertices)[n]); NewVertices->push_back((*Vertices)[n]);
break;
}
case video::EVT_2TCOORDS:
{
for(u32 n=0;n<Vertices->size();++n)
NewVertices->push_back((video::S3DVertex2TCoords&)(*Vertices)[n]);
break;
}
case video::EVT_TANGENTS:
{
for(u32 n=0;n<Vertices->size();++n)
NewVertices->push_back((video::S3DVertexTangents&)(*Vertices)[n]);
break;
}
}
delete Vertices; delete Vertices;
} }
@ -131,6 +175,7 @@ namespace scene
} }
virtual void* getData() IRR_OVERRIDE {return Vertices->pointer();} virtual void* getData() IRR_OVERRIDE {return Vertices->pointer();}
virtual const void* getData() const IRR_OVERRIDE {return Vertices->const_pointer();}
virtual video::E_VERTEX_TYPE getType() const IRR_OVERRIDE {return Vertices->getType();} virtual video::E_VERTEX_TYPE getType() const IRR_OVERRIDE {return Vertices->getType();}
@ -146,6 +191,36 @@ namespace scene
Vertices->push_back(element); Vertices->push_back(element);
} }
virtual void push_back(const video::S3DVertex2TCoords &element) IRR_OVERRIDE
{
Vertices->push_back(element);
}
virtual void push_back(const video::S3DVertexTangents &element) IRR_OVERRIDE
{
Vertices->push_back(element);
}
virtual void setValue(u32 index, const video::S3DVertex &value) IRR_OVERRIDE
{
Vertices->setValue(index, value);
}
virtual void setValue(u32 index, const video::S3DVertex2TCoords &value) IRR_OVERRIDE
{
Vertices->setValue(index, value);
}
virtual void setValue(u32 index, const video::S3DVertexTangents &value) IRR_OVERRIDE
{
Vertices->setValue(index, value);
}
virtual video::S3DVertex& operator [](u32 index) IRR_OVERRIDE
{
return (*Vertices)[index];
}
virtual video::S3DVertex& operator [](const u32 index) const IRR_OVERRIDE virtual video::S3DVertex& operator [](const u32 index) const IRR_OVERRIDE
{ {
return (*Vertices)[index]; return (*Vertices)[index];
@ -161,9 +236,9 @@ namespace scene
Vertices->set_used(usedNow); Vertices->set_used(usedNow);
} }
virtual void reallocate(u32 new_size) IRR_OVERRIDE virtual void reallocate(u32 new_size, bool canShrink=true) IRR_OVERRIDE
{ {
Vertices->reallocate(new_size); Vertices->reallocate(new_size, canShrink);
} }
virtual u32 allocated_size() const IRR_OVERRIDE virtual u32 allocated_size() const IRR_OVERRIDE
@ -171,11 +246,6 @@ namespace scene
return Vertices->allocated_size(); return Vertices->allocated_size();
} }
virtual video::S3DVertex* pointer() IRR_OVERRIDE
{
return Vertices->pointer();
}
//! get the current hardware mapping hint //! get the current hardware mapping hint
virtual E_HARDWARE_MAPPING getHardwareMappingHint() const IRR_OVERRIDE virtual E_HARDWARE_MAPPING getHardwareMappingHint() const IRR_OVERRIDE
{ {

@ -151,17 +151,6 @@ namespace scene
/** Basically its an alternate way to describe a transformation. */ /** Basically its an alternate way to describe a transformation. */
struct SMD3QuaternionTag struct SMD3QuaternionTag
{ {
virtual ~SMD3QuaternionTag()
{
position.X = 0.f;
}
// construct copy constructor
SMD3QuaternionTag( const SMD3QuaternionTag & copyMe )
{
*this = copyMe;
}
// construct for searching // construct for searching
SMD3QuaternionTag( const core::stringc& name ) SMD3QuaternionTag( const core::stringc& name )
: Name ( name ) {} : Name ( name ) {}
@ -181,14 +170,6 @@ namespace scene
return Name == other.Name; return Name == other.Name;
} }
SMD3QuaternionTag & operator=( const SMD3QuaternionTag & copyMe )
{
Name = copyMe.Name;
position = copyMe.position;
rotation = copyMe.rotation;
return *this;
}
core::stringc Name; core::stringc Name;
core::vector3df position; core::vector3df position;
core::quaternion rotation; core::quaternion rotation;
@ -202,14 +183,6 @@ namespace scene
Container.setAllocStrategy(core::ALLOC_STRATEGY_SAFE); Container.setAllocStrategy(core::ALLOC_STRATEGY_SAFE);
} }
// construct copy constructor
SMD3QuaternionTagList(const SMD3QuaternionTagList& copyMe)
{
*this = copyMe;
}
virtual ~SMD3QuaternionTagList() {}
SMD3QuaternionTag* get(const core::stringc& name) SMD3QuaternionTag* get(const core::stringc& name)
{ {
SMD3QuaternionTag search ( name ); SMD3QuaternionTag search ( name );
@ -250,12 +223,6 @@ namespace scene
Container.push_back(other); Container.push_back(other);
} }
SMD3QuaternionTagList& operator = (const SMD3QuaternionTagList & copyMe)
{
Container = copyMe.Container;
return *this;
}
private: private:
core::array < SMD3QuaternionTag > Container; core::array < SMD3QuaternionTag > Container;
}; };

@ -24,46 +24,13 @@ namespace scene
virtual void setVertexBuffer(IVertexBuffer *vertexBuffer) =0; virtual void setVertexBuffer(IVertexBuffer *vertexBuffer) =0;
virtual void setIndexBuffer(IIndexBuffer *indexBuffer) =0; virtual void setIndexBuffer(IIndexBuffer *indexBuffer) =0;
//! Get the material of this meshbuffer
/** \return Material of this buffer. */
virtual video::SMaterial& getMaterial() IRR_OVERRIDE =0;
//! Get the material of this meshbuffer // ------------------- Old interface ------------------- //
/** \return Material of this buffer. */ // That stuff could also be in CDynamicMeshBuffer
virtual const video::SMaterial& getMaterial() const IRR_OVERRIDE =0; // I suppose it was put here to show that the information
// is now basically handled by the vertex/index buffers instead
// of the meshbuffer itself.
//! Get the axis aligned bounding box of this meshbuffer.
/** \return Axis aligned bounding box of this buffer. */
virtual const core::aabbox3df& getBoundingBox() const IRR_OVERRIDE =0;
//! Set axis aligned bounding box
/** \param box User defined axis aligned bounding box to use
for this buffer. */
virtual void setBoundingBox(const core::aabbox3df& box) IRR_OVERRIDE =0;
//! Recalculates the bounding box. Should be called if the mesh changed.
virtual void recalculateBoundingBox() IRR_OVERRIDE =0;
//! Append the vertices and indices to the current buffer
/** Only works for compatible vertex types.
\param vertices Pointer to a vertex array.
\param numVertices Number of vertices in the array.
\param indices Pointer to index array.
\param numIndices Number of indices in array. */
virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) IRR_OVERRIDE
{
}
//! Append the meshbuffer to the current buffer
/** Only works for compatible vertex types
\param other Buffer to append to this one. */
virtual void append(const IMeshBuffer* const other) IRR_OVERRIDE
{
}
// ------------------- To be removed? ------------------- //
//! 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
@ -105,7 +72,6 @@ namespace scene
return getIndexBuffer().getChangedID(); return getIndexBuffer().getChangedID();
} }
// ------------------- Old interface ------------------- //
//! Get type of vertex data which is stored in this meshbuffer. //! Get type of vertex data which is stored in this meshbuffer.
/** \return Vertex type of this buffer. */ /** \return Vertex type of this buffer. */

@ -20,23 +20,43 @@ namespace scene
{ {
public: public:
//! Pointer to first element
virtual void* getData() =0; virtual void* getData() =0;
//! Const pointer to first element
virtual const void* getData() const =0;
//! Same as getData(), just closer to core::array interface
void* pointer() { return getData(); }
virtual video::E_INDEX_TYPE getType() const =0; virtual video::E_INDEX_TYPE getType() const =0;
//! Change between 16 and 32 bit indices.
/** This copies all indices to a new buffer of corresponding type.
Be careful - going from 32 to 16 bit will only work correctly
if none of your indices is larger than 16 bit. */
virtual void setType(video::E_INDEX_TYPE IndexType) =0; virtual void setType(video::E_INDEX_TYPE IndexType) =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;
virtual void push_back (const u32 &element) =0;
//! Add value to end. Note that for 16 bit index types values shouldn't be larger than u16
virtual void push_back(u32 value) =0;
//! Set value at index. Note that for 16 bit index types values shouldn't be larger than u16
/** Buffer must be already large enough. This is basically the non const version of operator [] */
virtual void setValue(u32 index, u32 value) =0;
//! Access element value at given index
virtual u32 operator [](u32 index) const =0; virtual u32 operator [](u32 index) const =0;
virtual u32 getLast() =0; virtual u32 getLast() =0;
virtual void setValue(u32 index, u32 value) =0;
virtual void set_used(u32 usedNow) =0;
virtual void reallocate(u32 new_size) =0;
virtual u32 allocated_size() const=0;
virtual void* pointer() =0; virtual void set_used(u32 usedNow) =0;
virtual void reallocate(u32 new_size, bool canShrink=true) =0;
virtual u32 allocated_size() const=0;
//! get the current hardware mapping hint //! get the current hardware mapping hint
virtual E_HARDWARE_MAPPING getHardwareMappingHint() const =0; virtual E_HARDWARE_MAPPING getHardwareMappingHint() const =0;

@ -120,14 +120,16 @@ namespace scene
virtual core::vector2df& getTCoords(u32 i) = 0; virtual core::vector2df& getTCoords(u32 i) = 0;
//! Append the vertices and indices to the current buffer //! Append the vertices and indices to the current buffer
/** Only works for compatible vertex types. /** Only works for compatible vertex types
and not implemented for most buffers for now.
\param vertices Pointer to a vertex array. \param vertices Pointer to a vertex array.
\param numVertices Number of vertices in the array. \param numVertices Number of vertices in the array.
\param indices Pointer to index array. \param indices Pointer to index array.
\param numIndices Number of indices in array. */ \param numIndices Number of indices in array. */
virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) = 0; virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) = 0;
//! Append the meshbuffer to the current buffer //! Not supported right now by any meshbuffer
//! In theory: Append the meshbuffer to the current buffer
/** Only works for compatible vertex types /** Only works for compatible vertex types
\param other Buffer to append to this one. */ \param other Buffer to append to this one. */
virtual void append(const IMeshBuffer* const other) = 0; virtual void append(const IMeshBuffer* const other) = 0;

@ -30,7 +30,7 @@ class IMeshLoader : public virtual IReferenceCounted
public: public:
//! Constructor //! Constructor
IMeshLoader() : TextureLoader(0), PreferredIndexType(video::EIT_16BIT) {} IMeshLoader() : TextureLoader(0), IndexTypeHint(EITH_OPTIMAL) {}
//! Destructor //! Destructor
virtual ~IMeshLoader() virtual ~IMeshLoader()
@ -79,30 +79,47 @@ public:
return TextureLoader; return TextureLoader;
} }
enum E_INDEX_TYPE_HINT
{
//! Prefer to use 16-bit index buffers even if it breaks the mesh
//! The default (and only option) before Irrlicht 1.9
EITH_16BIT,
//! Allow using 32-bit index buffers
EITH_32BIT,
//! Allow 32-bit, but copy back to 16-bit when 32 is not needed.
//! So tiny overhead (sometimes extra allocation+copying) on loading,
//! but meshes are later more optimal.
//! Default since Irrlicht 1.9
EITH_OPTIMAL
};
//! Give loader a hint if you would prefer 16 or 32 bit meshbuffers. //! Give loader a hint if you would prefer 16 or 32 bit meshbuffers.
/** /**
Generally Irrlicht works with 16-bit meshbuffers so far. Before Irrlicht 1.9 Irrlicht worked mostly with 16-bit meshbuffers.
Rendering 32-bit meshbuffers works, other functions like Rendering 32-bit meshbuffers works, but some functions like
mesh-writing and mesh manipulation might not work yet. mesh-writing and mesh manipulation might not work yet.
NOTE: Most loaders will ignore this hint so far, but hopefully NOTE: Most loaders will ignore this hint so far, but hopefully
will care about it in the future. will care about it in the future.
*/ */
void setPreferredIndexType(irr::video::E_INDEX_TYPE typeHint) void setIndexTypeHint(E_INDEX_TYPE_HINT typeHint)
{ {
PreferredIndexType = typeHint; IndexTypeHint = typeHint;
} }
//! Return current preference user has for the index-size of meshbuffers //! Return current preference user has for the index type of meshbuffers
/** Note that this is _not_ necessarily the type used by the meshloader */ /** Note that this is _not_ necessarily the type used by the meshloader */
irr::video::E_INDEX_TYPE getPreferredIndexType() const E_INDEX_TYPE_HINT getIndexTypeHint() const
{ {
return PreferredIndexType; return IndexTypeHint;
} }
protected: protected:
IMeshTextureLoader* TextureLoader; IMeshTextureLoader* TextureLoader;
irr::video::E_INDEX_TYPE PreferredIndexType; E_INDEX_TYPE_HINT IndexTypeHint;
}; };

@ -637,8 +637,6 @@ namespace quake3
{ {
IShader () IShader ()
: ID ( 0 ), VarGroup ( 0 ) {} : ID ( 0 ), VarGroup ( 0 ) {}
virtual ~IShader () {}
bool operator == (const IShader &other ) const bool operator == (const IShader &other ) const
{ {

@ -21,6 +21,12 @@ namespace scene
//! Pointer to first element of vertex data //! Pointer to first element of vertex data
virtual void* getData() =0; virtual void* getData() =0;
//! Const pointer to first element
virtual const void* getData() const =0;
//! Same as getData.
virtual void* pointer() { return getData(); }
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;
@ -30,16 +36,28 @@ namespace scene
//! Number of elements //! 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. //! Add vertex to end.
//* Note that if you pass another type than the currently used vertex type then information can be lost */
virtual void push_back(const video::S3DVertex &element) =0; virtual void push_back(const video::S3DVertex &element) =0;
virtual void push_back(const video::S3DVertex2TCoords &element) =0;
virtual void push_back(const video::S3DVertexTangents &element) =0;
//! Set value at index. Buffer must be already large enough that element exists.
//* Note that if you pass another type than the currently used vertex type then information can be lost */
virtual void setValue(u32 index, const video::S3DVertex &value) =0;
virtual void setValue(u32 index, const video::S3DVertex2TCoords &value) =0;
virtual void setValue(u32 index, const video::S3DVertexTangents &value) =0;
//! Direct access to elements. Risky to use!
/** The reference _must_ be cast to the correct type before use. It's only video::S3DVertex if getType is EVT_STANDARD.
otherwise cast it first to a reference type derived from S3DVertex like S3DVertex2TCoords& or S3DVertexTangents&. */
virtual video::S3DVertex& operator [](u32 index) = 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 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 void set_used(u32 usedNow) =0;
virtual video::S3DVertex* pointer() =0; virtual void reallocate(u32 new_size, bool canShrink=true) =0;
virtual u32 allocated_size() const =0;
//! get the current hardware mapping hint //! get the current hardware mapping hint
virtual E_HARDWARE_MAPPING getHardwareMappingHint() const =0; virtual E_HARDWARE_MAPPING getHardwareMappingHint() const =0;

@ -44,7 +44,7 @@ const char* const sBuiltInVertexTypeNames[] =
struct S3DVertex struct S3DVertex
{ {
//! default constructor //! default constructor
S3DVertex() {} S3DVertex() : Color(0xffffffff) {}
//! constructor //! constructor
S3DVertex(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv) S3DVertex(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv)
@ -142,7 +142,7 @@ struct S3DVertex2TCoords : public S3DVertex
: S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords) {} : S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords) {}
//! constructor from S3DVertex //! constructor from S3DVertex
S3DVertex2TCoords(S3DVertex& o) : S3DVertex(o) {} S3DVertex2TCoords(const S3DVertex& o) : S3DVertex(o) {}
//! Second set of texture coordinates //! Second set of texture coordinates
core::vector2d<f32> TCoords2; core::vector2d<f32> TCoords2;
@ -214,6 +214,9 @@ struct S3DVertexTangents : public S3DVertex
const core::vector3df& binormal=core::vector3df()) const core::vector3df& binormal=core::vector3df())
: S3DVertex(pos, normal, c, tcoords), Tangent(tangent), Binormal(binormal) { } : S3DVertex(pos, normal, c, tcoords), Tangent(tangent), Binormal(binormal) { }
//! constructor from S3DVertex
S3DVertexTangents(const S3DVertex& o) : S3DVertex(o) {}
//! Tangent vector along the x-axis of the texture //! Tangent vector along the x-axis of the texture
core::vector3df Tangent; core::vector3df Tangent;

@ -289,9 +289,8 @@ namespace video
We (mostly) avoid dynamic memory in SMaterial, so the extra memory We (mostly) avoid dynamic memory in SMaterial, so the extra memory
will still be allocated. But by lowering MATERIAL_MAX_TEXTURES_USED the will still be allocated. But by lowering MATERIAL_MAX_TEXTURES_USED the
material comparisons and assignments can be faster. Also several other material comparisons can be faster. Also several other places in the
places in the engine can be faster when reducing this value to the limit engine can be faster when reducing this value to the limit you need.
you need.
NOTE: This should only be changed once and before any call to createDevice. NOTE: This should only be changed once and before any call to createDevice.
NOTE: Do not set it below 1 or above the value of _IRR_MATERIAL_MAX_TEXTURES_. NOTE: Do not set it below 1 or above the value of _IRR_MATERIAL_MAX_TEXTURES_.
@ -318,63 +317,6 @@ namespace video
FogEnable(false), NormalizeNormals(false), UseMipMaps(true) FogEnable(false), NormalizeNormals(false), UseMipMaps(true)
{ } { }
//! Copy constructor
/** \param other Material to copy from. */
SMaterial(const SMaterial& other)
{
// These pointers are checked during assignment
for (u32 i=0; i<MATERIAL_MAX_TEXTURES_USED; ++i)
TextureLayer[i].TextureMatrix = 0;
*this = other;
}
//! Assignment operator
/** \param other Material to copy from. */
SMaterial& operator=(const SMaterial& other)
{
// Check for self-assignment!
if (this == &other)
return *this;
MaterialType = other.MaterialType;
AmbientColor = other.AmbientColor;
DiffuseColor = other.DiffuseColor;
EmissiveColor = other.EmissiveColor;
SpecularColor = other.SpecularColor;
Shininess = other.Shininess;
MaterialTypeParam = other.MaterialTypeParam;
MaterialTypeParam2 = other.MaterialTypeParam2;
Thickness = other.Thickness;
for (u32 i=0; i<MATERIAL_MAX_TEXTURES_USED; ++i)
{
TextureLayer[i] = other.TextureLayer[i];
}
Wireframe = other.Wireframe;
PointCloud = other.PointCloud;
GouraudShading = other.GouraudShading;
Lighting = other.Lighting;
ZWriteEnable = other.ZWriteEnable;
BackfaceCulling = other.BackfaceCulling;
FrontfaceCulling = other.FrontfaceCulling;
FogEnable = other.FogEnable;
NormalizeNormals = other.NormalizeNormals;
ZBuffer = other.ZBuffer;
AntiAliasing = other.AntiAliasing;
ColorMask = other.ColorMask;
ColorMaterial = other.ColorMaterial;
BlendOperation = other.BlendOperation;
BlendFactor = other.BlendFactor;
PolygonOffsetFactor = other.PolygonOffsetFactor;
PolygonOffsetDirection = other.PolygonOffsetDirection;
PolygonOffsetDepthBias = other.PolygonOffsetDepthBias;
PolygonOffsetSlopeScale = other.PolygonOffsetSlopeScale;
UseMipMaps = other.UseMipMaps;
return *this;
}
//! Texture layer array. //! Texture layer array.
SMaterialLayer TextureLayer[MATERIAL_MAX_TEXTURES]; SMaterialLayer TextureLayer[MATERIAL_MAX_TEXTURES];

@ -140,9 +140,6 @@ class map
reset(); reset();
} }
// Copy constructor
Iterator(const Iterator& src) : Root(src.Root), Cur(src.Cur) {}
void reset(bool atLowest=true) void reset(bool atLowest=true)
{ {
if (atLowest) if (atLowest)
@ -161,13 +158,6 @@ class map
return Cur; return Cur;
} }
Iterator& operator=(const Iterator& src)
{
Root = src.Root;
Cur = src.Cur;
return (*this);
}
void operator++(int) void operator++(int)
{ {
inc(); inc();
@ -287,8 +277,7 @@ class map
reset(); reset();
} }
// Copy constructor // Constructor(Iterator)
ConstIterator(const ConstIterator& src) : Root(src.Root), Cur(src.Cur) {}
ConstIterator(const Iterator& src) : Root(src.Root), Cur(src.Cur) {} ConstIterator(const Iterator& src) : Root(src.Root), Cur(src.Cur) {}
void reset(bool atLowest=true) void reset(bool atLowest=true)
@ -309,13 +298,6 @@ class map
return Cur; return Cur;
} }
ConstIterator& operator=(const ConstIterator& src)
{
Root = src.Root;
Cur = src.Cur;
return (*this);
}
void operator++(int) void operator++(int)
{ {
inc(); inc();

@ -27,8 +27,6 @@ public:
vector2d(T nx, T ny) : X(nx), Y(ny) {} vector2d(T nx, T ny) : X(nx), Y(ny) {}
//! Constructor with the same value for both members //! Constructor with the same value for both members
explicit vector2d(T n) : X(n), Y(n) {} explicit vector2d(T n) : X(n), Y(n) {}
//! Copy constructor
vector2d(const vector2d<T>& other) : X(other.X), Y(other.Y) {}
vector2d(const dimension2d<T>& other) : X(other.Width), Y(other.Height) {} vector2d(const dimension2d<T>& other) : X(other.Width), Y(other.Height) {}
@ -36,8 +34,6 @@ public:
vector2d<T> operator-() const { return vector2d<T>(-X, -Y); } vector2d<T> operator-() const { return vector2d<T>(-X, -Y); }
vector2d<T>& operator=(const vector2d<T>& other) { X = other.X; Y = other.Y; return *this; }
vector2d<T>& operator=(const dimension2d<T>& other) { X = other.Width; Y = other.Height; return *this; } vector2d<T>& operator=(const dimension2d<T>& other) { X = other.Width; Y = other.Height; return *this; }
vector2d<T> operator+(const vector2d<T>& other) const { return vector2d<T>(X + other.X, Y + other.Y); } vector2d<T> operator+(const vector2d<T>& other) const { return vector2d<T>(X + other.X, Y + other.Y); }

@ -28,15 +28,11 @@ namespace core
vector3d(T nx, T ny, T nz) : X(nx), Y(ny), Z(nz) {} vector3d(T nx, T ny, T nz) : X(nx), Y(ny), Z(nz) {}
//! Constructor with the same value for all elements //! Constructor with the same value for all elements
explicit vector3d(T n) : X(n), Y(n), Z(n) {} explicit vector3d(T n) : X(n), Y(n), Z(n) {}
//! Copy constructor
vector3d(const vector3d<T>& other) : X(other.X), Y(other.Y), Z(other.Z) {}
// operators // operators
vector3d<T> operator-() const { return vector3d<T>(-X, -Y, -Z); } vector3d<T> operator-() const { return vector3d<T>(-X, -Y, -Z); }
vector3d<T>& operator=(const vector3d<T>& other) { X = other.X; Y = other.Y; Z = other.Z; return *this; }
vector3d<T> operator+(const vector3d<T>& other) const { return vector3d<T>(X + other.X, Y + other.Y, Z + other.Z); } vector3d<T> operator+(const vector3d<T>& other) const { return vector3d<T>(X + other.X, Y + other.Y, Z + other.Z); }
vector3d<T>& operator+=(const vector3d<T>& other) { X+=other.X; Y+=other.Y; Z+=other.Z; return *this; } vector3d<T>& operator+=(const vector3d<T>& other) { X+=other.X; Y+=other.Y; Z+=other.Z; return *this; }
vector3d<T> operator+(const T val) const { return vector3d<T>(X + val, Y + val, Z + val); } vector3d<T> operator+(const T val) const { return vector3d<T>(X + val, Y + val, Z + val); }

@ -136,7 +136,8 @@ bool CB3DMeshFileLoader::load()
else else
{ {
os::Printer::log("Unknown chunk found in mesh base - skipping"); os::Printer::log("Unknown chunk found in mesh base - skipping");
B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length); if (!B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length))
return false;
B3dStack.erase(B3dStack.size()-1); B3dStack.erase(B3dStack.size()-1);
} }
} }
@ -232,7 +233,8 @@ bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *inJoint)
else else
{ {
os::Printer::log("Unknown chunk found in node chunk - skipping"); os::Printer::log("Unknown chunk found in node chunk - skipping");
B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length); if (!B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length))
return false;
B3dStack.erase(B3dStack.size()-1); B3dStack.erase(B3dStack.size()-1);
} }
} }
@ -315,7 +317,8 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *inJoint)
else else
{ {
os::Printer::log("Unknown chunk found in mesh - skipping"); os::Printer::log("Unknown chunk found in mesh - skipping");
B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length); if (!B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length))
return false;
B3dStack.erase(B3dStack.size()-1); B3dStack.erase(B3dStack.size()-1);
} }
} }
@ -859,7 +862,7 @@ bool CB3DMeshFileLoader::readChunkBRUS()
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats
{ {
// This is what blitz basic calls a brush, like a Irrlicht Material // This is what blitz basic calls a brush, like an Irrlicht material
core::stringc name; core::stringc name;
readString(name); readString(name);
@ -933,7 +936,7 @@ bool CB3DMeshFileLoader::readChunkBRUS()
} }
} }
//If a preceeding texture slot is empty move the others down: //If a preceding texture slot is empty move the others down:
for (i=num_textures; i>0; --i) for (i=num_textures; i>0; --i)
{ {
for (u32 j=i-1; j<num_textures-1; ++j) for (u32 j=i-1; j<num_textures-1; ++j)

@ -255,7 +255,9 @@ bool CB3DMeshWriter::writeMesh(io::IWriteFile* file, IMesh* const mesh, s32 flag
file->write(&i, 4); file->write(&i, 4);
u32 numIndices = mb->getIndexCount(); u32 numIndices = mb->getIndexCount();
const u16 * const idx = (u16 *) mb->getIndices(); if ( mb->getIndexType() == video::EIT_16BIT )
{
const u16 * const idx = mb->getIndices();
for (u32 j = 0; j < numIndices; j += 3) for (u32 j = 0; j < numIndices; j += 3)
{ {
u32 tmp = idx[j] + currentMeshBufferIndex; u32 tmp = idx[j] + currentMeshBufferIndex;
@ -267,6 +269,22 @@ bool CB3DMeshWriter::writeMesh(io::IWriteFile* file, IMesh* const mesh, s32 flag
tmp = idx[j + 2] + currentMeshBufferIndex; tmp = idx[j + 2] + currentMeshBufferIndex;
file->write(&tmp, sizeof(u32)); file->write(&tmp, sizeof(u32));
} }
}
else if ( mb->getIndexType() == video::EIT_32BIT )
{
const u32 * const idx = (const u32*) mb->getIndices();
for (u32 j = 0; j < numIndices; j += 3)
{
u32 tmp = idx[j] + currentMeshBufferIndex;
file->write(&tmp, sizeof(u32));
tmp = idx[j + 1] + currentMeshBufferIndex;
file->write(&tmp, sizeof(u32));
tmp = idx[j + 2] + currentMeshBufferIndex;
file->write(&tmp, sizeof(u32));
}
}
writeSizeFrom(file, trisSizeAdress+4, trisSizeAdress); // TRIS chunk size writeSizeFrom(file, trisSizeAdress+4, trisSizeAdress); // TRIS chunk size
currentMeshBufferIndex += mb->getVertexCount(); currentMeshBufferIndex += mb->getVertexCount();

@ -1217,7 +1217,7 @@ void CGUITable::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWri
Column column; Column column;
label = "Column"; label += i; label += "name"; label = "Column"; label += i; label += "name";
column.Name = core::stringw(in->getAttributeAsString(label.c_str()).c_str()); column.Name = in->getAttributeAsStringW(label.c_str());
label = "Column"; label += i; label += "width"; label = "Column"; label += i; label += "width";
column.Width = in->getAttributeAsInt(label.c_str()); column.Width = in->getAttributeAsInt(label.c_str());
label = "Column"; label += i; label += "OrderingMode"; label = "Column"; label += i; label += "OrderingMode";
@ -1252,7 +1252,7 @@ void CGUITable::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWri
Cell cell; Cell cell;
label = "Row"; label += i; label += "cell"; label += c; label += "text"; label = "Row"; label += i; label += "cell"; label += c; label += "text";
cell.Text = core::stringw(in->getAttributeAsString(label.c_str()).c_str()); cell.Text = in->getAttributeAsStringW(label.c_str());
breakText( cell.Text, cell.BrokenText, Columns[c].Width ); breakText( cell.Text, cell.BrokenText, Columns[c].Width );
label = "Row"; label += i; label += "cell"; label += c; label += "color"; label = "Row"; label += i; label += "cell"; label += c; label += "color";
cell.Color = in->getAttributeAsColor(label.c_str()); cell.Color = in->getAttributeAsColor(label.c_str());

@ -821,6 +821,8 @@ void CIrrDeviceMacOSX::setResize(int width, int height)
{ {
NSRect driverFrame = [Window contentRectForFrameRect:[Window frame]]; NSRect driverFrame = [Window contentRectForFrameRect:[Window frame]];
getVideoDriver()->OnResize(core::dimension2d<u32>( (s32)driverFrame.size.width, (s32)driverFrame.size.height)); getVideoDriver()->OnResize(core::dimension2d<u32>( (s32)driverFrame.size.width, (s32)driverFrame.size.height));
DeviceWidth = (s32)driverFrame.size.width;
DeviceHeight = (s32)driverFrame.size.height;
} }
else else
getVideoDriver()->OnResize(core::dimension2d<u32>( (s32)width, (s32)height)); getVideoDriver()->OnResize(core::dimension2d<u32>( (s32)width, (s32)height));

@ -52,14 +52,14 @@ bool CMemoryReadFile::seek(long finalPos, bool relativeMovement)
{ {
if (relativeMovement) if (relativeMovement)
{ {
if (Pos + finalPos > Len) if (Pos + finalPos < 0 || Pos + finalPos > Len)
return false; return false;
Pos += finalPos; Pos += finalPos;
} }
else else
{ {
if (finalPos > Len) if (finalPos < 0 || finalPos > Len)
return false; return false;
Pos = finalPos; Pos = finalPos;
@ -133,14 +133,14 @@ bool CMemoryWriteFile::seek(long finalPos, bool relativeMovement)
{ {
if (relativeMovement) if (relativeMovement)
{ {
if (Pos + finalPos > Len) if (Pos + finalPos < 0 || Pos + finalPos > Len)
return false; return false;
Pos += finalPos; Pos += finalPos;
} }
else else
{ {
if (finalPos > Len) if (finalPos < 0 || finalPos > Len)
return false; return false;
Pos = finalPos; Pos = finalPos;

@ -82,7 +82,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
core::array<core::vector3df, core::irrAllocatorFast<core::vector3df> > normalsBuffer(1000); core::array<core::vector3df, core::irrAllocatorFast<core::vector3df> > normalsBuffer(1000);
core::array<core::vector2df, core::irrAllocatorFast<core::vector2df> > textureCoordBuffer(1000); core::array<core::vector2df, core::irrAllocatorFast<core::vector2df> > textureCoordBuffer(1000);
SObjMtl * currMtl = new SObjMtl(PreferredIndexType); SObjMtl * currMtl = new SObjMtl(getIndexTypeHint());
Materials.push_back(currMtl); Materials.push_back(currMtl);
u32 smoothingGroup=0; u32 smoothingGroup=0;
@ -330,18 +330,20 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
{ {
if ( Materials[m]->Meshbuffer->getIndexCount() > 0 ) if ( Materials[m]->Meshbuffer->getIndexCount() > 0 )
{ {
if ( getIndexTypeHint() == EITH_OPTIMAL
&& Materials[m]->Meshbuffer->getVertexCount() <= 65536 )
{
Materials[m]->Meshbuffer->getIndexBuffer().setType(video::EIT_16BIT);
}
Materials[m]->Meshbuffer->recalculateBoundingBox(); Materials[m]->Meshbuffer->recalculateBoundingBox();
if (Materials[m]->RecalculateNormals) if (Materials[m]->RecalculateNormals)
SceneManager->getMeshManipulator()->recalculateNormals(Materials[m]->Meshbuffer); SceneManager->getMeshManipulator()->recalculateNormals(Materials[m]->Meshbuffer);
if (Materials[m]->Meshbuffer->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID) if (Materials[m]->Meshbuffer->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID)
{ {
SMesh tmp; Materials[m]->Meshbuffer->getVertexBuffer().setType(video::EVT_TANGENTS);
tmp.addMeshBuffer(Materials[m]->Meshbuffer);
IMesh* tangentMesh = SceneManager->getMeshManipulator()->createMeshWithTangents(&tmp);
mesh->addMeshBuffer(tangentMesh->getMeshBuffer(0));
tangentMesh->drop();
} }
else
mesh->addMeshBuffer( Materials[m]->Meshbuffer ); mesh->addMeshBuffer( Materials[m]->Meshbuffer );
} }
} }
@ -579,7 +581,7 @@ void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath)
c8 mtlNameBuf[WORD_BUFFER_LENGTH]; c8 mtlNameBuf[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
currMaterial = new SObjMtl(PreferredIndexType); currMaterial = new SObjMtl(getIndexTypeHint());
currMaterial->Name = mtlNameBuf; currMaterial->Name = mtlNameBuf;
} }
break; break;

@ -42,7 +42,9 @@ private:
struct SObjMtl struct SObjMtl
{ {
SObjMtl(irr::video::E_INDEX_TYPE indexType) : IndexType(indexType), Meshbuffer(0), Bumpiness (1.0f), Illumination(0), SObjMtl(E_INDEX_TYPE_HINT typeHint)
: IndexType(typeHint == EITH_16BIT ? video::EIT_16BIT : video::EIT_32BIT)
, Meshbuffer(0), Bumpiness (1.0f), Illumination(0),
RecalculateNormals(false) RecalculateNormals(false)
{ {
Meshbuffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, IndexType); Meshbuffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, IndexType);

@ -8,7 +8,8 @@
#include "CSTLMeshFileLoader.h" #include "CSTLMeshFileLoader.h"
#include "SMesh.h" #include "SMesh.h"
#include "SMeshBuffer.h" #include "CDynamicMeshBuffer.h"
#include "CMemoryFile.h"
#include "SAnimatedMesh.h" #include "SAnimatedMesh.h"
#include "IReadFile.h" #include "IReadFile.h"
#include "fast_atof.h" #include "fast_atof.h"
@ -34,14 +35,29 @@ bool CSTLMeshFileLoader::isALoadableFileExtension(const io::path& filename) cons
//! \return Pointer to the created mesh. Returns 0 if loading failed. //! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information. //! See IReferenceCounted::drop() for more information.
IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file) IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* fileIn)
{ {
const long filesize = file->getSize(); const long filesize = fileIn->getSize();
if (filesize < 6) // we need a header if (filesize < 6) // we need a header
return 0; return 0;
// We copy the whole file into a memory-read file if it isn't already one.
io::CMemoryReadFile * memoryFile = 0;
if ( fileIn->getType() != io::ERFT_MEMORY_READ_FILE )
{
u8* fileBuffer = new u8[filesize];
if ( fileIn->read(fileBuffer, filesize) != (size_t)filesize )
{
delete[] fileBuffer;
return 0;
}
memoryFile = new io::CMemoryReadFile(fileBuffer, filesize, io::path(""), true); // takes over fileBuffer
}
io::IReadFile* file = memoryFile ? memoryFile : fileIn;
SMesh* mesh = new SMesh(); SMesh* mesh = new SMesh();
SMeshBuffer* meshBuffer = new SMeshBuffer(); CDynamicMeshBuffer* meshBuffer = new CDynamicMeshBuffer(video::EVT_STANDARD, video::EIT_16BIT);
IVertexBuffer& vertBuffer = meshBuffer->getVertexBuffer();
mesh->addMeshBuffer(meshBuffer); mesh->addMeshBuffer(meshBuffer);
meshBuffer->drop(); meshBuffer->drop();
@ -49,8 +65,7 @@ IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file)
core::vector3df normal; core::vector3df normal;
bool binary = false; bool binary = false;
core::stringc token; if (getNextToken(file) != "solid")
if (getNextToken(file, token) != "solid")
binary = true; binary = true;
// read/skip header // read/skip header
u32 binFaceCount = 0; u32 binFaceCount = 0;
@ -66,62 +81,64 @@ IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file)
goNextLine(file); goNextLine(file);
u16 attrib=0; u16 attrib=0;
token.reserve(32); Token.reserve(32);
bool failure = false;
while (file->getPos() < filesize) while (file->getPos() < filesize)
{ {
if (!binary) if (!binary)
{ {
if (getNextToken(file, token) != "facet") if (getNextToken(file) != "facet")
{ {
if (token=="endsolid") if (Token!="endsolid")
failure = true;
break; break;
mesh->drop();
return 0;
} }
if (getNextToken(file, token) != "normal") if (getNextToken(file) != "normal")
{ {
mesh->drop(); failure = true;
return 0; break;
} }
} }
getNextVector(file, normal, binary); getNextVector(file, normal, binary);
if (!binary) if (!binary)
{ {
if (getNextToken(file, token) != "outer") if (getNextToken(file) != "outer")
{ {
mesh->drop(); failure = true;
return 0; break;
} }
if (getNextToken(file, token) != "loop") if (getNextToken(file) != "loop")
{ {
mesh->drop(); failure = true;
return 0; break;
} }
} }
for (u32 i=0; i<3; ++i) for (u32 i=0; i<3; ++i)
{ {
if (!binary) if (!binary)
{ {
if (getNextToken(file, token) != "vertex") if (getNextToken(file) != "vertex")
{ {
mesh->drop(); failure = true;
return 0; break;
} }
} }
getNextVector(file, vertex[i], binary); getNextVector(file, vertex[i], binary);
} }
if ( failure )
break;
if (!binary) if (!binary)
{ {
if (getNextToken(file, token) != "endloop") if (getNextToken(file) != "endloop")
{ {
mesh->drop(); failure = true;
return 0; break;
} }
if (getNextToken(file, token) != "endfacet") if (getNextToken(file) != "endfacet")
{ {
mesh->drop(); failure = true;
return 0; break;
} }
} }
else else
@ -132,41 +149,56 @@ IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file)
#endif #endif
} }
SMeshBuffer* mb = reinterpret_cast<SMeshBuffer*>(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1));
u32 vCount = mb->getVertexCount();
video::SColor color(0xffffffff); video::SColor color(0xffffffff);
if (attrib & 0x8000) if (attrib & 0x8000)
color = video::A1R5G5B5toA8R8G8B8(attrib); color = video::A1R5G5B5toA8R8G8B8(attrib);
if (normal==core::vector3df()) if (normal==core::vector3df())
normal=core::plane3df(vertex[2],vertex[1],vertex[0]).Normal; normal=core::plane3df(vertex[2],vertex[1],vertex[0]).Normal;
mb->Vertices.push_back(video::S3DVertex(vertex[2],normal,color, core::vector2df())); vertBuffer.push_back(video::S3DVertex(vertex[2],normal,color, core::vector2df()));
mb->Vertices.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df())); vertBuffer.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df()));
mb->Vertices.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df())); vertBuffer.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df()));
mb->Indices.push_back(vCount);
mb->Indices.push_back(vCount+1);
mb->Indices.push_back(vCount+2);
} // end while (file->getPos() < filesize) } // end while (file->getPos() < filesize)
mesh->getMeshBuffer(0)->recalculateBoundingBox();
// Create the Animated mesh if there's anything in the mesh // Create the Animated mesh if there's anything in the mesh
SAnimatedMesh* pAM = 0; SAnimatedMesh* pAM = 0;
if ( 0 != mesh->getMeshBufferCount() ) if ( !failure && mesh->getMeshBufferCount() > 0 )
{ {
IIndexBuffer& indexBuffer = meshBuffer->getIndexBuffer();
u32 vertCount = vertBuffer.size();
if (vertCount > 65535 ) // Note 65535 instead of 65536 as it divides by 3
{
if ( getIndexTypeHint() != EITH_16BIT )
indexBuffer.setType(video::EIT_32BIT);
else
{
// Could split buffer, but probably no one really needs this anymore now with 32-bit support and necessary buffer manipulation functions are not there yet
vertCount = 65535;
}
}
indexBuffer.reallocate(vertCount);
for (u32 i=0; i<vertCount; ++i) //every vertex is unique, so we can just generate the indices
indexBuffer.push_back(i);
meshBuffer->recalculateBoundingBox();
mesh->recalculateBoundingBox(); mesh->recalculateBoundingBox();
pAM = new SAnimatedMesh(); pAM = new SAnimatedMesh();
pAM->Type = EAMT_OBJ; pAM->Type = EAMT_STATIC;
pAM->addMesh(mesh); pAM->addMesh(mesh);
pAM->recalculateBoundingBox(); pAM->recalculateBoundingBox();
} }
mesh->drop(); mesh->drop();
Token.clear();
if ( memoryFile )
memoryFile->drop();
return pAM; return pAM;
} }
//! Read 3d vector of floats //! Read 3d vector of floats
void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary) const void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary)
{ {
if (binary) if (binary)
{ {
@ -182,34 +214,33 @@ void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vector3df& vec
else else
{ {
goNextWord(file); goNextWord(file);
core::stringc tmp;
getNextToken(file, tmp); getNextToken(file);
core::fast_atof_move(tmp.c_str(), vec.X); core::fast_atof_move(Token.c_str(), vec.X);
getNextToken(file, tmp); getNextToken(file);
core::fast_atof_move(tmp.c_str(), vec.Y); core::fast_atof_move(Token.c_str(), vec.Y);
getNextToken(file, tmp); getNextToken(file);
core::fast_atof_move(tmp.c_str(), vec.Z); core::fast_atof_move(Token.c_str(), vec.Z);
} }
vec.X=-vec.X; vec.X=-vec.X;
} }
//! Read next word //! Read next word
const core::stringc& CSTLMeshFileLoader::getNextToken(io::IReadFile* file, core::stringc& token) const const core::stringc& CSTLMeshFileLoader::getNextToken(io::IReadFile* file)
{ {
goNextWord(file); goNextWord(file);
u8 c; u8 c;
token = ""; Token = "";
while(file->getPos() != file->getSize()) while(file->getPos() != file->getSize())
{ {
file->read(&c, 1); file->read(&c, 1);
// found it, so leave // found it, so leave
if (core::isspace(c)) if (core::isspace(c))
break; break;
token.append(c); Token.append(c);
} }
return token; return Token;
} }

@ -34,12 +34,15 @@ private:
// skips to the first non-space character available // skips to the first non-space character available
void goNextWord(io::IReadFile* file) const; void goNextWord(io::IReadFile* file) const;
// returns the next word // returns the next word
const core::stringc& getNextToken(io::IReadFile* file, core::stringc& token) const; const core::stringc& getNextToken(io::IReadFile* file);
// skip to next printable character after the first line break // skip to next printable character after the first line break
void goNextLine(io::IReadFile* file) const; void goNextLine(io::IReadFile* file) const;
//! Read 3d vector of floats //! Read 3d vector of floats
void getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary) const; void getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary);
//! Buffering last read token to avoid reallocating string all the time
core::stringc Token;
}; };
} // end namespace scene } // end namespace scene

@ -92,11 +92,14 @@ bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s
{ {
const u32 indexCount = buffer->getIndexCount(); const u32 indexCount = buffer->getIndexCount();
const u16 attributes = 0; const u16 attributes = 0;
if( buffer->getIndexType() == video::EIT_16BIT )
{
const u16* indices = buffer->getIndices();
for (u32 j=0; j<indexCount; j+=3) for (u32 j=0; j<indexCount; j+=3)
{ {
const core::vector3df& v1 = buffer->getPosition(buffer->getIndices()[j]); const core::vector3df& v1 = buffer->getPosition(indices[j]);
const core::vector3df& v2 = buffer->getPosition(buffer->getIndices()[j+1]); const core::vector3df& v2 = buffer->getPosition(indices[j+1]);
const core::vector3df& v3 = buffer->getPosition(buffer->getIndices()[j+2]); const core::vector3df& v3 = buffer->getPosition(indices[j+2]);
const core::plane3df tmpplane(v1,v2,v3); const core::plane3df tmpplane(v1,v2,v3);
file->write(&tmpplane.Normal, 12); file->write(&tmpplane.Normal, 12);
file->write(&v1, 12); file->write(&v1, 12);
@ -105,6 +108,23 @@ bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s
file->write(&attributes, 2); file->write(&attributes, 2);
} }
} }
else if( buffer->getIndexType() == video::EIT_32BIT )
{
const u32* indices = (const u32*)buffer->getIndices();
for (u32 j=0; j<indexCount; j+=3)
{
const core::vector3df& v1 = buffer->getPosition(indices[j]);
const core::vector3df& v2 = buffer->getPosition(indices[j+1]);
const core::vector3df& v3 = buffer->getPosition(indices[j+2]);
const core::plane3df tmpplane(v1,v2,v3);
file->write(&tmpplane.Normal, 12);
file->write(&v1, 12);
file->write(&v2, 12);
file->write(&v3, 12);
file->write(&attributes, 2);
}
}
}
} }
return true; return true;
} }
@ -127,12 +147,27 @@ bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s3
if (buffer) if (buffer)
{ {
const u32 indexCount = buffer->getIndexCount(); const u32 indexCount = buffer->getIndexCount();
if ( buffer->getIndexType() == video::EIT_16BIT )
{
const u16* indices = buffer->getIndices();
for (u32 j=0; j<indexCount; j+=3) for (u32 j=0; j<indexCount; j+=3)
{ {
writeFace(file, writeFace(file,
buffer->getPosition(buffer->getIndices()[j]), buffer->getPosition(indices[j]),
buffer->getPosition(buffer->getIndices()[j+1]), buffer->getPosition(indices[j+1]),
buffer->getPosition(buffer->getIndices()[j+2])); buffer->getPosition(indices[j+2]));
}
}
else if ( buffer->getIndexType() == video::EIT_32BIT )
{
const u32* indices = (const u32*)buffer->getIndices();
for (u32 j=0; j<indexCount; j+=3)
{
writeFace(file,
buffer->getPosition(indices[j]),
buffer->getPosition(indices[j+1]),
buffer->getPosition(indices[j+2]));
}
} }
file->write("\n",1); file->write("\n",1);
} }

@ -760,10 +760,12 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh)
// read vertices // read vertices
mesh.Vertices.set_used(nVertices); mesh.Vertices.set_used(nVertices);
irr::video::S3DVertex vertex; // set_used doesn't call constructor, so we initalize it explicit here
vertex.Color = 0xFFFFFFFF;
for (u32 n=0; n<nVertices; ++n) for (u32 n=0; n<nVertices; ++n)
{ {
readVector3(mesh.Vertices[n].Pos); readVector3(vertex.Pos);
mesh.Vertices[n].Color=0xFFFFFFFF; mesh.Vertices[n] = vertex;
} }
if (!checkForTwoFollowingSemicolons()) if (!checkForTwoFollowingSemicolons())

@ -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 16:41:11 2022 Test suite pass at GMT Tue Apr 26 19:16:37 2022