Phong Shading giving a black line

I’ve had this problem before, I think its because of normals. If anyone knows how to fix this, or add normals to my existing block batch, let me know.

Block.java

package passage.games;

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.util.vector.Vector3f;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;

public class Block {
	public Vector3f location;
	public Vector3f rotation;
	
	private int vertexPointer;
	private int colorPointer;
	
	private FloatBuffer vertexBuffer;
	private FloatBuffer colorBuffer;
	
	private Shader boxShader;
		
	private float[] vertexData = {
	    -1.0f,-1.0f,-1.0f,
	    -1.0f,-1.0f, 1.0f,
	    -1.0f, 1.0f, 1.0f,
	    
	    1.0f, 1.0f,-1.0f,
	    -1.0f,-1.0f,-1.0f,
	    -1.0f, 1.0f,-1.0f,
	    
	    1.0f,-1.0f, 1.0f,
	    -1.0f,-1.0f,-1.0f,
	    1.0f,-1.0f,-1.0f,
	    
	    1.0f, 1.0f,-1.0f,
	    1.0f,-1.0f,-1.0f,
	    -1.0f,-1.0f,-1.0f,
	    
	    -1.0f,-1.0f,-1.0f,
	    -1.0f, 1.0f, 1.0f,
	    -1.0f, 1.0f,-1.0f,
	    
	    1.0f,-1.0f, 1.0f,
	    -1.0f,-1.0f, 1.0f,
	    -1.0f,-1.0f,-1.0f,
	    
	    -1.0f, 1.0f, 1.0f,
	    -1.0f,-1.0f, 1.0f,
	    1.0f,-1.0f, 1.0f,
	    
	    1.0f, 1.0f, 1.0f,
	    1.0f,-1.0f,-1.0f,
	    1.0f, 1.0f,-1.0f,
	    
	    1.0f,-1.0f,-1.0f,
	    1.0f, 1.0f, 1.0f,
	    1.0f,-1.0f, 1.0f,
	    
	    1.0f, 1.0f, 1.0f,
	    1.0f, 1.0f,-1.0f,
	    -1.0f, 1.0f,-1.0f,
	    
	    1.0f, 1.0f, 1.0f,
	    -1.0f, 1.0f,-1.0f,
	    -1.0f, 1.0f, 1.0f,
	    
	    1.0f,  1.0f, 1.0f,
	    -1.0f, 1.0f, 1.0f,
	    1.0f, -1.0f, 1.0f
	};
	
	public float[] colorData = {
		0.583f,  0.771f,  0.014f,
	    0.609f,  0.115f,  0.436f,
	    0.327f,  0.483f,  0.844f,
	    
	    0.822f,  0.569f,  0.201f,
	    0.435f,  0.602f,  0.223f,
	    0.310f,  0.747f,  0.185f,
	    
	    0.597f,  0.770f,  0.761f,
	    0.559f,  0.436f,  0.730f,
	    0.359f,  0.583f,  0.152f,
	    
	    0.483f,  0.596f,  0.789f,
	    0.559f,  0.861f,  0.639f,
	    0.195f,  0.548f,  0.859f,
	    
	    0.014f,  0.184f,  0.576f,
	    0.771f,  0.328f,  0.970f,
	    0.406f,  0.615f,  0.116f,
	    
	    0.676f,  0.977f,  0.133f,
	    0.971f,  0.572f,  0.833f,
	    0.140f,  0.616f,  0.489f,
	    
	    0.997f,  0.513f,  0.064f,
	    0.945f,  0.719f,  0.592f,
	    0.543f,  0.021f,  0.978f,
	    
	    0.279f,  0.317f,  0.505f,
	    0.167f,  0.620f,  0.077f,
	    0.347f,  0.857f,  0.137f,
	    
	    0.055f,  0.953f,  0.042f,
	    0.714f,  0.505f,  0.345f,
	    0.783f,  0.290f,  0.734f,
	    
	    0.722f,  0.645f,  0.174f,
	    0.302f,  0.455f,  0.848f,
	    0.225f,  0.587f,  0.040f,
	    
	    0.517f,  0.713f,  0.338f,
	    0.053f,  0.959f,  0.120f,
	    0.393f,  0.621f,  0.362f,
	    
	    0.673f,  0.211f,  0.457f,
	    0.820f,  0.883f,  0.371f,
	    0.982f,  0.099f,  0.879f,
	};
	
	public Block(Vector3f location, Vector3f rotation){
		this.location = location;
		this.rotation = rotation;
	}
	
