[IMPORTANT] Change in Mesh format and Vao

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Post Reply
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1279
Contact:

[IMPORTANT] Change in Mesh format and Vao

Post by dark_sylinc »

Today I merged branch v2-1-shadows-opt into main v2-1

This makes a few significant changes that can affect users working on Ogre 2.1:

The main feature introduced is that there is now 2 Vaos per Renderable for v2 objects, and 2 vertexData/indexData pairs for v1 objects.
So now Ogre can render a mesh during the regular pass, and a completely different one during the shadow casting pass.

This allows us to use an optimized version of the mesh for shadow mapping. In case you don't know, a cube can be represented with 8 vertices, 24 vertices, or 36.
This is because whenever there is a discontinuity, like per face normals or tangents, or UV seams; the vertex needs to be duplicated.

Normally, we don't need UVs or normals during the shadow map pass (unless we need the UVs for sampling a texture for alpha testing; in which case we use mVao[0] instead of mVao[1]) so Ogre will use mVao[1] to send a position-only buffer that has no duplicated vertices to speed up rendering.
The downside is that we need a little more memory to store the extra optimized mesh.

The performance differences can vary wildly. Heavy vertex count with lots of duplicated vertices or bandwidth limited will show the best performance improvements from this (I suspect Mobile will see a huge benefit when we support it) while other applications will see no difference at all.
Results can also depend on the GPU.

Note that this optimization is optional and turned off by default.
When it's off, the pointers of mVao[0] will be referenced by mVao[1]. When it's on, the pointers of mVao[0] & mVao[1] will be unique instances. Same goes for v1 objects.

How to enable it?
You can set Mesh::msOptimizeForShadowMapping and v1::Mesh::msOptimizeForShadowMapping to true and Ogre will automatically generate the optimized version when loading the mesh. However for large meshes this can take quite some time (like 10 seconds for a 200.000-vertices mesh) so it's best to leave this flag disabled, and save the optimized version into disk.
When the optimized vertices were saved to the mesh file, Ogre will load the optimized one regardless of what msOptimizeForShadowMapping says.
The new tool "OgreMeshTool" which was ported from OgreMeshUpgrader and merged with OgreXMLConverter can do this.

The file v2 format changed
Meshes in the previous v2 format are still supported, but we will remove support before releasing the official stable 2.1 version. It is therefore strongly recommended to update your meshes if they were stored in the v2 format. The MeshTool can upgrade them for you.

Examples with the Mesh tool:
To upgrade existing v1 and v2 files and generate the shadow mapping optimized buffers:

Code: Select all

OgreMeshTool -O s sourcefile [destfile]
To upgrade existing v2 files without generating the shadow mapping buffers:

Code: Select all

OgreMeshTool sourcefile [destfile]
To strip existing shadow mapping buffers from a mesh:

Code: Select all

