Page 1 of 2

Reading vertices out of a ms3d's meshbuff.

Posted: Fri Oct 31, 2008 5:48 am
by cheesehound
I'm trying to get the vertex data out of a MeshNode generated from a .ms3d file for use as a collision geom for ODE. Since my mesh collisions weren't looking too accurate, I decided to step through the vertices and found that my 8 vertex test box's mesh node had 24 vertices, many of which simply repeated alternatingly. Are there any known issues with this kind of thing? I tried it with a model in the .x format and experienced similar issues.

I'm using code that is more or less equivalent to the code at http://irrlicht.sourceforge.net/tut_ode.html 's setGeomData.

Code: Select all

			for( j = 0; j < theMeshBuff-> getVertexCount() ; ++j )
			{
				int theBaseIndex = theCurrentVertex * 3;
				theVertices[theBaseIndex] = theBufferVertices[j].Pos.X;
				theVertices[theBaseIndex + 1] = theBufferVertices[j].Pos.Y;
				theVertices[theBaseIndex + 2] = theBufferVertices[j].Pos.Z;

				std::ostringstream theDebugMsg;
				theDebugMsg << "\nVertex " << theCurrentVertex << ": (" <<	theBufferVertices[j].Pos.X << ", " << theBufferVertices[j].Pos.Y << ", " << theBufferVertices[j].Pos.Z << ")";

				OutputDebugString( theDebugMsg.str().c_str() );

				++theCurrentVertex;
			} 
outputs the following:
Vertex 0: (-109.868, 4.03141, 14.4375)
Vertex 1: (-109.868, 0.949764, 14.4375)
Vertex 2: (119.868, 4.03141, 14.4375)
Vertex 3: (119.868, 0.949764, 14.4375)
Vertex 4: (119.868, 4.03141, 14.4375)
Vertex 5: (119.868, 0.949764, 14.4375)
Vertex 6: (119.868, 4.03141, -14.4375)
Vertex 7: (119.868, 0.949764, -14.4375)
Vertex 8: (119.868, 4.03141, -14.4375)
Vertex 9: (119.868, 0.949764, -14.4375)
Vertex 10: (-109.868, 4.03141, -14.4375)
Vertex 11: (-109.868, 0.949764, -14.4375)
Vertex 12: (-109.868, 4.03141, -14.4375)
Vertex 13: (-109.868, 0.949764, -14.4375)
Vertex 14: (-109.868, 4.03141, 14.4375)
Vertex 15: (-109.868, 0.949764, 14.4375)
Vertex 16: (-109.868, 4.03141, -14.4375)
Vertex 17: (-109.868, 4.03141, 14.4375)
Vertex 18: (119.868, 4.03141, -14.4375)
Vertex 19: (119.868, 4.03141, 14.4375)
Vertex 20: (-109.868, 0.949764, 14.4375)
Vertex 21: (-109.868, 0.949764, -14.4375)
Vertex 22: (119.868, 0.949764, 14.4375)
Vertex 23: (119.868, 0.949764, -14.4375)
and I exported my .ms3d to plain text as proof that it's actually 8 vertices:

Code: Select all

SimpleMeshFormat 1
1
Box01
8
-109.868 4.03141 14.4375
-109.868 0.949764 14.4375
119.868 4.03141 14.4375
119.868 0.949764 14.4375
119.868 4.03141 -14.4375
119.868 0.949764 -14.4375
-109.868 4.03141 -14.4375
-109.868 0.949764 -14.4375
12
1 0 1 2 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0
1 1 3 2 0 0 1 0 0 1 0 0 1 0 1 1 1 1 0
2 2 3 4 1 0 0 1 0 0 1 0 0 0 0 0 1 1 0
2 3 5 4 1 0 0 1 0 0 1 0 0 0 1 1 1 1 0
1 4 5 6 0 0 -1 0 0 -1 0 0 -1 0 0 0 1 1 0
1 5 7 6 0 0 -1 0 0 -1 0 0 -1 0 1 1 1 1 0
2 6 7 0 -1 0 0 -1 0 0 -1 0 0 0 0 0 1 1 0
2 7 1 0 -1 0 0 -1 0 0 -1 0 0 0 1 1 1 1 0
3 6 0 4 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0
3 0 2 4 0 1 0 0 1 0 0 1 0 0 1 1 1 1 0
3 1 7 3 0 -1 0 0 -1 0 0 -1 0 0 0 0 1 1 0
3 7 5 3 0 -1 0 0 -1 0 0 -1 0 0 1 1 1 1 0
Chiefly I'm just confused as to why the vertex data I'm getting here seems so apparently wrong. Any wisdom would be most appreciated.

