OpenGL 3.x - Early preview stage avaiable

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

OpenGL 3.x - Early preview stage avaiable

Post by Nadro »

Hi,

I'm working on OpenGL 3.0 (Forward Compatible) driver for Irrlicht and I have some question about vertex format. In my opinion we should use one, unified vertex format instead of current S3DVertex, S3DVertex2TCoords and S3DVertexTangents. This is my proposal:

1. Positions
2. Normals
3. TexCoord0
4. TexCoord1
5. Tangents
6. Binormals
7. Weights
8. Bone Index
9. Diffuse Color
10 - 15. X (maybe have You got some proposal for this empty attribs?)

I ask about it now, because I don't attempted prebuild it this part n-times, for other vertex structures, so I wish consult it with Irrlicht Developers at first.

BTW. What do You think about 2 smaller VBOs, first for eg for Positions, Normals, TexCoord0, Tangents, Binormals and second for Weights, Bones, Diffuse Color, TexCoord1 and X, instead of 1 VBO bigger for all this elements? What should be better?
Last edited by Nadro on Fri Apr 30, 2010 12:24 am, edited 2 times in total.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

There's no way to replace the existing vertex formats, because your proposal is far too large for e.g. embedded platforms. Adding such a vertex format might be possible, though the current methods might need a replacement with some template mechanism to avoid many more cases to handle all vertex formats.
BTW: Why is color so far behind, which does not match the existing formats?

Two VBOs seems only half-hearted. Why not add a flag which allows to define the fields that need to be updated? This would allow an efficient buffer map.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Hmmm... It require only some "extra" bytes for each vertex, but this is only one disadvantage. I don't think that it will cause problem on embedded platforms, because for that platforms weuse mostly very low poly meshes, so we don't have too much vertex data in RAM. I think that we should remember about optimal usage the latest hardware, and old platforms should go on second plan.

In question for 1 VBO vs 2 VBOs, I thinked more about too small VBO or too large VBO, so I suggest 2 VBOs, but flag mechanism isn't bad idea.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Well, memory usage is always discussed, some people even request vertex formats with just position and color or position and normal to save some memory and/or bandwidth.
I don't get your point with the 2 VBOs, which VBOs are too large or too small?
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Alternative is create 2 vertex formats: Standard (Position, Normal, TexCoord) and Extended (All infos), but I don't think that it's require... Extended vertex format will be problem only in very extreme situations.

Too small VBO -> too many calls eg. glBindBuffer etc, because we have more smaller VBOs.
Too big VBO -> GL_OUT_OF_MEMORY error

But I think that it will be not problem, so fact, 1 VBO with Flags for update will be ok. Other option is create 2 VBOs, first for static data (Color, TexCoords etc.) and potentially dynamic data (Position, Normals etc), so we can always use GL_STATIC_DRAW for static data and change settings only for dynamic part, this option don't require flags, this isn't better solution?

BTW. For manage VBOs in OGL3.0, I of course use VAO, which are very good function.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

Coincidentally, I'm also currently working on the issue of vertex formats. I implemented Cal3D hardware skinning and then had to work out where in the vertex to put the blend weights and indices. Rather than hack something in I decided to design a vertex declaration API.

What I had in mind was a vertex declaration api where the user has full control over the size/type/order of the components they want in the buffer. Basically I was going to implement an api-agnostic api based on how DX9/10/11 handle it. A stream-api for Irrlicht would also be required to plug vertex buffers into streams.

Basically, the user puts together a vertex declaration struct and uses this to create the vertex buffer. There will be three built-in structs for the three existing Irrlicht vertex formats.

OK, so what benefits would be derived from this?
Namely:
  • control of vertex size - get the size you want with no wastage
    multiple streams - mix static and dynamic buffers in one vertex
    specify data size - half-float data, DWORD skin indices, etc.
    OpenCL/DirectCompute/CUDA ready
This may well be an Irrlicht 2.0 thing. I haven't looked deeply into the internals changes needed but I would envisage it could well be backward-breaking.
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