	public Block(Vector3f location){
		this.location = location;
		this.rotation = new Vector3f(0, 0, 0);
	}
	
	public Block(){
		this.location = new Vector3f(0, 0, 0);
		this.rotation = new Vector3f(0, 0, 0);
	}
	
	public void init(){
		vertexBuffer = BufferUtils.createFloatBuffer(108);
		vertexBuffer.put(vertexData);
		vertexBuffer.flip();
		
		colorBuffer = BufferUtils.createFloatBuffer(108);
		colorBuffer.put(colorData);
		colorBuffer.flip();
		
		vertexPointer = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, vertexPointer);
		glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		colorPointer = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, colorPointer);
		glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		
		boxShader = new Shader();
		boxShader.attachVertexShader("./assets/box.vert");
		boxShader.attachFragmentShader("./assets/box.frag");
		boxShader.link();
	}
	
	public void render(){
		boxShader.bind();
			glPushMatrix();
				
				glTranslatef(location.x, location.y, location.z);
				
				glRotatef(rotation.x, 1, 0, 0);
				glRotatef(rotation.y, 0, 1, 0);
				glRotatef(rotation.z, 0, 0, 1);
				
				glEnableClientState(GL_VERTEX_ARRAY);
				glEnableClientState(GL_COLOR_ARRAY);
				
				glBindBuffer(GL_ARRAY_BUFFER, vertexPointer);
				glVertexPointer(3, GL_FLOAT, 0, 0);
				
				glBindBuffer(GL_ARRAY_BUFFER, colorPointer);
				glColorPointer(3, GL_FLOAT, 0, 0);
				
				glDrawArrays(GL_TRIANGLES, 0, 12 * 3);
				
				glDisableClientState(GL_VERTEX_ARRAY);
				glDisableClientState(GL_COLOR_ARRAY);
			glPopMatrix();
		boxShader.unbind();
	}
	
	public void update(){
		
	}
	
	public void destroy(){
		glDeleteBuffers(vertexPointer);
		glDeleteBuffers(colorPointer);
	}
}

Vertex shader

varying vec3 normal; //Normal data (not setup through batch yet)
varying vec3 vertex; //Vertex location for next stage

void main(){
	vertex = vec3(gl_ModelViewMatrix * gl_Vertex); //Vertex location init
    normal = normalize(gl_NormalMatrix * gl_Normal); //Normal data init

    gl_FrontColor = gl_Color; //Vertex color for next stage
	gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; //Final position using built-in matrices because I'm lazy :P
}

Fragment shader

uniform vec3 lightLocation; //Just set to 10, 10, 10 in the game class
vec3 lightColor = vec3(100, 100, 100); //The lights color

varying vec3 normal; //Normal (not setup through batch yet)
varying vec3 vertex; //Vertex from last stage

void main(){
	vec3 light = normalize(lightLocation.xyz - vertex); //Normalize length between the light location, and vertex location
    vec4 diffuse = vec4(lightColor, 1.0) * max(dot(normal, light), 0.0); //Diffuse color (light color)
    diffuse = clamp(diffuse, 0.0, 1.0); //Final light color

    gl_FragColor = gl_Color * diffuse; //Vertex color + light color
}

My end result:

You need to renormalize interpolated vertex normal at fragment shader but I don’t think this only will fix your problems.

Like I said, I’m not getting normals from anywhere. I don’t know how to create those in VBOs. If you have any idea, please tell me!

To create draw normals, first create a buffer object for those normals and store them like you would vertex position. When its time to render, bind the normal buffer and call glNormalPointer

Okay, I think its working, I put the normals on the same data as the colors.

The current block code:

package passage.games;

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.util.vector.Vector3f;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;

public class Block {
	public Vector3f location;
	public Vector3f rotation;
	
	private int vertexPointer;
	private int colorPointer;
	private int normalPointer;
	
	private FloatBuffer vertexBuffer;
	private FloatBuffer colorBuffer;
	private FloatBuffer normalBuffer;
	
	private Shader boxShader;
		