OgreMeshTool -O S sourcefile [destfile]
We also now support generating QTangents and converting floats to 16-bit half formats for v1 meshes. Also v1 and v2 meshes can now be brought back from these representations (half + QTangents back to float + TBN matrices) in case you need to work on them (particularly with existing code that doesn't know how to read 16-bit floats.... or expects a normal instead of a quaternion in the VES_NORMAL semantic).

The MeshTool is still WIP, so not all command line combinations will work, specially because most of its options only work on v1 meshes yet, and if you load a v2 mesh it may ignore them silently.
In the future we plan the MeshTool to be able to convert between v1, v2 and xml mesh file formats without issues. The MeshTool can read XML meshes (not skeletons yet), but cannot write XML yet.

The code has been tested, but expect a few bugs. We may have missed one or two pointer evaluations, i.e. if you see a crash on vertexData and i=1 it's probably because of this new feature.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [IMPORTANT] Change in Mesh format and Vao

Post by xrgo »

Thank you so much!!!
but I have a problem =P

I am generating my mesh manually by reading data from a blender file (alla gamekit), I am first generating a v1mesh then import it to v2:
If I set msOptimizeForShadowMapping to true to my v1mesh after generating it and before load, it seems to be doing something because loading times increases a lot like you said... then I just import to v2, and I get no performance increase =(, if I print msOptimizeForShadowMapping for my v2mesh it says false.

If I set msOptimizeForShadowMapping to true for my v2mesh before or after the importV1 all my shadows looks messy and performance is decreased.

when maually generating v1mesh and then import it to v2, when do I have to make msOptimizeForShadowMapping true??

thanks in advance!!
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1279
Contact:

Re: [IMPORTANT] Change in Mesh format and Vao

Post by dark_sylinc »

Calm down! You're so excited it's hard to understand you! :)

msOptimizeForShadowMapping takes effect when "Mesh::prepareForShadowMapping" gets called.

This can happen when loading a v1 or v2 mesh from file (only if the mesh didn't have the optimized buffers embedded) or in certain functions where the data could become out of sync (like when generating LODs).
If you're uncertain place a few breakpoints :P

If the v1 mesh has these buffers generated, they will be imported to v2 when calling Mesh::importV1. But they won't be auto-generated if the v1 mesh didn't have them.

The best method I recommend for your case: Because you seem to be in control of how the mesh is getting loaded; set both msOptimizeForShadowMapping to false (Ogre::v1::Mesh' and Ogre::Mesh').
Once you are done with the whole import process, do the following:

Code: Select all

Mesh::msOptimizeForShadowMapping = true;
v2Mesh->prepareForShadowMapping( false );
Mesh::msOptimizeForShadowMapping = false;
This is way you'll be completely sure your v2 mesh has optimized shadow mapping and you don't waste time generating them twice or something like that. This is what MeshTool does.

Cheers
Matias
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [IMPORTANT] Change in Mesh format and Vao

Post by xrgo »

dark_sylinc wrote:Calm down! You're so excited it's hard to understand you! :)
:lol: hell yeahh!!asdasD!!
dark_sylinc wrote:Once you are done with the whole import process, do the following:

Code: Select all

Mesh::msOptimizeForShadowMapping = true;
v2Mesh->prepareForShadowMapping( false );
Mesh::msOptimizeForShadowMapping = false;
thanks! sadly I tried that and its same, the shadows looks bad.
I must be doing something else wrong, I going to dig into this later since I am late with some other stuffs :P, then I'll post more information!

Thanks again!!!
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1279
Contact:

Re: [IMPORTANT] Change in Mesh format and Vao

Post by dark_sylinc »

Well... there's a slight chance the optimizer is producing garbage.

That would be weird because I've tested it with really rare meshes and the algorithm is simple enough. However I could've missed something, and now that I think of it... I don't recall testing the optimizer in non-indexed geometry.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [IMPORTANT] Change in Mesh format and Vao

Post by xrgo »

Hello!!
one question...
can both vertexData[0]/indexData[0] and vertexData[1]/indexData[1] have completely different information?, lets say [0] has the information of a very complex mesh, many vertices etc... but [1] has information of a cube, less vertices and completely different indexes. or is just for removing normals and uvs..
I know shadows would look weird, its just an example...

I am doing this while manually constructing V1 mesh and I get a crash in myMesh->load(), before the importV1
If the answer of the above question is "yes is possible" I'll post more details

thanks!
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1279
Contact:

Re: [IMPORTANT] Change in Mesh format and Vao

Post by dark_sylinc »

You can purposely do this, yes. And it will work.
However the code might assume that if vaos don't match then the buffers should only contain position and blend weight and indices, though I'm not sure.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [IMPORTANT] Change in Mesh format and Vao

Post by xrgo »

Thanks! so not sure what am I doing wrong
this is my code:

Code: Select all

        Ogre::Vector3 minBB(Ogre::Vector3::UNIT_SCALE*FLT_MAX);
        Ogre::Vector3 maxBB(Ogre::Vector3::UNIT_SCALE*-FLT_MAX);

        Ogre::v1::MeshPtr newMesh = Ogre::v1::MeshManager::getSingleton().createManual(meshName+"_V1", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);


        for(unsigned int sm=0; sm<triangleBufferCombo.vertexTriangleBuffers.size(); sm++){ //mutiple submesh

            yVertexTriangleBuffer* currentBuffer = triangleBufferCombo.vertexTriangleBuffers.at(sm);
            yVertexTriangleBuffer* currentBufferShadow = triangleBufferCombo.vertexTriangleBufferShadow.at(sm);

            if( !currentBuffer ) continue;
            if( !currentBuffer->vertexs.size() ){
                continue;
            }


            static const unsigned short index16BitClamp = (0xFFFF) - 1;

            Ogre::v1::SubMesh *newSubMesh = newMesh->createSubMesh();
            newSubMesh->setMaterialName("DebugMat"); //just to avoid missing material warning

            newSubMesh->useSharedVertices = false;
            newSubMesh->operationType = Ogre::v1::RenderOperation::OT_TRIANGLE_LIST;

            Ogre::v1::HardwareVertexBufferSharedPtr vertexBuffer;
            //MAIN BUFFER
            {
                unsigned int vertexCount = currentBuffer->vertexs.size();
                unsigned int iBufSize = currentBuffer->triangles.size() * 3;

                newSubMesh->vertexData[0] = OGRE_NEW Ogre::v1::VertexData();
                newSubMesh->vertexData[0]->vertexCount = currentBuffer->vertexs.size();

                unsigned int offs = 0;

                Ogre::v1::VertexDeclaration *decl = newSubMesh->vertexData[0]->vertexDeclaration;
                //position
                decl->addElement(0, offs, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
                offs += Ogre::v1::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

                //normals
                decl->addElement(0, offs, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
                offs += Ogre::v1::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

                //uvs
                for(int i=0; i<currentBuffer->uvSetCount; i++){
                    decl->addElement(0, offs, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i);
                    offs += Ogre::v1::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
                }

                vertexBuffer = Ogre::v1::HardwareBufferManager::getSingleton().createVertexBuffer(
                            offs, vertexCount, Ogre::v1::HardwareBuffer::HBU_STATIC);

                Ogre::v1::VertexBufferBinding *bind = newSubMesh->vertexData[0]->vertexBufferBinding;
                bind->setBinding(0, vertexBuffer);



                //Index buffer
                Ogre::v1::HardwareIndexBuffer::IndexType buff_type = (currentBuffer->maxIndex > index16BitClamp) ?
                            Ogre::v1::HardwareIndexBuffer::IT_32BIT : Ogre::v1::HardwareIndexBuffer::IT_16BIT;

                Ogre::v1::HardwareIndexBufferSharedPtr indexBuffer = Ogre::v1::HardwareBufferManager::getSingleton().createIndexBuffer(buff_type,
                                                                                                                                       iBufSize,
                                                                                                                                       Ogre::v1::HardwareBuffer::HBU_STATIC);
                newSubMesh->indexData[0] = OGRE_NEW Ogre::v1::IndexData();
                newSubMesh->indexData[0]->indexCount = iBufSize;
                newSubMesh->indexData[0]->indexBuffer = indexBuffer;



                //Build index items
                bool using32 = buff_type == Ogre::v1::HardwareIndexBuffer::IT_32BIT;

                unsigned int *indices32 = 0;
                unsigned short *indices16 = 0;

                if (!using32)
                    indices16 = static_cast<unsigned short*>(indexBuffer->lock(Ogre::v1::HardwareBuffer::HBL_NORMAL));
                else
                    indices32 = static_cast<unsigned int*>(indexBuffer->lock(Ogre::v1::HardwareBuffer::HBL_NORMAL));

                for (unsigned int cur = 0; cur < currentBuffer->triangles.size(); cur++)
                {
                    const yTriangleIndex& currentTriangle = currentBuffer->triangles.at(cur);
                    for(unsigned int i=0; i<3; i++){
                        if(using32)
                            *indices32++ = (unsigned int)currentTriangle.index[i];
                        else
                            *indices16++ = (unsigned short)currentTriangle.index[i];
                    }
                }

                indexBuffer->unlock();

            }
            //END MAIN BUFFER


            Ogre::v1::HardwareVertexBufferSharedPtr vertexBufferShad;
            //SHADOW BUFFER
            {
                unsigned int vertexCount = currentBufferShadow->vertexs.size();  //currentBufferShadow
                unsigned int iBufSize = currentBufferShadow->triangles.size() * 3;

                newSubMesh->vertexData[1] = OGRE_NEW Ogre::v1::VertexData();
                newSubMesh->vertexData[1]->vertexCount = currentBufferShadow->vertexs.size();

                unsigned int offs = 0;

                Ogre::v1::VertexDeclaration *decl = newSubMesh->vertexData[1]->vertexDeclaration;
                //position
                decl->addElement(0, offs, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
                offs += Ogre::v1::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

                vertexBufferShad = Ogre::v1::HardwareBufferManager::getSingleton().createVertexBuffer(
                            offs, vertexCount, Ogre::v1::HardwareBuffer::HBU_STATIC);

                Ogre::v1::VertexBufferBinding *bind = newSubMesh->vertexData[1]->vertexBufferBinding;
                bind->setBinding(0, vertexBufferShad);


                //Index buffer
                Ogre::v1::HardwareIndexBuffer::IndexType buff_type = (currentBufferShadow->maxIndex > index16BitClamp) ?
                            Ogre::v1::HardwareIndexBuffer::IT_32BIT : Ogre::v1::HardwareIndexBuffer::IT_16BIT;

                Ogre::v1::HardwareIndexBufferSharedPtr indexBuffer = Ogre::v1::HardwareBufferManager::getSingleton().createIndexBuffer(buff_type,
                                                                                                                                       iBufSize,
                                                                                                                                       Ogre::v1::HardwareBuffer::HBU_STATIC);
                newSubMesh->indexData[1] = OGRE_NEW Ogre::v1::IndexData();
                newSubMesh->indexData[1]->indexCount = iBufSize;
                newSubMesh->indexData[1]->indexBuffer = indexBuffer;


                //Build index items
                bool using32 = buff_type == Ogre::v1::HardwareIndexBuffer::IT_32BIT;

                unsigned int *indices32 = 0;
                unsigned short *indices16 = 0;

                if (!using32)
                    indices16 = static_cast<unsigned short*>(indexBuffer->lock(Ogre::v1::HardwareBuffer::HBL_NORMAL));
                else
                    indices32 = static_cast<unsigned int*>(indexBuffer->lock(Ogre::v1::HardwareBuffer::HBL_NORMAL));

                for (unsigned int cur = 0; cur < currentBufferShadow->triangles.size(); cur++)
                {
                    const yTriangleIndex& currentTriangle = currentBufferShadow->triangles.at(cur);
                    for(unsigned int i=0; i<3; i++){
                        if(using32)
                            *indices32++ = (unsigned int)currentTriangle.index[i];
                        else
                            *indices16++ = (unsigned short)currentTriangle.index[i];
                    }
                }

                indexBuffer->unlock();

            }
            //END SHADOW BUFFER



            //Build vertex buffer
            float *bufferArray = static_cast<float*>(vertexBuffer->lock(Ogre::v1::HardwareBuffer::HBL_NORMAL));
            float *bufferArrayShad = static_cast<float*>(vertexBufferShad->lock(Ogre::v1::HardwareBuffer::HBL_NORMAL));

            for(int i=0; i<currentBuffer->vertexs.size(); i++)
            {
                Ogre::Vector3 pos = convertToYup(Ogre::Vector3(currentBuffer->vertexs.at(i).co[0],currentBuffer->vertexs.at(i).co[1],currentBuffer->vertexs.at(i).co[2]));
                //transform to Y-up
                *bufferArray++ = pos.x;
                *bufferArray++ = pos.y;
                *bufferArray++ = pos.z;

                *bufferArrayShad++ = pos.x;
                *bufferArrayShad++ = pos.y;
                *bufferArrayShad++ = pos.z;

                Ogre::Vector3 norm = convertToYup(Ogre::Vector3(currentBuffer->vertexs.at(i).no[0],currentBuffer->vertexs.at(i).no[1],currentBuffer->vertexs.at(i).no[2])).normalisedCopy();
                //Normals
                *bufferArray++ = norm.x;
                *bufferArray++ = norm.y;
                *bufferArray++ = norm.z;

                //uvs
                for(int j=0; j<currentBuffer->uvSetCount; j++){
                    *bufferArray++ = currentBuffer->vertexs.at(i).uv[j].x;
                    *bufferArray++ = 1.0-currentBuffer->vertexs.at(i).uv[j].y;
                }

                //Calc Bounds
                minBB.makeFloor(pos);
                maxBB.makeCeil(pos);

            }
            vertexBuffer->unlock();
            vertexBufferShad->unlock();


        newMesh->_setBounds(Ogre::AxisAlignedBox(minBB,maxBB),false);

        newMesh->load();  //////////<<<<<<<<<<<<<CRASH HERE

        Ogre::MeshPtr newMeshV2 = Ogre::MeshManager::getSingleton().createManual( meshName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );

        //Import the v1 mesh to v2
        newMeshV2->importV1( newMesh.get(), true, true, true );

        newMesh->unload();
        newMesh.setNull();

        return newMeshV2;

my "triangleBufferCombo" has two buffers with vertex and index data (yVertexTriangleBuffer), "vertexTriangleBuffers" and "vertexTriangleBufferShadow", I know that they are correct because if I do this (both vertexTriangleBuffers):

Code: Select all

            yVertexTriangleBuffer* currentBuffer = triangleBufferCombo.vertexTriangleBuffers.at(sm);
            yVertexTriangleBuffer* currentBufferShadow = triangleBufferCombo.vertexTriangleBuffers.at(sm);
I can see my meshes correctly, but obviously I am not using my optimized version of the mesh for the shadows

And if I do this (both vertexTriangleBufferShadow):

Code: Select all

            yVertexTriangleBuffer* currentBuffer = triangleBufferCombo.vertexTriangleBufferShadow.at(sm);
            yVertexTriangleBuffer* currentBufferShadow = triangleBufferCombo.vertexTriangleBufferShadow.at(sm);
I can see my optimized version of the mesh, I know because they look "smooth" on supposed flat faces and uvs are weird =), just as I intended

But when I do this (As I need):

Code: Select all

            yVertexTriangleBuffer* currentBuffer = triangleBufferCombo.vertexTriangleBuffers.at(sm);
            yVertexTriangleBuffer* currentBufferShadow = triangleBufferCombo.vertexTriangleBufferShadow.at(sm);
I get a crash newMesh->load();

Thanks in advance!!
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1279
Contact:

Re: [IMPORTANT] Change in Mesh format and Vao

Post by dark_sylinc »

Do you have a full callstack of where it crashes?
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [IMPORTANT] Change in Mesh format and Vao

Post by xrgo »

thanks, for some reason if I try a debug build of Ogre I get a crash in another place (when it tries to register low level hlms)... so here is the callstack using a non debug build of Ogre, hope is enough
#0 0x00007ffff3377267 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:55
#1 0x00007ffff3378eca in __GI_abort () at abort.c:89
#2 0x00007ffff33bac53 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7ffff34d31a8 "*** Error in `%s': %s: 0x%s ***\n")
at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff33c2c69 in malloc_printerr (ptr=<optimized out>, str=0x7ffff34d3300 "free(): invalid next size (normal)", action=1) at malloc.c:4965
#4 _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3834
#5 0x00007ffff33c689c in __GI___libc_free (mem=<optimized out>) at malloc.c:2950
#6 0x00007ffff3cc8604 in std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::~basic_stringstream() ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00000000005eba0a in Ogre::Log::Stream::~Stream() ()
#8 0x00000000006499d2 in Ogre::Resource::load(bool) ()
#9 0x00000000004443b8 in yBlendLoader::generateMesh (this=0xce5a40 <yBlendLoader::getSingleton()::instance>, meshName="./media/Main.blend_Sphere.113",
triangleBufferCombo=..., blendFile="./media/Main.blend", skeletonName="") at ../../yoyEngine/src/yBlendLoader.cpp:3098
#10 0x000000000043649a in yBlendLoader::generateObject (this=0xce5a40 <yBlendLoader::getSingleton()::instance>, objectsToAdd=0x7fffffff50b0, objectName="Sphere.113",
bObject=0x180bbd0, blendFile="./media/Main.blend", subObjectMain=0x0) at ../../yoyEngine/src/yBlendLoader.cpp:586
#11 0x0000000000434330 in yBlendLoader::generateObjects (this=0xce5a40 <yBlendLoader::getSingleton()::instance>, bFile=0x16f63c0, blendFileName="./media/Main.blend",
otherSceneManager="") at ../../yoyEngine/src/yBlendLoader.cpp:280
#12 0x0000000000433954 in yBlendLoader::loadFile (this=0xce5a40 <yBlendLoader::getSingleton()::instance>, blendFileName="./media/Main.blend", sceneManager=0x0)
at ../../yoyEngine/src/yBlendLoader.cpp:198
#13 0x0000000000541578 in yEngine::loadFile (this=0xce7f80 <yEngine::getSingleton()::instance>, blendFileName="./media/Main.blend", sceneManager=0x0)
at ../../yoyEngine/src/yEngine.cpp:123
#14 0x000000000052bd6a in yGraphicsSystem::init (this=0xce7b00 <yGraphicsSystem::getSingleton()::instance>) at ../../yoyEngine/src/yGraphicsSystem.cpp:332
#15 0x0000000000541201 in yEngine::initialize (this=0xce7f80 <yEngine::getSingleton()::instance>) at ../../yoyEngine/src/yEngine.cpp:80
#16 0x00000000004300e6 in main (argc=1, argv=0x7fffffffdea8) at ../../yoyEngine/src/main.cpp:88
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1279
Contact:

Re: [IMPORTANT] Change in Mesh format and Vao

Post by dark_sylinc »

Get that callstack carved into your brain. 90% of the time that error you're getting is typically glibc finding out you've corrupted memory. The error could be anywhere. It also explains why you an error shows up in a different place when you use a debug or a release build. They just find it earlier, or later.

However I did noticed that you fill the vertex buffers doing this:

Code: Select all

for(int i=0; i<currentBuffer->vertexs.size(); i++)
But the shadow's vertex buffer is being created with vertex count "currentBufferShadow->vertexs.size()".
Looking at the code alone, there is no guarantee that currentBuffer->vertexs.size() == currentBufferShadow->vertexs.size().
If that isn't true, then you'll be finding yourself at a memory corruption, which is consistent with the error you're getting inside glibc.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [IMPORTANT] Change in Mesh format and Vao

Post by xrgo »

dark_sylinc wrote:However I did noticed that you fill the vertex buffers doing this:

Code: Select all

for(int i=0; i<currentBuffer->vertexs.size(); i++)
But the shadow's vertex buffer is being created with vertex count "currentBufferShadow->vertexs.size()".
Looking at the code alone, there is no guarantee that currentBuffer->vertexs.size() == currentBufferShadow->vertexs.size().
If that isn't true, then you'll be finding yourself at a memory corruption, which is consistent with the error you're getting inside glibc.
Damn! I missed that xD Thank you so much! I fixed that and is now is working!!!!!! <3!!
dark_sylinc wrote:Get that callstack carved into your brain. 90% of the time that error you're getting is typically glibc finding out you've corrupted memory
Thanks for the tip =)
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [IMPORTANT] Change in Mesh format and Vao

