How to draw geometry using vertex buffer in Ogre 3D v2.1?

Problems building or running the engine, queries about how to use features etc.
Post Reply
rrl
Halfling
Posts: 78
Joined: Sun Jun 04, 2017 12:33 am

How to draw geometry using vertex buffer in Ogre 3D v2.1?

Post by rrl »

I'm trying to create a Triangle in order to understand how to use vertex buffers in Ogre, but having a problem when following the Samples function createIndexBuffer(). Eventually, I will have large arrays of geometries to render, but right now just trying to understand a simple triangle using vertex buffers. The sample I am using is Samples/2.0/ApiUsage/DynamicGeometry from Ogre 2.1.

This is test data to build a triangle (like in the sample

Code: Select all

    Point p1(4.5, 0.00, 4.02);
    Point p2(3.5, 1.5, 4.02);
    Point p3(2.1, 0.00, 4.5);

    const Triangle orig_Tris[1] = { Triangle(p1, p2, p3) };
My problem is mostly with the createIndexBuffer() as I'm not fully understanding it. I was hoping someone would help out with what should be in it for a single triangle.

Code: Select all

    Ogre::IndexBufferPacked* MyTest::createIndexBuffer()
    {
        Ogre::IndexBufferPacked *indexBuffer = 0;

        const Ogre::uint16 c_indexData[3 * 2 * 6] =
        {
            // confusion here
        }

        Ogre::uint16 *triIndices = reinterpret_cast<Ogre::uint16*>
            (OGRE_MALLOC_SIMD(sizeof(Ogre::uint16) * 3 * 2 * 6, 
            Ogre::MEMCATEGORY_GEOMETRY));
        
    	memcpy( cubeIndices, c_indexData, sizeof(c_indexData));

        Ogre::Root *root = mGraphicsSystem->getRoot();
        Ogre::RenderSystem *renderSystem = root->getRenderSystem();
        Ogre::VaoManager *vaoManager = renderSystem->getVaoManager();

        try
        {   
            indexBuffer = vaoManager->createIndexBuffer(Ogre::IndexBufferPacked::IT_16BIT, 
                3 * 2 * 6, Ogre::BT_IMMUTABLE, cubeIndices, true);
        }
        catch( Ogre::Exception &e )
        {   
            OGRE_FREE_SIMD(indexBuffer, Ogre::MEMCATEGORY_GEOMETRY);
            indexBuffer = 0;
            throw e;
        }

        return indexBuffer;
    }
And here is my scene which calls the createIndexBuffer(). My understanding is to create the mesh, a submesh, then declare the vertex.

Code: Select all

    void MyTest::createScene()
    {
        Ogre::RenderSystem *renderSystem = m_ogreRoot->getRenderSystem();
        Ogre::VaoManager *vaoManager = renderSystem->getVaoManager();
  
        /* Create the mesh. */
        Ogre::MeshPtr omesh =
            Ogre::MeshManager::getSingleton().createManual("TestA",
                Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

        /* Create a submesh. */
        Ogre::SubMesh *subMesh = omesh->createSubMesh();

        /* Vertex declaration. */
        Ogre::VertexElement2Vec vertexElements;
        vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT3,
            Ogre::VES_POSITION));
        vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT3,
            Ogre::VES_NORMAL));

        Triangle *tris =
            reinterpret_cast<Triangle*>(OGRE_MALLOC_SIMD(sizeof(Triangle) * 1,
                Ogre::MEMCATEGORY_GEOMETRY));

        // todo: revisit copying data
        memcpy(tris, orig_Tris, sizeof(Triangle) * 1);

        Ogre::VertexBufferPacked *vertexBuffer = nullptr;

        try {
            /* Create the actual vertex buffer. */
            vertexBuffer = vaoManager->createVertexBuffer(vertexElements, 1,
                Ogre::BT_IMMUTABLE, tris, true);
        }
        catch (Ogre::Exception &e) {
            OGRE_FREE_SIMD(vertexBuffer, Ogre::MEMCATEGORY_GEOMETRY);
            vertexBuffer = 0;

            throw e;
        }

        Ogre::VertexBufferPackedVec vertexBuffers;
        vertexBuffers.push_back(vertexBuffer);

        Ogre::IndexBufferPacked *indexBuffer = createIndexBuffer();

        Ogre::VertexArrayObject *vao = vaoManager->createVertexArrayObject(
            vertexBuffers, indexBuffer, Ogre::OT_TRIANGLE_LIST);

        subMesh->mVao[Ogre::VpNormal].push_back(vao);
        subMesh->mVao[Ogre::VpShadow].push_back(vao);

        omesh->_setBounds(Ogre::Aabb(Ogre::Vectgor3::ZERO, Ogre::Vector3::UNIT_SCALE), false);
        omesh->_setBoundingSphereRadius(1.732f);
    }
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: How to draw geometry using vertex buffer in Ogre 3D v2.1

