Code: Select all
#include <iostream>
#include "irrlicht.h"
// Attribute Types.
enum E_ATTRIBURE_TYPE
{
EAT_POSITION = 0, //vector3df
EAT_BLEND_WEIGHT, // f32[4]
EAT_BLEND_INDICES, // f32[4]
EAT_NORMAL, //vector3df
EAT_TEXCOORD0, //vector2df
EAT_TEXCOORD1, //vector2df
EAT_TEXCOORD2, //vector2df
EAT_TEXCOORD3, //vector2df
EAT_TEXCOORD4, //vector2df
EAT_TEXCOORD5, //vector2df
EAT_TEXCOORD6, //vector2df
EAT_TEXCOORD7, //vector2df
EAT_TANGENT, //vector3df
EAT_BINORMAL, //vector3df
EAT_COLOR, //SColor
EAT_XYZWI, // u32[4]
EAT_XYZI, // u32[3]
EAT_XYI, // u32[2]
EAT_XI, // u32
EAT_XYZWF, // f32[4]
EAT_XYZF, // f32[3]
EAT_XYF, // f32[2]
EAT_XF, // f32
EAT_UNDECLARED // s32, it tell our that with vertex attribute it's something wrong.
};
// Attribute Offset Types (more friendly for switch-case selecting, which we will use eg. for OpenGL VBO's).
enum E_ATTRIBURE_OFFSET_TYPE
{
EAOT_XYZWI = 0, // int, 4 x 4 bytes
EAOT_XYZI, // int, 3 x 4 bytes
EAOT_XYI, // int, 2 x 4 bytes
EAOT_XI, // int, 1 x 4 bytes
EAOT_XYZWF, // float, 4 x 4 bytes
EAOT_XYZF, // float, 3 x 4 bytes
EAOT_XYF, // float, 2 x 4 bytes
EAOT_XF, // float, 1 x 4 bytes
EAOT_XU, // unsigned, 1 x 4 bytes for SColor
EAOT_UNDECLARED // s32, it tell our that with vertex attribute it's something wrong.
};
// Flexible Vertex class. We store all vertices inside the mesh buffer in this way.
class IFlexibleVertex
{
public:
virtual irr::u32 getAttributeOffset(const irr::u32 vID) const = 0;
virtual E_ATTRIBURE_TYPE getAttributeType(const irr::u32 vID) const = 0;
virtual E_ATTRIBURE_OFFSET_TYPE getAttributeOffsetType(const irr::u32 vID) const = 0;
virtual irr::u32 getAttributesCount(const irr::u32 vID) const = 0;
};
// Our standard vertex type. Other types we will create in this way.
class SVertex : public IFlexibleVertex
{
public:
SVertex() :
Position(irr::core::vector3df(0.0f, 0.0f, 0.0f)),
Normal(irr::core::vector3df(0.0f, 0.0f, 0.0f)),
Color(irr::video::SColor(0, 0 ,0 ,0))
{
}
SVertex(const irr::core::vector3df& vPosition, const irr::core::vector3df& vNormal, const irr::video::SColor& vColor) :
Position(vPosition), Normal(vNormal), Color(vColor)
{
}
irr::u32 getAttributeOffset(const irr::u32 vID) const
{
irr::u32 _Offset = 0;
switch(vID)
{
case 0:
_Offset = sizeof(irr::core::vector3df);
break;
case 1:
_Offset = sizeof(irr::core::vector3df);
break;
case 2:
_Offset = sizeof(irr::video::SColor);
break;
default:
_Offset = 0;
break;
}
return _Offset;
}
E_ATTRIBURE_TYPE getAttributeType(const irr::u32 vID) const
{
E_ATTRIBURE_TYPE _Type = EAT_UNDECLARED;
switch(vID)
{
case 0:
_Type = EAT_POSITION;
break;
case 1:
_Type = EAT_NORMAL;
break;
case 2:
_Type = EAT_COLOR;
break;
default:
_Type = EAT_UNDECLARED;
break;
}
return _Type;
}
E_ATTRIBURE_OFFSET_TYPE getAttributeOffsetType(const irr::u32 vID) const
{
E_ATTRIBURE_OFFSET_TYPE _Type = EAOT_UNDECLARED;
switch(vID)
{
case 0:
_Type = EAOT_XYZF;
break;
case 1:
_Type = EAOT_XYZF;
break;
case 2:
_Type = EAOT_XU;
break;
default:
_Type = EAOT_UNDECLARED;
break;
}
return _Type;
}
irr::u32 getAttributesCount(const irr::u32 vID) const
{
return 3;
}
irr::core::vector3df Position;
irr::core::vector3df Normal;
irr::video::SColor Color;
};
class IFlexibleMeshBuffer
{
public:
virtual void* getArray() = 0;
virtual void* getData() = 0;
virtual irr::u32 getVerticesCount() const = 0;
};
template <class T>
class SFlexibleMeshBuffer : public IFlexibleMeshBuffer
{
public:
~SFlexibleMeshBuffer()
{
Vertices.clear();
}
void* getArray()
{
return &Vertices;
};
void* getData()
{
return Vertices.pointer();
};
irr::u32 getVerticesCount() const
{
return Vertices.size();
}
private:
irr::core::array<T> Vertices;
};
// Write attributes.
void writeAttributes(IFlexibleMeshBuffer* MeshBuffer)
{
irr::core::vector3df Position[3] =
{
irr::core::vector3df(10.1f,11.1f,12.1f),
irr::core::vector3df(100.1f,110.1f,120.1f),
irr::core::vector3df(1000.1f,1100.1f,1200.1f)
};
irr::core::vector3df Normal[3] =
{
irr::core::vector3df(20.1f,21.1f,22.1f),
irr::core::vector3df(200.1f,210.1f,220.1f),
irr::core::vector3df(2000.1f,2100.1f,2200.1f)
};
irr::video::SColor Color[3] =
{
irr::video::SColor(10,11,12,13),
irr::video::SColor(100,110,120,130),
irr::video::SColor(200,210,220,230)
};
// Get array.
irr::core::array<SVertex>* Vertices = (irr::core::array<SVertex>*)MeshBuffer->getArray();
// Add vertex to our array.
for(irr::u32 i = 0; i < 3; ++i)
{
SVertex Vertex(Position[i], Normal[i], Color[i]);
Vertices->push_back(Vertex);
}
}
// Read and display attributes.
void readAndDisplayAttributes(IFlexibleMeshBuffer* MeshBuffer)
{
// Get data.
void* Data = MeshBuffer->getData();
for(irr::u32 i = 0; i < MeshBuffer->getVerticesCount(); ++i)
{
// We can also select properly types thanks to IFlexibleVertex functions, but it will be more costly (switch-case).
irr::core::vector3df Position(0.0f,0.0f,0.0f);
irr::core::vector3df Normal(0.0f,0.0f,0.0f);
irr::video::SColor Color(0,0,0,0);
// Mostly time we needn't acces to simple vertex attribute (for send data to GPU we will use pointer to vertices array with offsets), but we can do it in this way:
SVertex* Vertex = ((SVertex*)Data +i);
Position = Vertex->Position;
Normal = Vertex->Normal;
Color = Vertex->Color;
// Display
std::cout << "Position" << i << ": " << Position.X << ", " << Position.Y << ", " << Position.Z << std::endl;
std::cout << "Normal" << i << ": " << Normal.X << ", " << Normal.Y << ", " << Normal.Z << std::endl;
std::cout << "Color" << i << ": " << Color.getAlpha() << ", " << Color.getRed() << ", " << Color.getGreen() << ", " << Color.getBlue() << std::endl << std::endl;
}
}
int main()
{
// Create Mesh Buffer.
IFlexibleMeshBuffer* MeshBuffer = new SFlexibleMeshBuffer<SVertex>();
// Write attributes.
writeAttributes(MeshBuffer);
// Read and display attributes.
readAndDisplayAttributes(MeshBuffer);
// Delete Mesh Buffer;
delete MeshBuffer;
system("Pause");
return 0;
}
In this solution create new vertex type need some more programmer work (see SVertex class), but memory mangament is very similar to current Irrlicht system. Inside engine we will use IFlexibleMeshBuffer and IFlexibleVertex and at loader stage predefined S3DVertex or others. I think that this solution is very similar to our current vertex, but programmer can add Your own vertex types in easy way.
I showed implementation for 3 different solution about flexible vertex problem. Now we must compare each and select the best.
We need talk about E_ATTRIBURE_TYPE and E_ATTRIBURE_OFFSET_TYPE members (these enums will be usefull also for previous systems).