Well i proposed such a flexible vertexformat as well (look at 2.2.2 in http://www.7bitfaster.de/downloads/irrl ... iative.pdf ). Such a vertexformat would NOT break the backwards compatibility but without a working patch this idea was refused...
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Well, without the patch the idea is just an idea. I don't think that it was rejected, but postponed to a point where a working implementation of a flexible vertex format is proposed. And this might pretty much break backwards compatibility, because the old types might not work as before, e.g. access to members might be quite different. This would probably break most existing apps. Even though it might be less problematic than changes like constness in OnEvent, because not too many apps will directly access vertex properties, and most apps don't write their own mesh loaders etc.
I'd really like to have a better vertex format support in Irrlicht, even if it would break some things and we might have to make a larger version jump. But we must keep some important properties intact in order to keep the vision of Irrlicht - simplicity and broad support for all kinds of platforms.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Hi, custom vertex format is very good idea. Backward compatibility is also neccessary, so I prepare first structure for them:

Code: Select all

// We will have 2 VBOs for each MeshBuffer Static and Dynamic, because some infos eg. TexCoord, Color always is Static.
enum CVertexElementStream
{
    VES_STATIC = 0,
    VES_DYNAMIC
};

// Info about current vertex element function, it will be use also for SEMENTIC.
enum CVertexElementUsage
{
    VEU_POSITION = 0,
    VEU_BLEND_WEIGHT,
    VEU_BLEND_INDICES,
    VEU_NORMAL,
    VEU_TEXCOORD,
    VEU_TANGENT,
    VEU_BINORMAL,
    VEU_COLOR
};

// Type of current vertex element.
enum CVertexElementType
{
    VET_FLOAT1 = 0, // float
    VET_FLOAT2, // float * 2
    VET_FLOAT3, // float * 2
    VET_FLOAT4, // float * 3
    VET_SHORT1, // short or int?
    VET_SHORT2, // short * 2
    VET_SHORT3, // short * 3
    VET_SHORT4, // short * 4
    VET_COLOR // SColor?
};

// Simple Vertex Element class, need functions and push some elements to private/protected sections.
class CVertexElement
{
public:
    CVertexElement(CVertexElementStream vStream, size_t vOffset, CVertexElementType vType, CVertexElementUsage vUsage, size_t vUsageIndex) :
                    Stream(vStream), Offset(vOffset), Type(vType), Usage(vUsage), UsageIndex(vUsageIndex), Data(0)
    {
    }

    ~CVertexElement()
    {
        if(Data)
        delete Data;
    }


    CVertexElementStream Stream;
    size_t Offset;
    CVertexElementType Type;
    CVertexElementUsage Usage;
    size_t UsageIndex;

    // Container for our data eg. vector3df, float[3], SColor etc. (types base on CVertexElementType).
    void* Data;
};

// Vertex Type, useful for properly casting.
enum CVertexType
{
    CVT_STANDARD = 0,
    CVT_CUSTOM
};

// Simple Vertex class. We should use it for easy usage Custom or Standard vertex formats in MeshBuffer.
class IVertex
{
public:
    virtual CVertexType getType() = 0;
};

// Simple Custom Vertex class
class CVertex : public IVertex
{
public:
    CVertex() {}
    ~CVertex()
    {
        VertexElement.clear();
    }

    // List with Vertex Elements.
    array<CVertexElement> VertexElement;

    // Return Type.
    CVertexType getType()
    {
        return CVT_CUSTOM;
    }
};

// Current Vertex Formats

class S3DVertex : public IVertex // IVertex class is memory friendly, so it's ok for embedded platforms.
{
    // ORIGINAL CODE FROM S3DVERTEX

    // Return Type.
    CVertexType getType()
    {
        return CVT_STANDARD;
    }
};
As you see we should only replace current S3DVertex declarations in MeshBuffer by IVertex for Backward compatibility. What do You think about this idea? Prebuild current apps also will be very easy with casting method. But how we will be manage vertex format type for current loading meshes? Maybe some global flag in SceneManager for which vertex format should be used for meshes, which we will be loading. I can prepare worked patch for it soon, if it will be accepted.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

And Nadros idea is flexible but each Vertex would store its the whole list.
hybrid wrote:Well, without the patch the idea is just an idea. I don't think that it was rejected, but postponed to a point where a working implementation of a flexible vertex format is proposed. And this might pretty much break backwards compatibility, because the old types might not work as before, e.g. access to members might be quite different. This would probably break most existing apps. Even though it might be less problematic than changes like constness in OnEvent, because not too many apps will directly access vertex properties, and most apps don't write their own mesh loaders etc.
I'd really like to have a better vertex format support in Irrlicht, even if it would break some things and we might have to make a larger version jump. But we must keep some important properties intact in order to keep the vision of Irrlicht - simplicity and broad support for all kinds of platforms.
Well i think whats not correct. Just keep the old structures and add the decl for them would be enough. This way the backwards compatibility would remain and the only thing what would change is that the new vertexdecl must be loaded if the vertexformat change. Maybe we could store a reference instate of the whole vertexdecl list.

short version:
Take Nadros solution or the decl i proposed in the paper, add the decl for the old types in the irr::core scope, use a IVertex interface which stores a ref to a decl and add in the drivers a check in every setVertexBuffer etc. call if the new decl is different to the old one and set the new one if needed (for this the ref on the decls are needed) => no breaking change, new flexible way to add own vertexformat
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Optionally we can remove CVertexElementType, because Position will be always FLOAT3, TexCoords will be FLOAT2 etc and remove UsageIndex, and add to CVertexElementUsage: VEU_TEXCOORD0, VEU_TEXCOORD1 ... VEU_TEXCOORD7 instead of VEU_TEXCOORD.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

I think that having a flexible vertex format is bad for performance and might be inconvenient for storage. Instead we should have a flexible meshbuffer format with separate float arrays for custom attributes (Float array paired with name, padsize and element size). Vertex attributes are more popular amongst the low level APIs these days anyway.

I know that this approach will be really easy to implement and should have good performance in OpenGL, but I am unsure about Direct3D9 (I'm fairly certain D3D10 is more than flexible enough for this though).

On the subject of color. I always thought color had too much importance in the Irrlicht vertex formats, as it's barely ever actually used and losing the color gives a much more cache friendly 32-byte vertex size.

Cheers
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

One is fact, current vertex format isn't enough, so we must decide what should looking new vertex formats and change it as quick as possible. BlindSide proposal looks more like VAO (our mesh buffer with attrib array) + VBO (our variable with data) works, so it is also interesting solution or more this is the best high level solution from all from this topic I think.

Update:
This is my proposal based od BlindSide idea (If I properly understand him)

Code: Select all

enum CVertexStream
{
    VES_STATIC = 0,
    VES_DYNAMIC
};

enum CVertexAttrib
{
    CVA_POSITION = 0,
    CVA_BLEND_WEIGHT,
    CVA_BLEND_INDICES,
    CVA_NORMAL,
    CVA_TEXCOORD0,
    CVA_TEXCOORD1,
    CVA_TEXCOORD2,
    CVA_TEXCOORD3,
    CVA_TEXCOORD4,
    CVA_TEXCOORD5,
    CVA_TEXCOORD6,
    CVA_TEXCOORD7,
    CVA_TANGENT,
    CVA_BINORMAL,
    CVA_COLOR
};

// In MeshBuffer we have to add container for our vertex data and function like this:
void enableVertexAttrib(CVertexStream vStream, CVertexAttrib vAttrib, size_t vOffset); // Offset is depend on how loader sort data in container.
This is more High Level solution I think.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Hi, I prepare vertex structure integrated with Mesh Buffer. I think that it's very good solution for high level API. This is code for write and read vertices info:

Code: Select all

#include <iostream>

#include "irrlicht.h"

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace std;


enum E_VERTEX_STREAM
{
    EVS_STATIC = 0,
    EVS_DYNAMIC,
    EVS_UNDECLARED
};

enum E_VERTEX_ATTRIBURE
{
    EVA_POSITION = 0,
    EVA_BLEND_WEIGHT,
    EVA_BLEND_INDICES,
    EVA_NORMAL,
    EVA_TEXCOORD0,
    EVA_TEXCOORD1,
    EVA_TEXCOORD2,
    EVA_TEXCOORD3,
    EVA_TEXCOORD4,
    EVA_TEXCOORD5,
    EVA_TEXCOORD6,
    EVA_TEXCOORD7,
    EVA_TANGENT,
    EVA_BINORMAL,
    EVA_COLOR,
    EVA_UNDECLARED
};

enum E_VERTEX_DATA_ATTRIBURE
{
    EVDA_POSITION = 1,
    EVDA_BLEND_WEIGHT = 2,
    EVDA_BLEND_INDICES = 4,
    EVDA_NORMAL = 8,
    EVDA_TEXCOORD0 = 16,
    EVDA_TEXCOORD1 = 32,
    EVDA_TEXCOORD2 = 64,
    EVDA_TEXCOORD3 = 128,
    EVDA_TEXCOORD4 = 256,
    EVDA_TEXCOORD5 = 512,
    EVDA_TEXCOORD6 = 1024,
    EVDA_TEXCOORD7 = 2048,
    EVDA_TANGENT = 4096,
    EVDA_BINORMAL = 8192,
    EVDA_COLOR = 16384,
    EVDA_UNDECLARED = 15
};

// Some functions should go into private/protected sections.
class MeshBuffer
{
public:
    MeshBuffer() : AlignedSize(16), CurrentVertex(0), Vertices(0)
    {
        EnableAttributes = new bool[EVA_UNDECLARED];
        VertexAttributeStream = new E_VERTEX_STREAM[EVA_UNDECLARED];
        VertexAttributeOffset = new u32[EVA_UNDECLARED];

        for(int i = 0; i < EVA_UNDECLARED; i++)
        {
            EnableAttributes[i] = 0;
            VertexAttributeStream[i] = EVS_UNDECLARED;
            VertexAttributeOffset[i] = -1;
        }
    }

    ~MeshBuffer()
    {
        for(int i = 0; i < Vertices.size(); i++)
        delete Vertices[i];

        Vertices.clear();
        VertexAttributes.clear();
    }

    void addVertex()
    {
        void* tData = new void*[AlignedSize];

        Vertices.push_back(tData);
        VertexAttributes.push_back((u32)0);

        CurrentVertex = Vertices.size() - 1;
    }

    bool addVertexData(u32 vID, E_VERTEX_ATTRIBURE vAttribute, void* vData)
    {
        // We must enable vertex attribute to store it.
        if(!EnableAttributes[vAttribute])
        return 0;

        // Check Vertex ID.
        u32 cID = vID;

        if(vID == -1)
        cID = CurrentVertex;

        if(cID >= Vertices.size() || cID < 0)
        return 0;

        bool Replace = checkVertexAttributeData(cID, vAttribute);
        u32 tSize = getVertexAttributeSize(vAttribute);

        // Are we replacing existing data?...
        if(Replace)
        {
            float* fData = (float*)Vertices[cID];
            memcpy(&fData[getVertexAttributeOffset(vAttribute) / 4],vData,tSize);

            return 1;
        }
        else // ..so, we are adding new data.
        {
            // We add this attribute at first time, so we must calculate offset for it.
            if(VertexAttributeOffset[vAttribute] == -1)
            {
                u32 CurrentOffset = 0;

                for(int i = 0; i < EVA_UNDECLARED; i++)
                {
                    if(checkVertexAttributeData(cID, (E_VERTEX_ATTRIBURE)i))
                    CurrentOffset += getVertexAttributeSize((E_VERTEX_ATTRIBURE)i);
                }

                VertexAttributeOffset[vAttribute] = CurrentOffset;
            }

            // Size of our container is too small, so we must resize it.
            bool newBuffer = 0;

            while(VertexAttributeOffset[vAttribute] + tSize > AlignedSize)
            {
                AlignedSize += 3; // n*32 for better VBO performance.
                newBuffer = 1;
            };

            // Copy existing data to new container.
            if(newBuffer)
            {
                void* tData = new void*[AlignedSize];
                memcpy(tData,Vertices[cID],VertexAttributeOffset[vAttribute]);
                delete Vertices[cID];
                Vertices[cID] = tData;
            }

            // Copy new data to our vertex data container.
            float* fData = (float*)Vertices[cID];
            memcpy(&fData[VertexAttributeOffset[vAttribute] / 4],vData,tSize);

            // Add vertex attribute data info to attributes info list of this vertex.
            VertexAttributes[cID] += getVertexAttributeData(vAttribute);

            return 1;
        }

        return 0;
    }

    bool removeVertex(u32 vID)
    {
        // Check Vertex ID.
        u32 cID = vID;

        if(vID == -1)
        cID = CurrentVertex;

        if(cID >= Vertices.size() || cID < 0)
        return 0;

        delete Vertices[cID];
        Vertices.erase(cID);

        VertexAttributes.erase(cID);

        return 1;
    }

    bool checkVertexAttribute(E_VERTEX_ATTRIBURE vAttribute)
    {
        return EnableAttributes[vAttribute];
    }

    bool checkVertexAttributeData(u32 vID, E_VERTEX_ATTRIBURE vAttribute)
    {
        // Check Vertex ID.
        u32 cID = vID;

        if(vID == -1)
        cID = CurrentVertex;

        if(cID >= Vertices.size() || cID < 0)
        return 0;

        E_VERTEX_DATA_ATTRIBURE nAttribute = getVertexAttributeData(vAttribute);

        if(nAttribute == EVDA_UNDECLARED)
        return 0;

        for (u32 i = 0; i<32; i++)
        {
            const u32 num = (1<<i);

            if(VertexAttributes[cID] &num)
            {
                if(num == nAttribute)
                return 1;
            }
        }

        return 0;
    }

    void enableVertexAttribute(E_VERTEX_STREAM vStream, E_VERTEX_ATTRIBURE vAttribute)
    {
        EnableAttributes[vAttribute] = 1;
        VertexAttributeStream[vAttribute] = vStream;
    };

    E_VERTEX_DATA_ATTRIBURE getVertexAttributeData(E_VERTEX_ATTRIBURE vAttribute)
    {
        switch(vAttribute)
        {
            case EVA_POSITION:
                return EVDA_POSITION;
            case EVA_BLEND_WEIGHT:
                return EVDA_BLEND_WEIGHT;
            case EVA_BLEND_INDICES:
                return EVDA_BLEND_INDICES;
            case EVA_NORMAL:
                return EVDA_NORMAL;
            case EVA_TEXCOORD0:
                return EVDA_TEXCOORD0;
            case EVA_TEXCOORD1:
                return EVDA_TEXCOORD1;
            case EVA_TEXCOORD2:
                return EVDA_TEXCOORD2;
            case EVA_TEXCOORD3:
                return EVDA_TEXCOORD3;
            case EVA_TEXCOORD4:
                return EVDA_TEXCOORD4;
            case EVA_TEXCOORD5:
                return EVDA_TEXCOORD5;
            case EVA_TEXCOORD6:
                return EVDA_TEXCOORD6;
            case EVA_TEXCOORD7:
                return EVDA_TEXCOORD7;
            case EVA_TANGENT:
                return EVDA_TANGENT;
            case EVA_BINORMAL:
                return EVDA_BINORMAL;
            case EVA_COLOR:
                return EVDA_COLOR;
            default:
                return EVDA_UNDECLARED;
        }
    }

    u32 getVertexAttributeOffset(E_VERTEX_ATTRIBURE vAttribute)
    {
        return VertexAttributeOffset[vAttribute];
    }

    u32 getVertexAttributeSize(E_VERTEX_ATTRIBURE vAttribute)
    {
        switch(vAttribute)
        {
            case EVA_POSITION:
                return 12;
            case EVA_BLEND_WEIGHT:
                return 16;
            case EVA_BLEND_INDICES:
                return 16;
            case EVA_NORMAL:
                return 12;
            case EVA_TEXCOORD0:
            case EVA_TEXCOORD1:
            case EVA_TEXCOORD2:
            case EVA_TEXCOORD3:
            case EVA_TEXCOORD4:
            case EVA_TEXCOORD5:
            case EVA_TEXCOORD6:
            case EVA_TEXCOORD7:
                return 8;
            case EVA_TANGENT:
            case EVA_BINORMAL:
                return 12;
            case EVA_COLOR:
                return 4;
            default:
                return 0;
        }
    }

    void* getVertex(u32 vID)
    {
        // Check Vertex ID.
        u32 cID = vID;

        if(vID == -1)
        cID = CurrentVertex;

        if(cID >= Vertices.size() || cID < 0)
        return 0;

        return Vertices[cID];
    }

    void* getVertices()
    {
        return Vertices.pointer();
    }

    virtual u32 getVertexCount() const
    {
        return Vertices.size();
    }

private:
    u32 AlignedSize;

    bool* EnableAttributes;
    E_VERTEX_STREAM* VertexAttributeStream;
    u32* VertexAttributeOffset;

    u32 CurrentVertex;
    array<void*> Vertices;
    array<u32> VertexAttributes;
};

int main()
{
    // Create pseudo Mesh Buffer
    MeshBuffer* MB = new MeshBuffer();

    // Enable Attributes
    MB->enableVertexAttribute(EVS_DYNAMIC, EVA_POSITION);
    MB->enableVertexAttribute(EVS_DYNAMIC, EVA_NORMAL);
    MB->enableVertexAttribute(EVS_STATIC, EVA_COLOR);

    // Define pseudo vertices

    // Vertex 0
    vector3df Position0(10.1,11.1,12.1);
    vector3df Normal0(20.1,21.1,22.1);
    SColor Color0(10,11,12,13);

    // Vertex 1
    vector3df Position1(10.2,11.2,12.2);
    vector3df Normal1(20.2,21.2,22.2);
    SColor Color1(20,21,22,23);

    // Vertex 2
    vector3df Position2(10.3,11.3,12.3);
    vector3df Normal2(20.3,21.3,22.3);
    SColor Color2(30,31,32,33);

    MB->addVertex(); // Add vertex to list
    MB->addVertexData(-1, EVA_POSITION, &Position0); // Add position attribute, -1 -> current active vertex signed in addVertex function.
    MB->addVertexData(-1, EVA_COLOR, &Color0); // Add color attribute
    MB->addVertexData(-1, EVA_NORMAL, &Normal0); // Add normal attribute

    MB->addVertex();
    // Add attributes in other order
    MB->addVertexData(-1, EVA_NORMAL, &Normal1);
    MB->addVertexData(-1, EVA_POSITION, &Position1);
    MB->addVertexData(-1, EVA_COLOR, &Color1);

    MB->addVertex();
    // Add attributes in other order
    MB->addVertexData(-1, EVA_COLOR, &Color2);
    MB->addVertexData(-1, EVA_POSITION, &Position2);
    MB->addVertexData(-1, EVA_NORMAL, &Normal2);

    // Get attributes
    for(int i = 0; i < MB->getVertexCount(); i++)
    {
        float* nData = static_cast<float*>(MB->getVertex(i));

        stringc name = "Vertex";
        name += i;

        cout << endl << name.c_str() << endl << endl;

        if(MB->checkVertexAttribute(EVA_POSITION))
        {
            u32 Offset = MB->getVertexAttributeOffset(EVA_POSITION) / 4;
            vector3df v(nData[Offset], nData[Offset+1], nData[Offset+2]);
            cout << "Position:\n" << v.X << endl << v.Y << endl << v.Z << endl << endl;
        }

        if(MB->checkVertexAttribute(EVA_NORMAL))
        {
            u32 Offset = MB->getVertexAttributeOffset(EVA_NORMAL) / 4;
            vector3df v(nData[Offset], nData[Offset+1], nData[Offset+2]);
            cout << "Normal:\n" << v.X << endl << v.Y << endl << v.Z << endl << endl;
        }

        if(MB->checkVertexAttribute(EVA_COLOR))
        {
            u32 Offset = MB->getVertexAttributeOffset(EVA_COLOR) / 4;
            SColor c = static_cast<SColor*>(MB->getVertex(i))[Offset];
            cout << "Color:\n" << c.getAlpha() << endl << c.getRed() << endl << c.getGreen() << endl << c.getBlue() << endl << endl;
        }
    }

    system("Pause");

    delete MB;

    return 0;
}
Integration process with Irrlicht eg. mesh loaders should be very easy :) I'm waiting for Your comments.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

Every single vertex is allocated dynamically. I think this is not really practicable. By the way can this solution be used for the fixed function pipeline and how to set the vertex decl fo the driver?

And i dont get BlindSides idea. Why should a flexible vertex format similiar to the dx solution be bad?
Post Reply