Posted: Fri Oct 31, 2008 8:24 am
by hybrid
Irrlicht binds vertex position, vertex normals, vertex colors, and texture coordinates together into a S3DVertex struct. If the positions are equal, but normals or any other part differ, a new vertex is created. The ms3d file has 12 quads defined, which means 24 triangles, and those are composed from those 24 vertices you find in your mesh.

Posted: Fri Oct 31, 2008 5:07 pm
by cheesehound
Thanks hybrid.

I guess the problem is that I'm taking this data to represent a trimesh when in fact it doesn't?

For example, the vertices
Vertex 6: (119.868, 4.03141, -14.4375)
Vertex 7: (119.868, 0.949764, -14.4375)
Vertex 8: (119.868, 4.03141, -14.4375)
don't make a face, but show up sequentially in the mesh data and have indices that indicate (to me) that they belong to the same face.

Will I have to check for these kinds of issues if I want a valid trimesh for use in ODE, or am I barking up the wrong tree here?

Posted: Fri Oct 31, 2008 5:47 pm
by hybrid
To be honest, your loop seems to extract rather random values from the vertex list. Simply because you take the x value of the first vertex, the y value of the second, and Z from the third vertex of a face. Instead, you should print all x,y,z for each of the three, forming a face. Or just print each vertex in the vertex list without taking into account the indices...

Posted: Fri Oct 31, 2008 8:19 pm
by cheesehound
I think you may be misreading it. It's just iterating through the members of theBufferVertices from 0 to theMeshbuff->getVertexCount().

theVertices is a float* with a length of 3 * the total vertex count, and I'm sticking the x,y, and z coords each into sequential indices of theVertices. The values I'm actually printing are the ones inside theBufferVertices, though, so regardless of where I'm sticking them, what I'm reading out of my irr::video::S3DVertex* theBuffVertices seems pretty off.

Posted: Fri Oct 31, 2008 9:22 pm
by hybrid
oh yes, you're right. So why don't you take into account the indices :P Faces are build based on the indices, you need to check vertex[index[0]],...,vertex[index[2]] for the first triangle!

Posted: Tue Nov 04, 2008 6:03 am
by cheesehound
I am copying my indices data into an array and passing it along to

Code: Select all

ODE_API void dGeomTriMeshDataBuildSimple(dTriMeshDataID g,
                                 const dReal* Vertices, int VertexCount,
                                 const dTriIndex* Indices, int IndexCount);
a dTriIndex is a typedef of a uint32, so I figured all was right in my copying of indices and passing it on to ODE via this call. I'm posting my code below, but it really does follow the ODE tutorial so far as I can figure. I'm pretty sure this is a regularly done thing in Irrlicht. Is there another resource I should be looking at for pointers on getting this rolling? I'd feel less guilty if you didn't have to read all this :P.

