[2.1] creating manual objects

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Post Reply
nqdev
Gnoblar
Posts: 20
Joined: Sun Sep 09, 2018 12:59 am

[2.1] creating manual objects

Post by nqdev »

I am trying to create manual objects in 2.1 on Linux. My test case is two cubes, one inside the other. Each cube a separate mesh. If I only render one cube, it renders correctly, no issues. The problem is when trying to render both cubes, the first cube (mesh) renders but the second cube isn't rendering correctly, rather, it's drawing lines within the first cube as if it's part of the first cube, which it is not. The cubes are created/exported via another app which I'm certain are correct. Also, some of the points, when trying to render both cubes, extend to 0,0,0 which is not a coordinate of any of my cubes vertices.

I was hoping someone could look over what I've done and see if anything sticks out, or have thoughts on how else I might troubleshoot this problem. I've printed the values of the arrays being passed in to createVertexBuffer() and createIndexBuffer(), and they appear perfectly ok.

Code: Select all

    Point* AGS::fill_vertices(const MInfo &mi)
    {
        PointGroup pg = points[mi.get_group_id()];
 
        Point *vertices = reinterpret_cast<Point*>
            (OGRE_MALLOC_SIMD(sizeof(Point) * mi.get_total_points(),
                Ogre::MEMCATEGORY_GEOMETRY));
 
        for (auto& p : pg)
            vertices[i++] = p.second;
 
        return vertices;
    }
 
    Ogre::uint16* AGS::fill_indices(const MInfo &mi)
    {
        ElementGroup egrp = mesh.at(mi.get_group_id());
 
        Ogre::uint16 *indices =
            reinterpret_cast<Ogre::uint16*>(OGRE_MALLOC_SIMD(
                sizeof(Ogre::uint16) * (mm.get_total_elements() * 3),
                Ogre::MEMCATEGORY_GEOMETRY));
 
        auto i { 0 };
 
        for (auto& epnts : egrp) {
            for (auto& pnt : epnts->get_points())
                indices[i] = pnt.first;
        }                                                                      
                                                                               
        return indices;
    }                                              
 
    Ogre::IndexBufferPacked* AGS::createIndexBuffer(
        const MInfo &mi)
    {  
        Ogre::IndexBufferPacked *index_buffer = nullptr;
       
        Ogre::uint16 *tri_indices = fill_indices(mi);
       
        Ogre::RenderSystem *renderSystem = root->getRenderSystem();
        Ogre::VaoManager *vaoManager = renderSystem->getVaoManager();
       
        try {
            index_buffer = vaoManager->createIndexBuffer(
                Ogre::IndexBufferPacked::IT_16BIT, mi.get_total_elements() * 3,
                    Ogre::BT_IMMUTABLE, tri_indices, true);
        }
        catch (Ogre::Exception &e) {
            OGRE_FREE_SIMD(index_buffer, Ogre::MEMCATEGORY_GEOMETRY);
            index_buffer = nullptr;
           
            throw e;
        }
       
        return index_buffer;
    }
 
    Ogre::MeshPtr AGS::createStaticMesh(const MInfo &mi)
    {
        Ogre::RenderSystem *renderSystem = root->getRenderSystem();
        Ogre::VaoManager *vaoManager = renderSystem->getVaoManager();
 
        /* Create the mesh. */
        Ogre::MeshPtr mesh =
            Ogre::MeshManager::getSingleton().createManual(mi.get_label(),
                Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
 
        /* Create a submesh. */
        Ogre::SubMesh *subMesh = mesh->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));
 
        /* Fill the data. */
        Point *tri_vertices = fill_vertices(mm);
 
        Ogre::VertexBufferPacked *vertexBuffer = nullptr;                      
                                                                               
        try {                                                                  
            /* Create the actual vertex buffer. */                            
            vertexBuffer = vaoManager->createVertexBuffer(vertexElements,      
                mi.get_total_points(), Ogre::BT_IMMUTABLE, tri_vertices, true);
        }                                                                      
        catch (Ogre::Exception &e) {                                          
            OGRE_FREE_SIMD(vertexBuffer, Ogre::MEMCATEGORY_GEOMETRY);          
            vertexBuffer = nullptr;                                            
                                                                               
            throw e;                                                          
        }                                                                      
                                                                               
        Ogre::VertexBufferPackedVec vertexBuffers;                            
        vertexBuffers.push_back(vertexBuffer);                                
                                                                               
        Ogre::IndexBufferPacked *indexBuffer = createIndexBuffer(mm);          
                                                                               
        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);                          
                                                                               
        mesh->_setBounds(Ogre::Aabb(Ogre::Vector3::ZERO,                      
            Ogre::Vector3::UNIT_SCALE), false);                                
        mesh->_setBoundingSphereRadius(1.732f);                                
                                                                               
        return mesh;                                                          
    }
 
// Here is the iteration of the two cubes from my createScene() ...
 
        for (auto& mi : mesh_info) {
            Ogre::MeshPtr mp = createStaticMesh(mi);
 
            Ogre::Item *item =
                sceneManager->createItem(mp, Ogre::SCENE_DYNAMIC);
            item->setDatablock(unlitBlock);
 
            Ogre::SceneNode *scene_node =
                sceneManager->getRootSceneNode(Ogre::SCENE_DYNAMIC)->
                    createChildSceneNode(Ogre::SCENE_DYNAMIC);
            scene_node->attachObject(item);
            scene_node->setPosition(Ogre::Vector3(0.0f, 0.0f, 0.0f));          
            scene_node->setScale(Ogre::Vector3(3.0f, 3.0f, 3.0f));            
        }
