1

Below is a picture of what my outcome is.

I am using flat shading and have put each vertex in their respectable triangle objects. Then I use these vertices to calculate the surface normals. I have been reading that because my triangles share similar vertices that calculating the normals may be an issue? But to me this looks like a windings problem given that every other one is off.

I provided some of my code below to anyone who wants to look through it and get a better idea what the issue could be.

A triangle strip with

Triangle currentTri = new Triangle();
int triPointIndex = 0;
List<Triangle> triList = new ArrayList<Triangle>()                               

GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
        int counter1 = 0;               
        float stripZ = 1.0f;
        float randY;
        for (float x=0.0f; x<20.0f; x+=2.0f) {
            if (stripZ == 1.0f) {
                stripZ = -1.0f;
            } else { stripZ = 1.0f; }

            randY = (Float) randYList.get(counter1);
            counter1 += 1;

            GL11.glVertex3f(x, randY, stripZ);

            Vert currentVert = currentTri.triVerts[triPointIndex];
            currentVert.x = x;
            currentVert.y = randY;
            currentVert.z = stripZ;

            triPointIndex++;

            System.out.println(triList);

            Vector3f normal = new Vector3f();
            float Ux = currentTri.triVerts[1].x - currentTri.triVerts[0].x;
            float Uy = currentTri.triVerts[1].y - currentTri.triVerts[0].y;
            float Uz = currentTri.triVerts[1].z - currentTri.triVerts[0].z;

            float Vx = currentTri.triVerts[2].x - currentTri.triVerts[0].x;
            float Vy = currentTri.triVerts[2].y - currentTri.triVerts[0].y;
            float Vz = currentTri.triVerts[2].z - currentTri.triVerts[0].z;

            normal.x = (Uy * Vz) - (Uz * Vy);
            normal.y = (Uz * Vx) - (Ux * Vz);
            normal.z = (Ux * Vy) - (Uy * Vx);

            GL11.glNormal3f(normal.x, normal.y, normal.z);

            if (triPointIndex == 3) {
                triList.add(currentTri);
                Triangle nextTri = new Triangle();

                nextTri.triVerts[0] = currentTri.triVerts[1];
                nextTri.triVerts[1] = currentTri.triVerts[2];
                currentTri = nextTri;
                triPointIndex = 2;
            }           

        }
 GL11.glEnd();

2 Answers2

1

Actually it's both in one. The direction of the normal depends on the winding used to calculate it. However ultimately it boils down to a normals problem, since that's what determines lighting calculations.

Winding is also important for OpenGL, but you can't change anything about that in a striped primitive.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • So are you saying that there is no way to get around this and that I should switch from using GL_TRIANGLE_STRIP to using GL_TRIANGLES? – Alpha Centauri A B Dec 04 '13 at 21:29
  • Or could I do something different with my surface normal calculations so that it compensates and reverses every other triangle? – Alpha Centauri A B Dec 04 '13 at 21:31
  • 1
    @AlphaCentauriAB: You should fix your normals calculation. For every odd indexed triangle you either have to swap the vectors into the cross product or scale the resulting normal by -1. Also you must call glNormal before calling glVertex. – datenwolf Dec 04 '13 at 22:11
  • Thank you! The second sentence in this comment really helped me the most in figuring this out. It was a lot easier than I though. – Alpha Centauri A B Dec 05 '13 at 06:08
1

You should be setting the normal before calling glVertex3f (...). A call to glVertex* is basically what finalizes a vertex, it associates the current color, normal, texture coordinates, etc... with the vertex at the position you pass and emits a new vertex.


glVertex — specify a vertex

Description

glVertex commands are used within glBegin / glEnd pairs to specify point, line, and polygon vertices. The current color, normal, texture coordinates, and fog coordinate are associated with the vertex when glVertex is called.

When only x and y are specified, z defaults to 0.0 and w defaults to 1.0. When x, y, and z are specified, w defaults to 1.0.


Chances are very good that this is a large part of your problem. Triangle strips are designed to workaround implicit winding issues. You have to reverse the winding of every triangle when you use a strip, but the rasterizer compensates for this by flipping the winding order used for front/back internally on each alternate triangle.

Update:

Understand of course that the rasterizer is smart enough to flip the front/back winding for each alternate triangle when using a strip but your code is not (at least not currently). You need to compensate for the alternately reversed winding when you calculate the normals yourself on the CPU side.

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • 1
    OPs issue is likely caused by his normal calculation getting "swapped" for every odd indexed triangle. You can see the dim triangles in his picture, so this is not a winding/culling issue (can't be in a strip, as you pointed out). – datenwolf Dec 04 '13 at 22:13
  • 1
    @datenwolf: Ah, I re-read the question and looked at the diagram again. Yeah, the "missing" (laptop LCD made them hard to see when I first looked at the question) dark triangles are definitely because the normals are being calculated on the CPU side after the winding order is reversed. The rasterizer does its job as described, but the actual Java code that is calculating the normals is not behaving as described; it needs to flip them for each alternate triangle as well. But in addition to that, the normals are being assigned to each vertex late so they are always off-by-one. – Andon M. Coleman Dec 04 '13 at 22:23
  • Thank you! This really helped me figure out what was going on and cleared a lot of things up. I eventually got it working. :) – Alpha Centauri A B Dec 05 '13 at 06:11