背景
我正在尝试制作一个 CAD 查看器,我可以将 STL 文件带入其中并简单地旋转、平移等。这不应该像游戏那样先进。
我在照明方面遇到了困难,这可以在以前的帖子中看到: 以前的帖子
问题
基本上我现在已经亮了,我在正确的地方有我的弹出和推送矩阵调用。我现在要做的就是优化我的照明,使其类似于 CAD 环境。如果我错了,请纠正我,但我相信观看零件的最佳照明总是让相机上的光指向物体的方向。如果这不是进行照明的最佳方式,请随时提出更好的方式。
我认为这主要归结为数学。我不知道是否有任何内置函数可以简单地获取相机的位置,或者您是否必须跟踪它。
这是我的显示功能:
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
基本上我有 lighting_x、lighting_y 和 lighting_z 作为变量来移动我的光。我有一个变量 X、Y 和 Z 来建立平移 (Gl.glTranslatef(X, Y, Z))。变量 rotx、roty 和 rotz 使用 Gl.glRotatef(rotX, 1.0F, 0.0F, 0.0F) 在主函数中设置旋转。
这些变量被应用于整个场景,这在 CAD 环境中是有意义的,因此我的轴也会移动。
最重要的是,我正在使用 gluLookAt 函数来创建“缩放以适应”函数。据我了解,我的显示功能中的功能移动和旋转我的环境,但 gluLookAt 正在移动我的相机。保持这些之间的关系必须是我的照明计算所需要的:
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
我不知道环境在最初运行时将相机相对于原点放置在哪里,但我认为这也需要考虑在内。
到目前为止我能看到的:
茶壶的光面:
月之暗面(茶壶):
所有代码都是用 VB.NET 编写的,但 C# 答案也可以。