Page 1 of 1

Trouble with texturing manual meshes

Posted: Thu Sep 29, 2005 2:13 am
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;

}

Posted: Thu Sep 29, 2005 1:39 pm
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.

Posted: Wed Oct 05, 2005 10:58 pm
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