Trouble with texturing manual meshes

Problems building or running the engine, queries about how to use features etc.
Post Reply
User avatar
AmitMathew
Gnoblar
Posts: 21
Joined: Mon Jul 21, 2003 3:48 pm
Location: Athens, GA, USA
Contact:

Trouble with texturing manual meshes

Post by AmitMathew »

I'm trying to create a way to import FBX files into Ogre. This is my first time playing with the HardwareBuffers, so if I've done anything dumb, please let me off easy. So far the vertices look right (for most meshes at least), but my texture UVs are for some reason incorrect.

Here is a link to the picture of the problem if it is any help:

http://www.amitmathew.org/files/fbx_problem_1.png

Any help would be appreciated.

Thanks,
Amit

Code: Select all

void DrawMesh(KFbxNode* pNode, 
			  KTime& pTime, 
			  KFbxXMatrix& pGlobalPosition, KFbxPose* pPose
{
	KFbxMesh* lMesh = (KFbxMesh*) pNode->GetNodeAttribute();

	int lVertexCount = lMesh->GetControlPointsCount();
	int polygonCount = lMesh->GetPolygonCount();
	int texCoordCount = lMesh->GetTextureUVCount();

	KFbxVector4* lControlPoints = lMesh->GetControlPoints();
	KFbxVector4* lNormals = lMesh->GetNormals();
	KFbxVector2* lTexCoords = lMesh->GetTextureUV();

	Ogre::MeshPtr mesh = MeshManager::getSingleton().createManual("test", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	SubMesh* sub = mesh->createSubMesh();

	mesh->sharedVertexData = new VertexData();
	VertexData* vertexData = mesh->sharedVertexData;
	vertexData->vertexCount = lVertexCount;

	VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
	// positions
	vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION);
	// normals
	vertexDecl->addElement(1, 0, VET_FLOAT3, VES_NORMAL);
	// UVs
	vertexDecl->addElement(2, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);

	VertexBufferBinding* binding = vertexData->vertexBufferBinding;

	// allocate the vertex buffer
	HardwareVertexBufferSharedPtr vBuf = 
		HardwareBufferManager::getSingleton().createVertexBuffer(
		vertexDecl->getVertexSize(0), vertexData->vertexCount, 
		HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	binding->setBinding(0, vBuf);
	Real* pVertex = static_cast<Real*>(vBuf->lock(HardwareBuffer::HBL_DISCARD));

	// allocate the normal buffer
	HardwareVertexBufferSharedPtr nBuf = 
		HardwareBufferManager::getSingleton().createVertexBuffer(
		vertexDecl->getVertexSize(1), getMeshVertexCount(lMesh), 
		HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	binding->setBinding(1, nBuf);
	Real* nVertex = static_cast<Real*>(nBuf->lock(HardwareBuffer::HBL_DISCARD));

	// allocate the uv buffer
	HardwareVertexBufferSharedPtr tBuf = 
		HardwareBufferManager::getSingleton().createVertexBuffer(
		vertexDecl->getVertexSize(2), getMeshVertexCount(lMesh),
		HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	binding->setBinding(2, tBuf);
	Real* tVertex = static_cast<Real*>(tBuf->lock(HardwareBuffer::HBL_DISCARD));

	// build the vertex list
	for (int i = 0; i < lVertexCount; ++i) {

		KFbxVector4 vec = lControlPoints[i];

		*pVertex++ = vec[0];
		*pVertex++ = vec[1];
		*pVertex++ = vec[2];

	}

        // build normal list
	for (int i = 0; i < polygonCount; ++i) {

		for (int j = 0; j < lMesh->GetPolygonSize(i); ++j) {

			KFbxVector4 normal;
			lMesh->GetPolygonVertexNormal(i, j, normal);

			*nVertex++ = normal[0];
			*nVertex++ = normal[1];
			*nVertex++ = normal[2];

		}

	}

        // build uv list
	for (int i = 0; i < polygonCount; ++i) {

		KFbxVector2* uvVertices = lMesh->GetTextureUV();

		for (int j = 0; j < lMesh->GetPolygonSize(i); ++j) {

			KFbxVector2 uv = uvVertices[lMesh->GetTextureUVIndex(i, j)];

			*tVertex++ = uv[0];
			*tVertex++ = uv[1];

		}

	}

	// calculate index count
	int indexCount = getMeshVertexCount(lMesh);

	// allocate the index buffer
	sub->indexData->indexCount = indexCount;
	sub->indexData->indexBuffer = 
		HardwareBufferManager::getSingleton().createIndexBuffer(
		HardwareIndexBuffer::IT_16BIT, sub->indexData->indexCount, 
		HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	HardwareIndexBufferSharedPtr iBuf = sub->indexData->indexBuffer;
	unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD));

	// build the index list
	for (int i = 0; i < polygonCount; ++i) {

		int polygonSize = lMesh->GetPolygonSize(i);

		for (int j = 0; j < polygonSize; j++) {

			int controlPointIndex = lMesh->GetPolygonVertex(i, j);

			*pIndices++ = controlPointIndex;

		}

	}

	vBuf->unlock();
	nBuf->unlock();
	tBuf->unlock();
	iBuf->unlock();
	sub->useSharedVertices = true;
	Vector3 minVertex = getMinVertex(lControlPoints, lVertexCount);
	Vector3 maxVertex = getMaxVertex(lControlPoints, lVertexCount);
	mesh->_setBounds(AxisAlignedBox(minVertex, maxVertex), false);
	mesh->_setBoundingSphereRadius(getRadius(minVertex, maxVertex)); 
	mesh->load();
}

int getMeshVertexCount(KFbxMesh* mesh) {

	int polygonCount = mesh->GetPolygonCount();
	int vertexCount = 0;

	for (int i = 0; i < polygonCount; ++i) {

		vertexCount += mesh->GetPolygonSize(i);

	}

	return vertexCount;

}
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

You probably need to invert the 'v' coordinate, some systems use the opposite v direction.

BTW you should really create a combined buffer, using 3 separate buffers is sub-optimal.
User avatar
AmitMathew
Gnoblar
Posts: 21
Joined: Mon Jul 21, 2003 3:48 pm
Location: Athens, GA, USA
Contact:

Post by AmitMathew »

The inverted v was one problem, but I also had much bigger problems. I originally had everything in one buffer, but changed it to three because the number of vertices given by FBX didn't match the number of UVs or normals, since there was a set of UVs and normals for each polygon vertex. To get everything to work, I changed it back to one buffer, and used a vertex for each polygon vertex. Of course that means the index buffer just goes from 0 to the number of vertices, which doesn't seem right. Is there a standard way of handling this for exporters?

Amit
Post Reply