Original Post
Can you see anything wrong with this OpenGL Light class(C#) or the normal generation function here? With a light mode of 1 (I.e setting the four par in the light position call to 1) I get good lighting on one side of the plane, but bad non existant lighting on the other. With a light mode of 0 I get no lighting at all except for highlights.) Even with no shininess or specular, turning the camera still affects the light sourec as well, it shimmers. Are there any great tutorials/methods for normal generation on the net? Or general gl lighting tutorials? (Not how to set it up, but how to use it effectively to achieve good lighting in practical siturations) Light Class. Normal Generator.
namespace Vivid3D
{
public class Light : Pivot
{
public int glLight, lightObj;
public static int[] lstack = new int[8];
public static int[] GL_Light = new int[8];
public static void SetupLights()
{
GL_Light[0] = Gl.GL_LIGHT0;
GL_Light[1] = Gl.GL_LIGHT1;
GL_Light[2] = Gl.GL_LIGHT2;
GL_Light[3] = Gl.GL_LIGHT3;
GL_Light[4] = Gl.GL_LIGHT4;
GL_Light[5] = Gl.GL_LIGHT5;
GL_Light[6] = Gl.GL_LIGHT6;
GL_Light[7] = Gl.GL_LIGHT7;
}
public static int RequestLight()
{
for (int j = 0; j < 8; j++)
{
if (lstack[j] == 0)
{
lstack[j] = 1;
Gl.glEnable(GL_Light[j]);
return j;
}
}
return -1;
}
public static void FreeLight(int light)
{
if (light < 0 || light > 7) return;
lstack[light] = 0;
Gl.glDisable(GL_Light[light]);
}
public Light()
{
glLight = Light.RequestLight();
if (glLight != -1)
{
lightObj = Light.GL_Light[glLight];
}
}
~Light()
{
Light.FreeLight(glLight);
}
public void SetupGL()
{
float[] mat_spec = new float[4];
float[] mat_shin = new float[4];
float[] light_pos = new float[4];
mat_spec[0] = 0;
mat_spec[1] = 0;
mat_spec[2] = 0;
mat_spec[3] = 0;
mat_shin[0] = 0;
light_pos[0] = X;
light_pos[1] = Y;
light_pos[2] = Y;
light_pos[3] = 1;
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SPECULAR,mat_spec);
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SHININESS,mat_shin);
Gl.glLightfv(lightObj,Gl.GL_POSITION,light_pos);
}
}
}
public void UpdateNormals()
{
float[] Face_NX = new float[triCount];
float[] Face_NY = new float[triCount];
float[] Face_NZ = new float[triCount];
int[] Vertex_ConnectedTris = new int[vertexCount];
int[,] Vertex_TriList = new int[vertexCount,64];
for (int i = 0; i < triCount; i++)
{
Face_NX = 0;
Face_NY = 0;
Face_NZ = 0;
}
for (int i = 0; i < vertexCount; i++)
{
Vertex_ConnectedTris = 0;
for (int k = 0; k < 64; k++)
{
Vertex_TriList[i, k] = 0;
}
}
Console.WriteLine("About to update surface normals.");
Console.WriteLine("Surface has " + CountTriangles().ToString() + " Triangles");
for (int LOOP_Tris = 0; LOOP_Tris < CountTriangles(); LOOP_Tris++)
{
Console.WriteLine("Updating Normal:" + LOOP_Tris.ToString());
int Vertex_0, Vertex_1, Vertex_2;
Vertex_0 = TriangleVertex(LOOP_Tris, 0);
Vertex_1 = TriangleVertex(LOOP_Tris, 1);
Vertex_2 = TriangleVertex(LOOP_Tris, 2);
int ConnectedTris = Vertex_ConnectedTris[Vertex_0];
Vertex_TriList[Vertex_0, ConnectedTris] = LOOP_Tris;
Vertex_ConnectedTris[Vertex_0] = ConnectedTris + 1;
ConnectedTris = Vertex_ConnectedTris[Vertex_1];
Vertex_TriList[Vertex_1, ConnectedTris] = LOOP_Tris;
Vertex_ConnectedTris[Vertex_1] = ConnectedTris + 1;
ConnectedTris = Vertex_ConnectedTris[Vertex_2];
Vertex_TriList[Vertex_2, ConnectedTris] = LOOP_Tris;
Vertex_ConnectedTris[Vertex_2] = ConnectedTris + 1;
float Ax, Ay, Az, Bx, By, Bz, Cx, Cy, Cz;
Ax = VertexX(Vertex_0);
Ay = VertexY(Vertex_0);
Az = VertexZ(Vertex_0);
Bx = VertexX(Vertex_1);
By = VertexY(Vertex_1);
Bz = VertexZ(Vertex_1);
Cx = VertexX(Vertex_2);
Cy = VertexY(Vertex_2);
Cz = VertexZ(Vertex_2);
float Px, Py, Pz, Qx, Qy, Qz;
Px = Ax - Bx;
Py = Ay - By;
Pz = Az - Bz;
Qx = Bx - Cx;
Qy = By - Cy;
Qz = Bz - Cz;
float Nx, Ny, Nz;
Nx = Py * Qz - Pz * Qy;
Ny = Pz * Qx - Px * Qz;
Nz = Px * Qy - Py * Qx;
Face_NX[LOOP_Tris] = Nx;
Face_NY[LOOP_Tris] = Ny;
Face_NZ[LOOP_Tris] = Nz;
}
Console.WriteLine("Updating surface vertice normals.");
for (int Loop_Vertices = 0; Loop_Vertices < CountVertices(); Loop_Vertices++)
{
Console.WriteLine("Updating vertice " + Loop_Vertices.ToString());
float Nx, Ny, Nz;
Nx = Ny = Nz = 0;
int Polys = Vertex_ConnectedTris[Loop_Vertices];
for (int Loop_Polys = 0; Loop_Polys < Polys; Loop_Polys++)
{
int ThisPoly = Vertex_TriList[Loop_Vertices,Loop_Polys];
Nx += Face_NX[ThisPoly];
Ny += Face_NY[ThisPoly];
Nz += Face_NZ[ThisPoly];
}
float N1 = (float)Math.Sqrt((double)Nx * (double)Nx + (double)Ny * (double)Ny + (Double)Nz * (double)Nz);
Nx = Nx / N1;
Ny = Ny / N1;
Nz = Nz / N1;
VertexNormal(Loop_Vertices, Nx, Ny, Nz);
}
}