al2950
OGRE Expert User
OGRE Expert User
Posts: 1227
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK
x 157

Re: [2.1] creating manual objects

Post by al2950 »

Only had a very quick look, but its seems ok. The only thing that is unclear is that you set the vertex layout to be float3 (position) float3 (normal), however its not clear how fill_vertices matches that layout.
nqdev
Gnoblar
Posts: 20
Joined: Sun Sep 09, 2018 12:59 am

Re: [2.1] creating manual objects

Post by nqdev »

Here's the layout I'm using ...

Code: Select all

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

    Point() { };
    Point(const float *, std::vector<float> &);
    Point(float _px, float _py, float _pz, float _nx, float _ny, float _nz);

    Point(std::vector<float> &, std::vector<float> &);
    ~Point();

    void set_coords(const float, const float, const float);
    void set_coords(std::vector<float> &);
    void set_normals(const float, const float, const float);
    void set_normals(std::vector<float> &);

    void print();
};
al2950
OGRE Expert User
OGRE Expert User
Posts: 1227
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK
x 157

Re: [2.1] creating manual objects

Post by al2950 »

Seems fine... at this point I would use renderdoc to look at what is actually being sent to the GPU. I suspect perhaps indexes are not quite right for some reason.
nqdev
Gnoblar
Posts: 20
Joined: Sun Sep 09, 2018 12:59 am

Re: [2.1] creating manual objects

Post by nqdev »

Incredible tool. Though I'm not well versed on how to use it, I think I've gleaned what I need and it does seem to show that the vertices being passed in are not making it to the GPU.

Depending upon which glMultiDrawElementsIndirect event I select within Texture Viewer, Mesh Output shows the vertices and indices. The problem appears to be that one of the events has none of the vertices and indices as they are given.

And I'm not yet sure where that leaves me as I print all the vertices and indices before they are passed into createVertexArrayObject() and they all appear fine. So far I haven't found a way to print VertexBufferPacked and IndexBufferPacked.

I've attached a few images of the issue I have. The buffer that is corrupted is supposed to be a larger cube, but is corrupted and not using any of the vertices that have been passed in.

Image

Image
al2950
OGRE Expert User
OGRE Expert User
Posts: 1227
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK
x 157

Re: [2.1] creating manual objects

Post by al2950 »

you can actually see the mesh buffer contents by looking at the 'Mesh Output' tab with the appropriate draw call selected. You should be able to see the following
- The input vertices as a table
- The Output vertices as a table
- The input vertices as a wireframe model
- The output mesh as a wireframe model

If you would like you could share the renderdoc capture file and I could take a quick look and point you in the correct direction
nqdev
Gnoblar
Posts: 20
Joined: Sun Sep 09, 2018 12:59 am

Re: [2.1] creating manual objects

Post by nqdev »

Heh, I was referring to the Mesh Outputs tab on where I saw the incorrect values.

I appreciate the help on this. I've attached the capture.
Attachments
2-cubes.rdc.gz
(34.86 KiB) Downloaded 156 times
al2950
OGRE Expert User
OGRE Expert User
Posts: 1227
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK
x 157

Re: [2.1] creating manual objects

Post by al2950 »

nqdev wrote: Fri Nov 23, 2018 11:59 pm Heh, I was referring to the Mesh Outputs tab on where I saw the incorrect values.
Sorry missed that in your post!

I am afraid I still can not see where its going wrong. What is interesting though is the second cube (draw id EID: 72) looks fine, but the first drawn cube (draw id EID: 71) does not. It seems some, not all, verticies are wrong a reference a very small number, most likely un-initialised memory. Whats confusing is both cubes are generated from the same code path :? . I would quadruple check the input data! Keep in mind the draw order is not necessarily the order in which the meshes are created.

Just had another look at the code and I am further confused as I am not sure how the following should work!?

Code: Select all

        auto i { 0 };
 
        for (auto& epnts : egrp) {
            for (auto& pnt : epnts->get_points())
                indices[i] = pnt.first;
        }                                                                      
            
The same is for fill_verticies but i is not declared, so unless its global it should not compile?
nqdev
Gnoblar
Posts: 20
Joined: Sun Sep 09, 2018 12:59 am

Re: [2.1] creating manual objects

Post by nqdev »

The cube that's drawn correctly has vertex values of all 1.0's. The second cube has vertex values that are all 2.0's, but none of those values appear. The cubes should appear as one inside the other, two separate meshes. So the values of 1.0 that you see in the second cube should all be 2.0. Something is going on memory-wise. The weird part is that I print the values of these arrays after I've fill them, and they are correct.

That's the part that I can't understand either and is most confusing. The same code path draws both cubes, the first is always correct, and the one thereafter is always wrong. To reiterate, there are two arrays to be filled. The vertices and the indices. After the arrays are filled, and just before they are placed into createVertexBuffer(...) and createIndexBuffer(...), I print the values and they show correctly.

I've noticed the detail about draw order. The first mesh I input is always drawn correctly, no matter the complexity (i.e., even models with hundreds of elements). But I've noticed it does get a latter EID, and the second mesh (or third, fourth, etc...) I pass, no matter how simple gets an earlier EID and is always corrupted.

The snippet of code you mention iterates through a map of elements, and the second for loop iterates through the Point objects within that element. Then I assign the point id to the to the indices array.
Post Reply