	private float[] vertexData = {
	    -1.0f,-1.0f,-1.0f,
	    -1.0f,-1.0f, 1.0f,
	    -1.0f, 1.0f, 1.0f,
	    
	    1.0f, 1.0f,-1.0f,
	    -1.0f,-1.0f,-1.0f,
	    -1.0f, 1.0f,-1.0f,
	    
	    1.0f,-1.0f, 1.0f,
	    -1.0f,-1.0f,-1.0f,
	    1.0f,-1.0f,-1.0f,
	    
	    1.0f, 1.0f,-1.0f,
	    1.0f,-1.0f,-1.0f,
	    -1.0f,-1.0f,-1.0f,
	    
	    -1.0f,-1.0f,-1.0f,
	    -1.0f, 1.0f, 1.0f,
	    -1.0f, 1.0f,-1.0f,
	    
	    1.0f,-1.0f, 1.0f,
	    -1.0f,-1.0f, 1.0f,
	    -1.0f,-1.0f,-1.0f,
	    
	    -1.0f, 1.0f, 1.0f,
	    -1.0f,-1.0f, 1.0f,
	    1.0f,-1.0f, 1.0f,
	    
	    1.0f, 1.0f, 1.0f,
	    1.0f,-1.0f,-1.0f,
	    1.0f, 1.0f,-1.0f,
	    
	    1.0f,-1.0f,-1.0f,
	    1.0f, 1.0f, 1.0f,
	    1.0f,-1.0f, 1.0f,
	    
	    1.0f, 1.0f, 1.0f,
	    1.0f, 1.0f,-1.0f,
	    -1.0f, 1.0f,-1.0f,
	    
	    1.0f, 1.0f, 1.0f,
	    -1.0f, 1.0f,-1.0f,
	    -1.0f, 1.0f, 1.0f,
	    
	    1.0f,  1.0f, 1.0f,
	    -1.0f, 1.0f, 1.0f,
	    1.0f, -1.0f, 1.0f
	};
	
	public float[] colorData = {
		0.583f,  0.771f,  0.014f,
	    0.609f,  0.115f,  0.436f,
	    0.327f,  0.483f,  0.844f,
	    
	    0.822f,  0.569f,  0.201f,
	    0.435f,  0.602f,  0.223f,
	    0.310f,  0.747f,  0.185f,
	    
	    0.597f,  0.770f,  0.761f,
	    0.559f,  0.436f,  0.730f,
	    0.359f,  0.583f,  0.152f,
	    
	    0.483f,  0.596f,  0.789f,
	    0.559f,  0.861f,  0.639f,
	    0.195f,  0.548f,  0.859f,
	    
	    0.014f,  0.184f,  0.576f,
	    0.771f,  0.328f,  0.970f,
	    0.406f,  0.615f,  0.116f,
	    
	    0.676f,  0.977f,  0.133f,
	    0.971f,  0.572f,  0.833f,
	    0.140f,  0.616f,  0.489f,
	    
	    0.997f,  0.513f,  0.064f,
	    0.945f,  0.719f,  0.592f,
	    0.543f,  0.021f,  0.978f,
	    
	    0.279f,  0.317f,  0.505f,
	    0.167f,  0.620f,  0.077f,
	    0.347f,  0.857f,  0.137f,
	    
	    0.055f,  0.953f,  0.042f,
	    0.714f,  0.505f,  0.345f,
	    0.783f,  0.290f,  0.734f,
	    
	    0.722f,  0.645f,  0.174f,
	    0.302f,  0.455f,  0.848f,
	    0.225f,  0.587f,  0.040f,
	    
	    0.517f,  0.713f,  0.338f,
	    0.053f,  0.959f,  0.120f,
	    0.393f,  0.621f,  0.362f,
	    
	    0.673f,  0.211f,  0.457f,
	    0.820f,  0.883f,  0.371f,
	    0.982f,  0.099f,  0.879f,
	};
	
	public float[] normalData = {
		0.583f,  0.771f,  0.014f,
	    0.609f,  0.115f,  0.436f,
	    0.327f,  0.483f,  0.844f,
	    
	    0.822f,  0.569f,  0.201f,
	    0.435f,  0.602f,  0.223f,
	    0.310f,  0.747f,  0.185f,
	    
	    0.597f,  0.770f,  0.761f,
	    0.559f,  0.436f,  0.730f,
	    0.359f,  0.583f,  0.152f,
	    
	    0.483f,  0.596f,  0.789f,
	    0.559f,  0.861f,  0.639f,
	    0.195f,  0.548f,  0.859f,
	    
	    0.014f,  0.184f,  0.576f,
	    0.771f,  0.328f,  0.970f,
	    0.406f,  0.615f,  0.116f,
	    
	    0.676f,  0.977f,  0.133f,
	    0.971f,  0.572f,  0.833f,
	    0.140f,  0.616f,  0.489f,
	    
	    0.997f,  0.513f,  0.064f,
	    0.945f,  0.719f,  0.592f,
	    0.543f,  0.021f,  0.978f,
	    
	    0.279f,  0.317f,  0.505f,
	    0.167f,  0.620f,  0.077f,
	    0.347f,  0.857f,  0.137f,
	    
	    0.055f,  0.953f,  0.042f,
	    0.714f,  0.505f,  0.345f,
	    0.783f,  0.290f,  0.734f,
	    
	    0.722f,  0.645f,  0.174f,
	    0.302f,  0.455f,  0.848f,
	    0.225f,  0.587f,  0.040f,
	    
	    0.517f,  0.713f,  0.338f,
	    0.053f,  0.959f,  0.120f,
	    0.393f,  0.621f,  0.362f,
	    
	    0.673f,  0.211f,  0.457f,
	    0.820f,  0.883f,  0.371f,
	    0.982f,  0.099f,  0.879f,
	};
	