Post by xrgo »

Hello again! One thing is bothering me now is that the mere existence of an UV in my mesh disable the optimization, even if I don't set alpha test. How can I fix this?
Thanks!
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1279
Contact:

Re: [IMPORTANT] Change in Mesh format and Vao

Post by dark_sylinc »

Ummm. That should not be happening.

For v2 objects, SubItem::_setHlmsHashes evaluates if the new material being assigned uses alpha testing and disables the optimization, or enables it back.

For v1 objects, it's evaluated in real time in OgreRenderQueue.cpp when calling getRenderOperation.

It's possible for some reason prepareForShadowMapping is getting called. Mesh::msOptimizeForShadowMapping defaults to false (disabled) hence it will destroy your manually created meshes. Set it to true while loading so that it respects your buffers. Also places a breakpoints inside prepareForShadowMapping to make sure something weird doesn't happen (e.g. gets called again much afterwards while msOptimizeForShadowMapping is false)

If the optimization is being disabled despite alpha testing not being used, try to look for those places to check if the logic is wrong; or if you can spot what's wrong. Otherwise come back and I'll have a look when I can. It's definitely a bug.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [IMPORTANT] Change in Mesh format and Vao

Post by xrgo »

Thank you!
In all of those places everything seems correct, but I found that if I remove the prepareForShadowMapping( false ); in Mesh::buildTangentVectors on OgreMesh.cpp (V1) (line ~1779) it works =D! I am going to keep looking...
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1279
Contact:

Re: [IMPORTANT] Change in Mesh format and Vao

Post by dark_sylinc »

Beware that Mesh::msOptimizeForShadowMapping is different from v1::Mesh::msOptimizeForShadowMapping
Since you're using v1 objects to generate tangents, you need to turn the bool in v1:: namespace to true as well.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [IMPORTANT] Change in Mesh format and Vao

Post by xrgo »

yes, I tried that:

Code: Select all

        Ogre::v1::MeshPtr newMesh = Ogre::v1::MeshManager::getSingleton().createManual(meshName+"_V1", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
        newMesh->msOptimizeForShadowMapping = true;

       //create the mesh................

        newMesh->msOptimizeForShadowMapping = true;

        newMesh->load();

        newMesh->msOptimizeForShadowMapping = true;

        Ogre::MeshPtr newMeshV2 = Ogre::MeshManager::getSingleton().createManual( meshName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );

        newMeshV2->msOptimizeForShadowMapping = true;

        //Import the v1 mesh to v2
        newMeshV2->importV1( newMesh.get(), true, true, true );

        newMeshV2->msOptimizeForShadowMapping = true;
I set it true in many places xD
Post Reply