Flexible Vertex Format - special SVN branch is ready!!!
Flexible Vertex Format - special SVN branch is ready!!!
How looks FVF support in Irrlicht?
In each, unified mesh buffer (IMeshBuffer), we had one vertex (in future we can will easy add support for many vertex buffers per mesh buffer) and index buffer (IVertexBuffer and IIndexBuffer). Each index buffer is now a dynamically, so You can easy switch between 16 and 32 bytes indices in each meshes. Vertex buffer require 2 elements, vertex structure eg. S3DVertex and 2 others built-in Irrlicht and compatible vertex descriptor (IVertexDescriptor), which include all important infos, about vertex structure. With a functions from a MeshManipulator convert vertices between a differences formats is really easy. It is important to use properly semantic, element count and type for an each vertex attribute when You define new vertex descriptor. Of course You must also prepare compatible vertex type (container class).
What is unfinished?
- createForsythOptimizedMesh method from IMeshManipulator.
Know bugs:
- None
Custom vertex structures are only supported in a Direct3D9 and OpenGL drivers. Other drivers, so Burning's Video, Software and Direct3D8 support only build-in Irrlicht vertex types, because FVF in these drivers isn't needed.
I hope that final patch will be ready soon and it will be included in Irrlicht 1.9.
You can download Irrlicht with FVF support from:
https://irrlicht.svn.sourceforge.net/sv ... -pipeline/
In each, unified mesh buffer (IMeshBuffer), we had one vertex (in future we can will easy add support for many vertex buffers per mesh buffer) and index buffer (IVertexBuffer and IIndexBuffer). Each index buffer is now a dynamically, so You can easy switch between 16 and 32 bytes indices in each meshes. Vertex buffer require 2 elements, vertex structure eg. S3DVertex and 2 others built-in Irrlicht and compatible vertex descriptor (IVertexDescriptor), which include all important infos, about vertex structure. With a functions from a MeshManipulator convert vertices between a differences formats is really easy. It is important to use properly semantic, element count and type for an each vertex attribute when You define new vertex descriptor. Of course You must also prepare compatible vertex type (container class).
What is unfinished?
- createForsythOptimizedMesh method from IMeshManipulator.
Know bugs:
- None
Custom vertex structures are only supported in a Direct3D9 and OpenGL drivers. Other drivers, so Burning's Video, Software and Direct3D8 support only build-in Irrlicht vertex types, because FVF in these drivers isn't needed.
I hope that final patch will be ready soon and it will be included in Irrlicht 1.9.
You can download Irrlicht with FVF support from:
https://irrlicht.svn.sourceforge.net/sv ... -pipeline/
Last edited by Nadro on Tue Mar 13, 2012 10:15 pm, edited 23 times in total.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
-
- Posts: 758
- Joined: Mon Mar 31, 2008 3:32 pm
- Location: Bulgaria
Hey, very nice, short and simple code. The only thing missing is the vertex type and/or vertex typename, giving the user the opportunity to set and get his own vertex type completely outside. The standard Irr types will be kept quite easily.
[0] vec3df Position
[1] vec3df Normal
[2] SColor Color
[3] vec2df TexCoord
[4] vec3df Tangent
[5] vec3df Binormal
STANDARD uses 0-2
TEXTURE uses 0-3
TANGENT uses 0-5
CUSTOM1
CUSTOM2
char* UnifVertexTypeName = "standard";
(...)
You`re simply a genious...
[0] vec3df Position
[1] vec3df Normal
[2] SColor Color
[3] vec2df TexCoord
[4] vec3df Tangent
[5] vec3df Binormal
STANDARD uses 0-2
TEXTURE uses 0-3
TANGENT uses 0-5
CUSTOM1
CUSTOM2
char* UnifVertexTypeName = "standard";
(...)
You`re simply a genious...
"Although we walk on the ground and step in the mud... our dreams and endeavors reach the immense skies..."
-
- Posts: 1186
- Joined: Fri Dec 29, 2006 12:04 am
Re: Flexible Vertex Format
Hi Nadro,
interesting code, but there's an issue.
This seems to be ok on windows using the msvc compiler. On Linux,
however, using gcc 4.4.3, the code actually generated uses plain delete, so at best there will be a memory leak and at worst undefined behaviour.
Edit: After deleting UV, the memory leak was gone. But still scary.
interesting code, but there's an issue.
Code: Select all
../source/main.cpp: In destructor 'UnifiedVertex::~UnifiedVertex()':
../source/main.cpp:64: warning: deleting 'void*' is undefined
however, using gcc 4.4.3, the code actually generated uses plain delete, so at best there will be a memory leak and at worst undefined behaviour.
Edit: After deleting UV, the memory leak was gone. But still scary.
"Whoops..."
i would simply replace the void* with a unsigned char*. that should solve the problem. actually when i think about it. what is the size of void? lol
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
-
- Posts: 1186
- Joined: Fri Dec 29, 2006 12:04 am
Yes, this solves the problem.Sudi wrote:i would simply replace the void* with a unsigned char*. that should solve the problem. actually when i think about it. what is the size of void? lol
Another improment would be to make the code const-correct.
Code: Select all
bool accessAttribute(void* const vData, const unsigned int vPosition, const E_ACCESS_TYPE& vAccessType) const
Code: Select all
bool accessAttribute(void* vData, int vPosition, E_ACCESS_TYPE vAccessType)
Thumps up!
Edit:
Here's the updated code. I made some changes:
- it is now const-correct
- it uses Irrlichts types for POD data (u32 vs int)
- uses unsigned types vs signed types, this simplifies some checks
- i moved the E_ACCESS_TYPE enum inside the class
- the using namespace directive is bad, so removed them
- delete uv, to prevent memory leak in example code
- system("Pause"); doesn't work on Linux.
Code: Select all
#include <irrlicht.h>
#include <iostream>
// Unified Vertex class.
class UnifiedVertex
{
public:
// Access types.
enum E_ACCESS_TYPE
{
EAT_READ = 0,
EAT_WRITE
};
// Constructor.
UnifiedVertex(const irr::core::array<irr::u32>& vAttribute) :
AttributesCount(vAttribute.size())
{
irr::u32 _Size = 0;
// Allocate offsets array.
Offset = new irr::u32[AttributesCount];
for(irr::u32 i = 0; i < AttributesCount; ++i)
{
Offset[i] = vAttribute[i];
_Size += Offset[i];
}
// Allocate memory for data.
Data = new irr::u8[_Size];
}
// Constructor.
UnifiedVertex(const irr::u32* vAttribute, const irr::u32 AttributeCount) :
AttributesCount(AttributeCount)
{
irr::u32 _Size = 0;
// Allocate offsets array.
Offset = new irr::u32[AttributesCount];
for(irr::u32 i = 0; i < AttributesCount; ++i)
{
Offset[i] = vAttribute[i];
_Size += Offset[i];
}
// Allocate memory for data.
Data = new irr::u8[_Size];
}
// Destructor.
~UnifiedVertex()
{
// Release allocated memory.
delete[] Offset;
delete[] Data;
}
// Access to data (write or read selected attribute).
bool accessAttribute(void* const vData, const irr::u32 vPosition, const E_ACCESS_TYPE& vAccessType) const
{
// Check avaiable offsets.
if(vPosition >= AttributesCount || !vData)
return false;
irr::u32 _Size = 0;
for(irr::u32 i = 0; i < vPosition; ++i)
_Size += Offset[i];
// Write or read data.
if(vAccessType == EAT_WRITE)
memcpy((irr::u8*)Data + _Size, vData, Offset[vPosition]);
else
memcpy(vData, (irr::u8*)Data + _Size, Offset[vPosition]);
return true;
}
// Get selected attribute offset.
irr::u32 getAttributeOffset(const irr::u32 vPosition) const
{
irr::u32 _Offset = 0;
if(vPosition < AttributesCount)
_Offset = Offset[vPosition];
return _Offset;
}
// Get attributes count.
irr::u32 getAttributesCount() const { return AttributesCount; }
private:
// Data.
irr::u8* Data;
// Array with offsets sizes.
irr::u32* Offset;
// Attributes count.
irr::u32 AttributesCount;
};
int main()
{
// Example attributes.
irr::core::vector3df Position0(10.1,11.1,12.1);
irr::core::vector3df Normal0(20.1,21.1,22.1);
irr::video::SColor Color0(10,11,12,13);
// Prepare vertex structure.
irr::core::array<irr::u32> Attribute;
Attribute.push_back(sizeof(irr::core::vector3df));
Attribute.push_back(sizeof(irr::core::vector3df));
Attribute.push_back(sizeof(irr::video::SColor));
UnifiedVertex* const uv = new UnifiedVertex(Attribute);
// Alternative method.
/*
irr::u32 Attribute[3] =
{
sizeof(irr::core::vector3df),
sizeof(irr::core::vector3df),
sizeof(irr::video::SColor)
};
UnifiedVertex* const uv = new UnifiedVertex(Attribute, 3);
*/
// Write attributes values.
uv->accessAttribute(&Position0, 0, UnifiedVertex::EAT_WRITE);
uv->accessAttribute(&Normal0, 1, UnifiedVertex::EAT_WRITE);
uv->accessAttribute(&Color0, 2, UnifiedVertex::EAT_WRITE);
// Read attributes values.
irr::core::vector3df PositionR(0,0,0);
irr::core::vector3df NormalR(0,0,0);
irr::video::SColor ColorR(0,0,0,0);
uv->accessAttribute(&PositionR, 0, UnifiedVertex::EAT_READ);
uv->accessAttribute(&NormalR, 1, UnifiedVertex::EAT_READ);
uv->accessAttribute(&ColorR, 2, UnifiedVertex::EAT_READ);
// Display attributes values.
std::cout <<
"Position: " << PositionR.X << ", " << PositionR.Y << ", " << PositionR.Z << "\n" <<
"Normal: " << NormalR.X << ", " << NormalR.Y << ", " << NormalR.Z << "\n" <<
"Color: " << ColorR.getAlpha() << ", " << ColorR.getRed() << ", " << ColorR.getGreen() << ", " << ColorR.getBlue() <<
std::endl;
delete uv;
return 0;
}
"Whoops..."
Thanks for interesting of this code. Improvments are very good, I thinked about it for final code version, but apply it to current version also is ok. Now, we can also remove casting to (irr::u8*) in memcpy code. What do You think about put the latest code at my first post? (if topic will be longer, searching the latest code will be waste of time). I put the latest code in first post, I also add getData function.
Now it's time for discussion about vertex type started by shadowslair, today I will prepare some code for it.
Now it's time for discussion about vertex type started by shadowslair, today I will prepare some code for it.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
-
- Posts: 1186
- Joined: Fri Dec 29, 2006 12:04 am
Ok, storing the data this way is a problem indeed.Dorth wrote:An unsigned vertex position?
Code: Select all
irr::core::vector3df Position0(-123456789.4, -11.1, -12.1);
Code: Select all
Position: -1.23457e+08, -11.1, -12.1
Too bad.
But this hasn't got something to do with unsigned/signed, the original code shows the same problem.
"Whoops..."
@Dorth
What do You mean?
@randomMesh
Code is ok, You get the same effect when You call:
So data is store properly.
What do You mean?
@randomMesh
Code is ok, You get the same effect when You call:
Code: Select all
irr::core::vector3df PositionTest(123456789.4,11.1,12.1);
std::cout << "Position: " << PositionTest.X << ", " << PositionTest.Y << ", " << PositionTest.Z << std::endl;
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
-
- Posts: 1186
- Joined: Fri Dec 29, 2006 12:04 am
I am afraid it is not stored properly, since −12345700000000 is a different number than -123456789.4.Nadro wrote:Code is ok, You get the same effect when You call:So data is store properly.Code: Select all
irr::core::vector3df PositionTest(123456789.4,11.1,12.1); std::cout << "Position: " << PositionTest.X << ", " << PositionTest.Y << ", " << PositionTest.Z << std::endl;
"Whoops..."
It's ok, this is cause by precision rounding (vector3d<f32>).
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Hey there seams to be an error in the code.
this just seams wrong to me. correct me if i am.
when a function is declared const it means that it WON'T modify data of the object right? so this is wrong when u call the function with EAT_WRITE.
Then again "void* const vData" didn't try it but is there a difference between const void* and void* const? anyway writing to that data is actually not allowed.
EDIT: nevermind read it up....its a const pointer....totaly useless
while we are at it.
"const irr::u32 vPosition" should be "const irr::u32& vPosition"
"const irr::u32 AttributeCount" should be "const irr::u32& AttributeCount"
"irr::u32 getAttributesCount() const { return AttributesCount; } " should be "const irr::u32& getAttributesCount() const { return AttributesCount; } "
Code: Select all
bool accessAttribute(void* const vData, const irr::u32 vPosition, const E_ACCESS_TYPE& vAccessType) const
when a function is declared const it means that it WON'T modify data of the object right? so this is wrong when u call the function with EAT_WRITE.
Then again "void* const vData" didn't try it but is there a difference between const void* and void* const? anyway writing to that data is actually not allowed.
EDIT: nevermind read it up....its a const pointer....totaly useless
while we are at it.
"const irr::u32 vPosition" should be "const irr::u32& vPosition"
"const irr::u32 AttributeCount" should be "const irr::u32& AttributeCount"
"irr::u32 getAttributesCount() const { return AttributesCount; } " should be "const irr::u32& getAttributesCount() const { return AttributesCount; } "
Last edited by sudi on Sun May 09, 2010 6:43 pm, edited 1 time in total.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
-
- Posts: 1186
- Joined: Fri Dec 29, 2006 12:04 am
Of course.Sudi wrote:is there a difference between const void* and void* const?
Code: Select all
int* foo; //pointer to an int
const int* foo; //pointer to a constant int
int* const foo; //constant pointer to an int
const int* const foo; // constant pointer to a constant int
No. You don't need references when dealing with POT, only for own data types.Sudi wrote: "const irr::u32 vPosition" should be "const irr::u32& vPosition"
"const irr::u32 AttributeCount" should be "const irr::u32& AttributeCount"
...
Being const-correct is not useless.Sudi wrote: EDIT: nevermind read it up....its a const pointer....totaly useless
Last edited by randomMesh on Sun May 09, 2010 6:46 pm, edited 2 times in total.
"Whoops..."
yeah just found that same article...
well when i don't use a reference then the const is pointless. i can't change the var from the outside anyway. ok i could change it inside the call but yeah...wellrandomMesh wrote: No. You don't need references when dealing with POT, only for own data types.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
well but still the accessAttribute function shouldn't be const.randomMesh wrote:Being const-correct is not useless.Sudi wrote:is there a difference between const void* and void* const?
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.