	public Block(Vector3f location, Vector3f rotation){
		this.location = location;
		this.rotation = rotation;
	}
	
	public Block(Vector3f location){
		this.location = location;
		this.rotation = new Vector3f(0, 0, 0);
	}
	
	public Block(){
		this.location = new Vector3f(0, 0, 0);
		this.rotation = new Vector3f(0, 0, 0);
	}
	
	public void init(){
		vertexBuffer = BufferUtils.createFloatBuffer(108);
		vertexBuffer.put(vertexData);
		vertexBuffer.flip();
		
		colorBuffer = BufferUtils.createFloatBuffer(108);
		colorBuffer.put(colorData);
		colorBuffer.flip();
		
		normalBuffer = BufferUtils.createFloatBuffer(108);
		normalBuffer.put(normalData);
		normalBuffer.flip();
		
		vertexPointer = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, vertexPointer);
		glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		colorPointer = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, colorPointer);
		glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		
		normalPointer = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, normalPointer);
		glBufferData(GL_ARRAY_BUFFER, normalBuffer, GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}
	
	public void render() {
		glPushMatrix();

		glTranslatef(location.x, location.y, location.z);

		glRotatef(rotation.x, 1, 0, 0);
		glRotatef(rotation.y, 0, 1, 0);
		glRotatef(rotation.z, 0, 0, 1);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_NORMAL_ARRAY);

		glBindBuffer(GL_ARRAY_BUFFER, vertexPointer);
		glVertexPointer(3, GL_FLOAT, 0, 0);

		glBindBuffer(GL_ARRAY_BUFFER, colorPointer);
		glColorPointer(3, GL_FLOAT, 0, 0);
		
		glBindBuffer(GL_ARRAY_BUFFER, normalPointer);
		glNormalPointer(GL_FLOAT, 0, 0);
		
		glDrawArrays(GL_TRIANGLES, 0, 12 * 3);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
		glPopMatrix();
	}

	public void update(){
		
	}
	
	public void destroy(){
		glDeleteBuffers(vertexPointer);
		glDeleteBuffers(colorPointer);
	}
}

Does anyone know how to correctly find the normals for this cube? I’m not really sure how to do that.

This is a segment of the per vertex normal generation code I use.


        for(int i = 0; i < indices.size(); i += 3) {
            int i0 = indices.get(i);
            int i1 = indices.get(i + 1);
            int i2 = indices.get(i + 2);

            Vector3f v1 = positions.get(i1).sub(positions.get(i0));
            Vector3f v2 = positions.get(i2).sub(positions.get(i0));

            Vector3f normal = v1.cross(v2).normalized();
        }

Where the positions List are the positions of the vertices.

Thanks for the reply, but I don’t have indices, are there any tutorials on them? I was planning on just getting basic lighting working in 3D, so I can then build upon it with secularity, and different mappings.

psst.
[sub][sub](Your vertices)[/sub][/sub]

I see what you mean, but me being the terrible thinker I am… How do I do this with Slyth2727’s code?

for (int i = 0; i < vertexData.length; i += 9) {
	float[] v1 = {vertexData[i],     vertexData[i + 1], vertexData[i + 2]}
	float[] v2 = {vertexData[i + 3], vertexData[i + 4], vertexData[i + 5]}
	float[] v3 = {vertexData[i + 6], vertexData[i + 7], vertexData[i + 8]}
	
	float[] normal = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]
}

