OpenGL圆变换后正射投影、透视投影及相机旋转实现求助
问题解答
Q1:变换后圆在xy平面的正射投影
推导过程
- 原圆参数方程(θ∈[0, 2π)):
x₀ = 40 + 20cosθ y₀ = 40 + 20sinθ z₀ = 0 - 绕X轴逆时针转30°的旋转矩阵作用后坐标:
x₁ = x₀ = 40 + 20cosθ y₁ = y₀ * cos30° - z₀ * sin30° = (40 + 20sinθ) * (√3/2) z₁ = y₀ * sin30° + z₀ * cos30° = (40 + 20sinθ) * 0.5 - 沿Z轴正方向平移20单位后最终坐标:
x = x₁ = 40 + 20cosθ y = y₁ = 20√3 + 10√3 sinθ z = z₁ + 20 = 40 + 10sinθ - 正射投影到xy平面直接丢弃z坐标,最终投影为椭圆,标准方程为:
椭圆中心为(40, 20√3),x方向半轴长20,y方向半轴长10√3。((x - 40)/20)² + ((y - 20√3)/(10√3))² = 1
Q2:透视投影求解与实现代码
投影规则推导
三个坐标轴点(100, 0, 0)、(0, 100, 0)、(0, 0, 100)构成的平面方程为x + y + z = 100。相机位于原点,透视投影为原点出发的射线穿过圆上点,与该平面的交点:
- 设圆上任意点坐标为(x, y, z),射线参数方程为
t(x, y, z), t>0 - 代入平面方程得
t = 100/(x+y+z) - 最终投影点坐标为
(100x/(x+y+z), 100y/(x+y+z), 100z/(x+y+z))
可运行实现代码(含相机沿Z轴旋转效果)
from OpenGL.GL import * from OpenGL.GLUT import * from OpenGL.GLU import * from math import * # 相机绕Z轴旋转角度 cam_rotate = 0.0 # 变换后圆的圆心坐标 target_x, target_y, target_z = 40, 40 * cos(radians(30)), 40 * sin(radians(30)) + 20 def circle(): posx, posy = 40,40 sides = 80 radius = 20 glBegin(GL_POLYGON) for i in range(sides): cosine = radius * cos(i*2*pi/sides) + posx sine = radius * sin(i*2*pi/sides) + posy glVertex3f(cosine, sine, 0) glEnd() def iterate(): global cam_rotate glViewport(0, 0, 800, 800) # 设置透视投影 glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(60, 1, 0.1, 1000) # 设置视图变换+模型变换 glMatrixMode(GL_MODELVIEW) glLoadIdentity() # 相机绕Z轴旋转 glRotatef(cam_rotate, 0, 0, 1) # 相机位于原点,看向变换后的圆心,向上向量为原Z轴(0,0,1) gluLookAt(0, 0, 0, target_x, target_y, target_z, 0, 0, 1) # 圆的变换:先绕X轴转30度,再沿Z轴平移20 glTranslatef(0, 0, 20) glRotatef(30, 1, 0, 0) # 每帧旋转角度+0.5度 cam_rotate += 0.5 def showScreen(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) iterate() glColor3f(1.0, 0.0, 0.0) circle() glutSwapBuffers() glutInit() glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH) glutInitWindowSize(800, 800) glutInitWindowPosition(200, 200) wind = glutCreateWindow("Perspective Projection Demo") # 开启深度测试 glEnable(GL_DEPTH_TEST) glClearColor(1.0, 1.0, 1.0, 1.0) glutDisplayFunc(showScreen) glutIdleFunc(showScreen) glutMainLoop()
内容的提问来源于stack exchange,提问作者XGB
相关产品推荐
相关产品推荐