Code: Select all

    int theIndexCount = 0;
    int theVertexCount = 0;
    // count vertices and indices
    for( int i = 0; i < theMesh->getMeshBufferCount(); ++i)
	{
		irr::scene::IMeshBuffer* theMeshBuff= theMesh->getMeshBuffer( i );
		theIndexCount += theMeshBuff->getIndexCount();
		theVertexCount += theMeshBuff->getVertexCount();
    }

	int theMeshBuffCount = theMesh->getMeshBufferCount();

    // build structure for ode trimesh geom
    float* theVertices = new float[theVertexCount * 3];
    dTriIndex* theIndices = new dTriIndex[theIndexCount];

    // fill trimesh geom
	int theCurrentIndex = 0;
	int theIrrVertexOffset = 0;
	int theCurrentVertex = 0;

	int i;
	int j;

    for( i = 0 ; i < theMesh->getMeshBufferCount(); ++i)
	{
		irr::scene::IMeshBuffer* theMeshBuff = theMesh->getMeshBuffer( i );
		// fill indices
		irr::u16* theBufferIndices = theMeshBuff->getIndices();

		for( j = 0; j < theMeshBuff->getIndexCount(); j++)
		{
			// scale the indices from multiple meshbuffers to single index array
			theIndices[theCurrentIndex] = theIrrVertexOffset + theBufferIndices[j];

			std::ostringstream theDebugMsg;
			theDebugMsg << "\n Index " << theCurrentIndex << ": " << theBufferIndices[j] << " + offset:" << theIrrVertexOffset;
			OutputDebugString( theDebugMsg.str().c_str() );

			++theCurrentIndex;
		}

		// update the offset for the next meshbuffer
		theIrrVertexOffset = theIrrVertexOffset + theMeshBuff->getVertexCount();
		
		// fill vertices
		if( theMeshBuff->getVertexType() == irr::video::EVT_STANDARD )
		{
			irr::video::S3DVertex* theBufferVertices=
				  (irr::video::S3DVertex*) theMeshBuff->getVertices();

			for( j = 0; j < theMeshBuff-> getVertexCount() ; ++j )
			{
				int theBaseIndex = theCurrentVertex * 3;
				theVertices[theBaseIndex] = theBufferVertices[j].Pos.X;
				theVertices[theBaseIndex + 1] = theBufferVertices[j].Pos.Y;
				theVertices[theBaseIndex + 2] = theBufferVertices[j].Pos.Z;

				std::ostringstream theDebugMsg;
				theDebugMsg << "\nVertex " << theCurrentVertex << ": (" <<	theBufferVertices[j].Pos.X << ", " << theBufferVertices[j].Pos.Y << ", " << theBufferVertices[j].Pos.Z << ")";

				OutputDebugString( theDebugMsg.str().c_str() );

				++theCurrentVertex;
			} 
		}
	}

	irr::core::vector3df thePosition = aMeshNode->getPosition();

	// build the trimesh data
	dTriMeshDataID theData = dGeomTriMeshDataCreate();
	//TODO: check on memory management of Data.  Is it destroyed with our Geom?

	dGeomTriMeshDataBuildSimple( theData,(dReal*)theVertices, 
					  theVertexCount, theIndices, theIndexCount);
	// build the trimesh geom 
	mPhysicsInfo.geomId = dCreateTriMesh( aWorldInfo.spaceId, theData, 0, 0, 0);

	// set the geom position 
	dGeomSetPosition( mPhysicsInfo.geomId, thePosition.X, thePosition.Y, thePosition.Z);
}
And these are the indices I'm getting output by my test code.
Index 0: 0 + offset:0
Index 1: 1 + offset:0
Index 2: 2 + offset:0
Index 3: 1 + offset:0
Index 4: 3 + offset:0
Index 5: 2 + offset:0
Index 6: 4 + offset:0
Index 7: 5 + offset:0
Index 8: 6 + offset:0
Index 9: 5 + offset:0
Index 10: 7 + offset:0
Index 11: 6 + offset:0
Index 12: 8 + offset:0
Index 13: 9 + offset:0
Index 14: 10 + offset:0
Index 15: 9 + offset:0
Index 16: 11 + offset:0
Index 17: 10 + offset:0
Index 18: 12 + offset:0
Index 19: 13 + offset:0
Index 20: 14 + offset:0
Index 21: 13 + offset:0
Index 22: 15 + offset:0
Index 23: 14 + offset:0
Index 24: 16 + offset:0
Index 25: 17 + offset:0
Index 26: 18 + offset:0
Index 27: 17 + offset:0
Index 28: 19 + offset:0
Index 29: 18 + offset:0
Index 30: 20 + offset:0
Index 31: 21 + offset:0
Index 32: 22 + offset:0
Index 33: 21 + offset:0
Index 34: 23 + offset:0
Index 35: 22 + offset:0
Thanks again.