public static float[] getTriangleNormal(float argument0, float argument1, float argument2, float argument3, float argument4, float argument5, float argument6, float argument7, float argument8) {
	float ax,ay,az,bx,by,bz,m,rx,ry,rz;

	//point0 -> point1
	ax = argument3-argument0;
	ay = argument4-argument1;
	az = argument5-argument2;

	//point0 -> point2
	bx = argument6-argument0;
	by = argument7-argument1;
	bz = argument8-argument2;

	//cross product
	rx = ay*bz-by*az;
	ry = az*bx-bz*ax;
	rz = ax*by-bx*ay;

	//magnitude
	m = (float) Math.sqrt(rx*rx+ry*ry+rz*rz);

	//normalize
	rx /= m;
	ry /= m;
	rz /= m;

	return new float[] {rx, ry, rz};
}

Not tested, just wrote it in notepad++

Okay, the cubes are completely black now… Is this what you meant?


		for (int i = 0; i < vertexData.length; i += 9) {
			float[] v1 = { vertexData[i],      vertexData[i + 1], vertexData[i + 2] };
			float[] v2 = { vertexData[i + 3], vertexData[i + 4], vertexData[i + 5] };
			float[] v3 = { vertexData[i + 6], vertexData[i + 7], vertexData[i + 8] };

			normalData = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]);
		}

What I gave you would give you a float array containing the normal data for each triangle. You should be able to figure out the rest :slight_smile:

[hint]
simply setting the normal array I provided to the “normalData” array wont work. You need to figure out how to fill the normalData array with the data from “normal”
[/hint]

Alright… I’m starting to get this…

    for (int i = 0; i < vertexData.length; i += 9) {
			float[] v1 = { vertexData[i],     vertexData[i + 1], vertexData[i + 2] };
			float[] v2 = { vertexData[i + 3], vertexData[i + 4], vertexData[i + 5] };
			float[] v3 = { vertexData[i + 6], vertexData[i + 7], vertexData[i + 8] };
			
			normalData[i] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2])[0];
			normalData[i+1] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2])[1];
			normalData[i+2] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2])[2];
		}

Still gives me incorrect normals.

Notice how you increment i by 9 with [icode]i+=9[/icode], and fill only the slots [icode]i+0, i+1, i+2[/icode]. Therefore the [icode]normalData[/icode] array will contain zeroed normals for every 2nd and 3rd vertex of each triangle.

You probably meant:


normalData[i/3+0]  = ...
normalData[i/3+1]  = ...
normalData[i/3+2]  = ...

Okay, it still gives me this:

		for (int i = 0; i < vertexData.length; i += 9) {
			float[] v1 = { vertexData[i],     vertexData[i + 1], vertexData[i + 2] };
			float[] v2 = { vertexData[i + 3], vertexData[i + 4], vertexData[i + 5] };
			float[] v3 = { vertexData[i + 6], vertexData[i + 7], vertexData[i + 8] };
			
			normalData[i/3+0] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [0];
			normalData[i/3+1] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [1];
			normalData[i/3+2] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [2];
		}
		
		normalBuffer = BufferUtils.createFloatBuffer(108);
		normalBuffer.put(normalData);
		normalBuffer.flip();

                normalPointer = glGenBuffers();
		glBindBuffer(GL_ARRAY_BUFFER, normalPointer);
		glBufferData(GL_ARRAY_BUFFER, normalBuffer, GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);

For every vec3 in the vertexData array, there must be a vec3 in the normalData array. You currently generate 3x less data than you should for the normals.

So, for every i+=9, you have to stuff 9 values in normalData. In this case you replicate the calculated normal for each vertex of the triangle.

I really suck at this normal stuff, is this what you meant by ‘replicate’?


		for (int i = 0; i < vertexData.length; i += 9) {
			float[] v1 = { vertexData[i],     vertexData[i + 1], vertexData[i + 2] };
			float[] v2 = { vertexData[i + 3], vertexData[i + 4], vertexData[i + 5] };
			float[] v3 = { vertexData[i + 6], vertexData[i + 7], vertexData[i + 8] };
			
			normalData[i/3+0] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [0];
			normalData[i/3+1] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [1];
			normalData[i/3+2] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [2];
			
			normalData[i/3+3] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [0];
			normalData[i/3+4] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [1];
			normalData[i/3+5] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [2];
			
			normalData[i/3+6] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [0];
			normalData[i/3+7] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [1];
			normalData[i/3+8] = getTriangleNormal(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) [2];
			
			System.out.println(normalData[i/3+0] + " " + normalData[i/3+1] + " " +normalData[i/3+2]);
		}

i+0…i+8

and try not to calculate the same normal 9 times

I don’t understand?