Mesh precision problem
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 168
Mesh precision problem
Hello, I am having this problem:
I made a sphere (obviously this happens with other meshes, the sphere is just a test) in Blender, but the center of the object is far away ( (-200,-200,-200) in this test ):
and when exporting and/or *reading from the blender file alla assimp/gamkit* I get this precision problem, it seems that it can only accept 6 digits for the vertex pos, so when the vertex is far from the center I get less decimals =(
In blender everything looks good =)
I really don't care about the exporter, my engine *reads from the blender file alla assimp/gamkit*, and if I print the vertex pos with std::setprecision(16) I see that the numbers readed from the blender file has the corresponding decimals, so I am guessing is something to do with the ogre mesh generation (?).
Any ideas how to solve this problem?
I made a sphere (obviously this happens with other meshes, the sphere is just a test) in Blender, but the center of the object is far away ( (-200,-200,-200) in this test ):
and when exporting and/or *reading from the blender file alla assimp/gamkit* I get this precision problem, it seems that it can only accept 6 digits for the vertex pos, so when the vertex is far from the center I get less decimals =(
In blender everything looks good =)
I really don't care about the exporter, my engine *reads from the blender file alla assimp/gamkit*, and if I print the vertex pos with std::setprecision(16) I see that the numbers readed from the blender file has the corresponding decimals, so I am guessing is something to do with the ogre mesh generation (?).
Any ideas how to solve this problem?
- dark_sylinc
- OGRE Team Member
- Posts: 5299
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1280
- Contact:
Re: Mesh precision problem
Is that voxel-like thing supposed to be a sphere???
There are multiple possible failure points (basically, every time position data is read or written), but top candidates are:
There are multiple possible failure points (basically, every time position data is read or written), but top candidates are:
- Half floating point precision is not enough for that particular mesh. Use full 32-bit precision.
- The exporter exports to XML with low precision due to the bigger numbers. I don't know the exporter plugin in detail, but you would have to locate how it is being written to the file and check how to increase the precision using Python commands.
- OgreMeshTool/OgreXMLConverter for some reason is not reading with enough precision.
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 168
Re: Mesh precision problem
Thanks!
since my engine reads data directly from the blender file (I did mention that) option 2 and 3 don't fit this case, so about option 1...
I am constructing my mesh like this (lets imagine "yVertexTriangleBuffer* currentBuffer" has the correct values to make the perfect sphere):
How do I use full 32-bit precision? I thought that I was already using it, since I store the position data as Ogre::Vector3 (currentBuffer->vertexs.at(i).co is a Vector3) and Vector3 are Real and Real are float and floats are 32 bit (¿?) and the vertex buffer is float* and the elements are Ogre::VET_FLOAT3/2. So it seems I already store everything in 32 bit???
[ so this comes to mi mind, if I already doing full precision float, using half (for those meshes that would look good using half) would I get performance boost? or just memory? ]
So I tried setting the buffer as double* and the elements as Ogre::VET_DOUBLE3/2 and the mesh looks worst
thanks again!
Yes!dark_sylinc wrote:Is that voxel-like thing supposed to be a sphere???
since my engine reads data directly from the blender file (I did mention that) option 2 and 3 don't fit this case, so about option 1...
I am constructing my mesh like this (lets imagine "yVertexTriangleBuffer* currentBuffer" has the correct values to make the perfect sphere):
Code: Select all
yVertexTriangleBuffer* currentBuffer = triangleBufferCombo.vertexTriangleBuffers.at(sm);
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;
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);
//colors
if(currentBuffer->hasVertexColors){
decl->addElement(0, offs, Ogre::VET_FLOAT3, Ogre::VES_DIFFUSE);
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();
//Build vertex buffer
float *bufferArray = static_cast<float*>(vertexBuffer->lock(Ogre::v1::HardwareBuffer::HBL_NORMAL));
for(int i=0; i<currentBuffer->vertexs.size(); i++)
{
//Position
Ogre::Vector3 pos = convertToYup(currentBuffer->vertexs.at(i).co);
*bufferArray++ = pos.x;
*bufferArray++ = pos.y;
*bufferArray++ = pos.z;
//Normals
Ogre::Vector3 norm = convertToYup(currentBuffer->vertexs.at(i).no);//.normalisedCopy();
*bufferArray++ = norm.x;
*bufferArray++ = norm.y;
*bufferArray++ = norm.z;
//Colors
if(currentBuffer->hasVertexColors){
*bufferArray++ = currentBuffer->vertexs.at(i).col.r;
*bufferArray++ = currentBuffer->vertexs.at(i).col.g;
*bufferArray++ = currentBuffer->vertexs.at(i).col.b;
}
//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();
[ so this comes to mi mind, if I already doing full precision float, using half (for those meshes that would look good using half) would I get performance boost? or just memory? ]
So I tried setting the buffer as double* and the elements as Ogre::VET_DOUBLE3/2 and the mesh looks worst
I am going to try that as last optiondark_sylinc wrote:is to export the mesh as a smaller mesh, then make it bigger again at runtime using SceneNode::setScale
thanks again!
- dark_sylinc
- OGRE Team Member
- Posts: 5299
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1280
- Contact:
Re: Mesh precision problem
Yes, you're already using 32-bit floats. I thought you were using v2 meshes. You're constructing v1 meshes.
You need to watch out for:
If you import from v1 to v2, watch out halfPosition (should be false). Also place breakpoints inside both arrangeEfficient to see if they're being called, and if they are, that their arguments aren't halfPosition = true.
You need to watch out for:
Code: Select all
v2Mesh->importV1( v1Mesh.get(), halfPosition, halfUVs, useQtangents );
Mesh::arrangeEfficient //(v2 mesh)
v1::Mesh::arrangeEfficient //(v1 mesh)
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 168
Re: Mesh precision problem
YEEEESSSS I was importV1 and didn't noticed that halfPosition flag, that did the trick! thank youuuuuu