Post by dark_sylinc »

rrl wrote: My problem is mostly with the createIndexBuffer() as I'm not fully understanding it. I was hoping someone would help out with what should be in it for a single triangle.

Code: Select all

    Ogre::IndexBufferPacked* MyTest::createIndexBuffer()
    {
        Ogre::IndexBufferPacked *indexBuffer = 0;

        const Ogre::uint16 c_indexData[3 * 2 * 6] =
        {
            // confusion here
        }
It would appear your problem is in understanding how index buffers work.
I suggest you read: In simple terms, the GPU needs to know how the vertices will be addressed. So it will perform:

Code: Select all

v0 = vertex_buffer[index_buffer[0]];
v1 = vertex_buffer[index_buffer[1]];
v2 = vertex_buffer[index_buffer[2]];
The routine you mentioned creates a cube. A cube is made of 6 faces. Each face needs 2 triangles. And each triangle needs 3 indices. Therefore 3 * 2 * 6.
This connects the 8 vertices together to form all 12 triangles required to render the cube.
rrl
Halfling
Posts: 78
Joined: Sun Jun 04, 2017 12:33 am

Re: How to draw geometry using vertex buffer in Ogre 3D v2.1

Post by rrl »

rrl
Halfling
Posts: 78
Joined: Sun Jun 04, 2017 12:33 am

Re: How to draw geometry using vertex buffer in Ogre 3D v2.1?

Post by rrl »

How do the point coordinates for each CubeVertices (from DynamicGeometry Sample in 2.0) get accessed/drawn? Do my objects (Triangles) need to be structured like CubeVertices, i.e., struct with public float members?

Code: Select all

struct CubeVertices {
    float px, py, pz;
    float nx, ny, nz;

    CubeVertices() {}
    // ...
}
Because right now I use ...

Code: Select all

class Vert
{
    double p1;
    double p2;
    double p3;

    public:
        Vert();
        Vert(double, double, double);
        // ...
}

Class Triangle : public Shape
{
    private:
	Vert v1;
	Vert v2;
	Vert v3;

    public:
	Triangle(Vert _v1, Vert _v2, Vert _v3);
	// ...
}
And so for example, my code looks like this ...

Code: Select all

    Triangle *tris =
        reinterpret_cast<Triangle*>(OGRE_MALLOC_SIMD(sizeof(Triangle) * 1,
            Ogre::MEMCATEGORY_GEOMETRY));

    // somehow, copy data into 1st param here.
    memcpy(tris, orig_Tris, sizeof(Triangle) * 1);
Which causes me to question how the values in my Triangle class get accessed.

I'm close to drawing a triangle, but thinking it's not working because I'm using class objects instead of structs like in the example. I see where OGRE_MALLOC_SIMD's are happening, but I don't understand how CubeVertices.px, CubeVertices.py, CubeVertices.pz get accessed with Vertex Buffers or if my class is requried to have individual members (e.g., px, py, pz).
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: How to draw geometry using vertex buffer in Ogre 3D v2.1?

Post by dark_sylinc »

That is a class instead of a struct has nothing to do.

What defines how to read/interpret the data you feed is the VertexElement:

Code: Select all

VertexElement2Vec vertexElements;
vertexElements.push_back( VertexElement2( VET_FLOAT3, VES_POSITION ) );
vertexElements.push_back( VertexElement2( VET_FLOAT3, VES_NORMAL ) );
That is, the first 3 floats are position, the next 3 floats are the normals.

You are using doubles, and VET_DOUBLE3 is likely not going to work (because most GPUs lack support for it).
Post Reply