Background
I am attempting to make a CAD viewer to which I can bring in an STL file and simply rotate, pan, etc. This shouldn't be anything that advanced like a game.
I was having difficulty with lighting which can be seen in a previous post: Previous Post
Problem
Basically I have light on now, and I have my pop and push matrix call outs in the right place. All I am trying to do now is to optimize my lighting to be like a CAD environment. Correct me if I am wrong but I believe the best lighting for viewing a part is always having the light at the camera pointing in the direction of the object. If this is not the optimal way to do lighting, by all means feel free to suggest a better way.
I think this mostly comes down to math. I don't know if there are any built in functions to simply get where the camera is, or if you have to keep track of it.
Here is what I have for my display function:
Private Sub display()
Gl.glEnable(Gl.GL_DEPTH_TEST)
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT)
Gl.glClear(Gl.GL_DEPTH_BUFFER_BIT)
Gl.glPushMatrix()
Gl.glRotatef(rotX, 1.0F, 0.0F, 0.0F)
' Rotate on x
Gl.glRotatef(rotY, 0.0F, 1.0F, 0.0F)
' Rotate on y
Gl.glRotatef(rotZ, 0.0F, 0.0F, 1.0F)
' Rotate on z
Gl.glTranslatef(X, Y, Z)
'Draw x,y,z axis
Gl.glBegin(Gl.GL_LINES)
Gl.glColor4f(0.0F, 1.0F, 0.0F, 1.0F)
' Green for x axis
Gl.glVertex3f(0.0F, 0.0F, 0.0F)
Gl.glVertex3f(5000.0F, 0.0F, 0.0F)
Gl.glColor3f(1.0F, 0.0F, 0.0F)
' Red for y axis
Gl.glVertex3f(0.0F, 0.0F, 0.0F)
Gl.glVertex3f(0.0F, 5000.0F, 0.0F)
Gl.glColor3f(0.0F, 0.0F, 1.0F)
' Blue for z axis
Gl.glVertex3f(0.0F, 0.0F, 0.0F)
Gl.glVertex3f(0.0F, 0.0F, 15.0F)
Gl.glEnd()
' Dotted lines for the negative sides of x,y,z
Gl.glEnable(Gl.GL_LINE_STIPPLE)
' Enable line stipple to
' use a dotted pattern for
' the lines
Gl.glLineStipple(1, &H101)
' Dotted stipple pattern for
' the lines
Gl.glBegin(Gl.GL_LINES)
Gl.glColor3f(0.0F, 1.0F, 0.0F)
' Green for x axis
Gl.glVertex3f(-5000.0F, 0.0F, 0.0F)
Gl.glVertex3f(0.0F, 0.0F, 0.0F)
Gl.glColor3f(1.0F, 0.0F, 0.0F)
' Red for y axis
Gl.glVertex3f(0.0F, 0.0F, 0.0F)
Gl.glVertex3f(0.0F, -5000.0F, 0.0F)
Gl.glColor3f(0.0F, 0.0F, 1.0F)
' Blue for z axis
Gl.glVertex3f(0.0F, 0.0F, 0.0F)
Gl.glVertex3f(0.0F, 0.0F, -5000.0F)
Gl.glEnd()
Gl.glDisable(Gl.GL_LINE_STIPPLE)
' Disable the line stipple
Gl.glColor3f(1.0F, 1.0F, 1.0F)
Glut.glutSolidTeapot(5)
Gl.glEnable(Gl.GL_LIGHTING)
Label1.Text = "X=" & lighting_x & ", Y=" & lighting_y & " Z=" & lighting_z
Light1Position = {lighting_x, lighting_y, lighting_z, 0.0F}
' Enable Default Light
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_AMBIENT, Light1Ambient)
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_DIFFUSE, Light1Diffuse)
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, Light1Position)
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_SPECULAR, Light1Specular)
Gl.glEnable(Gl.GL_LIGHT1)
Gl.glPopMatrix()
draw_extras()
Gl.glEnable(Gl.GL_COLOR_MATERIAL)
Gl.glColorMaterial(Gl.GL_FRONT, Gl.GL_AMBIENT_AND_DIFFUSE)
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SPECULAR, MaterialSpecular)
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SHININESS, SurfaceShininess)
Gl.glEnable(Gl.GL_COLOR_MATERIAL)
Glut.glutSwapBuffers()
End Sub
Basically I have lighting_x, lighting_y, and lighting_z as variables to move my light around. I have a variables X, Y, and Z that establish the panning (Gl.glTranslatef(X, Y, Z)). The variables rotx, roty, and rotz set the rotation in the main function using Gl.glRotatef(rotX, 1.0F, 0.0F, 0.0F).
These variables are being applied to the whole scene which makes sense in a CAD environment so that my axis moves as well.
On top of this, I am using the gluLookAt function to create a "zoom to fit" function. From what I understand, the functions in my display function move and rotate my environment but the gluLookAt is moving my camera. Keeping the relation between these must be what is needed for my lighting calculation:
Private Sub zoom_fit()
rotX = 0
rotY = 0
rotZ = 0
rotLx = 0
rotLy = 0
rotLz = 0
Dim i As Integer = 1
Dim maxz As Decimal = -10000
Do Until i >= ListView1.Items.Count
If Convert.ToDecimal(ListView1.Items.Item(i).SubItems(2).Text) > maxz Then
maxz = Convert.ToDecimal(ListView1.Items.Item(i).SubItems(2).Text)
End If
If Convert.ToDecimal(ListView1.Items.Item(i + 1).SubItems(2).Text) > maxz Then
maxz = Convert.ToDecimal(ListView1.Items.Item(i).SubItems(2).Text)
End If
If Convert.ToDecimal(ListView1.Items.Item(i + 2).SubItems(2).Text) > maxz Then
maxz = Convert.ToDecimal(ListView1.Items.Item(i).SubItems(2).Text)
End If
i = i + 4
Loop
rotLz = Convert.ToSingle((maxz - avgz) * 10)
Gl.glMatrixMode(Gl.GL_MODELVIEW)
Gl.glLoadIdentity()
Glu.gluLookAt(rotLx, rotLy, 15.0 + rotLz, 0.0, 0.0, 0.0, _
0.0, 1.0, 0.0)
Glut.glutPostRedisplay()
End Sub
I don't know where the environment puts the camera relative to the origin when it initially runs but I would think that this too would need to be taken into account.
What I can see so far:
The light side of the teapot:
Dark side of the moon (teapot):
All code is written in VB.NET but C# answers would work too.