How to calculate normals for a trianglemesh?

Started by
16 comments, last by jor1980 10 years ago

The file is from a game and you need to understand it to extract the data so if i put the file you couldn´t see nothing clearly, what I can do is extract the vertex positions as binary file telling you the dataformat, and also extract the trianglestrip in another binaryfile.Is it right for you?

The file in its game shows the mesh correctly

Advertisement

Hmm... That's like the exact result I had when I imported .obj files that weren't triangulated. Basically, half the indices were missing.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Here is the triangle strip binary file: http://www48.zippyshare.com/v/72608354/file.html

Here the vertexPositions binary file: http://www48.zippyshare.com/v/34761531/file.html
Vertex definition: each vertex 8 bytes: 2bytes x, 2 bytes y, 2bytes z, 2 bytes unknown
Triangle strip: Uint16

Here i left a custom file that i made with the info of the mesh, is a string format file, easy to read in text editor: http://www75.zippyshare.com/v/45873494/file.html

Oh, I thought you were opening a file and reading every vertex and face directly from the file, but it sounds like the file stores the information in a different way and the you make a vertices and faces list, right?

I was looking at the .m3d file you uploaded, and if you look at two consecutive faces you'll see that most of the times one is clockwise and the other is counterclockwise:

For example:

13 14 15 <- if this is counterclockwise
14 15 17 <- this would be clockwise

Since those 2 faces share a side (from vertex number 14 to vertex number 15) the second line should be "15 14 17" instead. Maybe the code that reads that model and generates the list of vertices and faces is doing something wrong. Before you posted a triangle strip, does the original file specify the way to draw it? I guess maybe it stores something like "13 14 15 17" and the file loader makes a face for 13 14 15 and the other for 14 15 17 when the second face should be 15 14 17. If you use the vertex directly to draw a triangle strip, OpenGL makes that swap for you.

As for the question you posted before about knowing if a face is defined clockwise or counterclockwise, unless the file format stores something that specifies it there's no way to tell. In a three dimensional space, a face is defined clockwise AND counterclockwise, it's relative to where the camera is standing. What you could do (with A LOT of work) is check if a normal is pointing outside or inside of the model, but it's not easy and for sure is not trivial.

I think you are right, the triangleList was created by me with my own code deleteing degenerated triangles, and not changing the order of the vertices in the triangles.

I was trying now triStrip methos of jme3 to build the triangleStrip but i think i can´t use because it optimize the triangleList making that some vertices doesn´t belong to any face and when I import the mesh to blender i get errors.

So to test it your theory is right i need to create a correct triangleList to see if the mesh is rendered ok.

i have to two options, find an api that create a triangleList without optimize it, or change my code to create the triangleList in a right way, but I still don´t know how to do it.

Here is the code I use to create the triangleList:


static List<Vector3f> createTriangleListFromStrip(ByteBuffer stripBuffer){
		
		List<Vector3f> facesList= new ArrayList<Vector3f>();
		stripBuffer.clear();
		
		int a=0;
		int b=0;
		int c=0;
		int flagPar=0;
		
		for(int i=0;i<(stripBuffer.capacity()/2)-2;i++){
			
			if(i==0){
				a=Short.reverseBytes(stripBuffer.getShort());
				b=Short.reverseBytes(stripBuffer.getShort());
				c=Short.reverseBytes(stripBuffer.getShort());
				
				if(a!=b & a!=c & b!=c ){
					Vector3f face= new Vector3f();
					face.setX(a);
					face.setY(b);
					face.setZ(c);
					facesList.add(face);
				}
			}
			else{
				a=b;
				b=c;
				c=Short.reverseBytes(stripBuffer.getShort());
				
				if(a!=b & a!=c & b!=c ){
					Vector3f face= new Vector3f();
					face.setX(a);
					face.setY(b);
					face.setZ(c);
					facesList.add(face);
				}
			}
		}
		return facesList;
	}

Try something like this:


static List<Vector3f> createTriangleListFromStrip(ByteBuffer stripBuffer){
		
		List<Vector3f> facesList= new ArrayList<Vector3f>();
		stripBuffer.clear();
		//Maybe you need to check if stripBuffer has enough elements, I'm not sure if you test that before calling this method
		int a=Short.reverseBytes(stripBuffer.getShort());
		int b=0;
		int c=Short.reverseBytes(stripBuffer.getShort());
		
		for(int i=2;i<(stripBuffer.capacity()/2)-2;i++){ //check if the "-2" still makes sense, I'm not sure what capacity() returns (byte size maybe?)
			
			if(i%2==0) {
				b = c;
			} else {
				a = c;
			}
			
			c = Short.reverseBytes(stripBuffer.getShort());
			
			if(a!=b & a!=c & b!=c ){
				Vector3f face= new Vector3f();
				face.setX(a);
				face.setY(b);
				face.setZ(c);
				facesList.add(face);
			}
		}
		return facesList;
	}

Also, doesn't Vector3f have a constructor with parameters? If you can do something like


Vector3f face= new Vector3f(a,b,c);
faceList.add(face);

the code is much readable.

Your code works ok, i made my own but was wrong, Now the mesh I think looks almost correct maybe there is one triangle with the normal inverted at the bottom or with another error, but this the result now:

ao71.jpg

I would like that this mesh looks like in blender, but i don´t know if my problem is the material or the lights.

This is the blender look:

uylo.jpg

This topic is closed to new replies.

Advertisement