Posted: Tue Nov 04, 2008 2:25 pm
by hybrid
Ok, so 36 indices makes 12 faces, which is correct according to the ms3d file output. So you just need to check the vertices which are referenced by the indices, instead of doing it via the 0,1,2,3,4,5,6,... scheme.

Posted: Tue Nov 04, 2008 5:22 pm
by cheesehound
I swear I'd typed that they looked fine to me after a cursory glance, but that's definitely not anywhere in the post. I'll take a closer look at it the next chance I get, though.

My main hope in posting this was that it was a common (but something I failed searching for) issue and that there would be something terribly obvious I was off on via outdated info or good ol' dumbness. Oh well. I'll take another swat at it tonight :).

Posted: Wed Nov 05, 2008 6:02 am
by cheesehound
Does vertex order matter here? I've noticed that some of my faces appear to be defined in counter-clockwise order while others are defined in clockwise order. That said, the top of my box is all defined counter-clockwise, so I may just have gotten cross-eyed halfway through this. And if the top's fine, my lame "drop objects on it" test should be working.

This unfortunately seems to put me back at square 1, with no idea about just what in my fairly vanilla looking code might be causing this. What I've done seems to match the ODE tutorial pretty directly, and also follows what I saw done in examples of creating a trimesh I found for PAL and Newton. I must be doing something impressively stupid :). Back to le code.

Posted: Wed Nov 05, 2008 2:40 pm
by jddevnet
I've been learning about this recently as well.

The order of the vertices are important, as the indices are defining the triangles based on that. This little picture from Hybrid helped me understand it immensely:
hybrid wrote: Also note that you need to use clockwise orientation of the faces. So the following quad results in indices 0,1,2,1,3,2

Code: Select all

0---1
|  / |
| /  |
2---3
From: http://irrlicht.sourceforge.net/phpBB2/ ... highlight=

Posted: Wed Nov 05, 2008 5:16 pm
by cheesehound
Oh, damn. I'm used to seeing faces defined in counter-clockwise order, so figured that was correct. Is this a known issue with ms3d-generated files? Anyone have an idea for an app that could save out a simple cube model with the correct vertices order? I'll try creating something with Blender and crossing my fingers that it defines the vertices in the right order, otherwise :P.

Posted: Wed Nov 05, 2008 5:30 pm
by Acki
jddevnet wrote:I've been learning about this recently as well.

The order of the vertices are important, as the indices are defining the triangles based on that. This little picture from Hybrid helped me understand it immensely:
hybrid wrote: Also note that you need to use clockwise orientation of the faces. So the following quad results in indices 0,1,2,1,3,2

Code: Select all

0---1
|  / |
| /  |
2---3
From: http://irrlicht.sourceforge.net/phpBB2/ ... highlight=
it's right that the order is important, but it must not be clockwise, it must be anti-clockwise (I mentioned this in the same thread, 2 posts after hybrid's post: http://irrlicht.sourceforge.net/phpBB2/ ... 123#175123) !!! ;)

maybe this post is also usefull to understand this: http://irrlicht.sourceforge.net/phpBB2/ ... 367#171367

Posted: Wed Nov 05, 2008 7:07 pm
by jddevnet
Ah, yes - my apologies Acki! I do recall seeing that, although I guess I didn't quite get the implication at the time..

I never saw this before your link, but it sure does clear up why my initial attempts placed the image on the back. lol

Acki wrote:remember the order of the indices !!!
to see the face from the front the order must be anti-clockwise !!!
to see the face from the back the order must be clockwise !!!

Posted: Wed Nov 05, 2008 8:19 pm
by cheesehound
Well, heck. Looks like there's nothing wrong with my mesh, then. I'll go back to staring at my code. Thanks, guys :).