问题描述
所以我一直在尝试学习3D渲染的工作原理。我尝试编写一个脚本,目标是在3D空间中旋转平面(2D)正方形。我首先在标准化空间(-1,1)中定义一个正方形。请注意,只有x和y被归一化。
class Vec3:
# 3D VECTOR
def __init__(self,x,y,z):
self.x = x
self.y = y
self.z = z
s = 1
p1 = Vec3(-s,-s,-s)
p2 = Vec3(s,-s)
p3 = Vec3(s,s,-s)
p4 = Vec3(-s,-s)
然后将这些点翻译到屏幕中
p1.z += 6
p2.z += 6
p3.z += 6
p4.z += 6
此后的所有操作都在应用程序循环内完成。我使用以下功能应用投影来将点缩放到屏幕上:
class Transform:
# IT TRANSFORMS THE X AND Y FROM NORMALISED SPACE TO SCREEN SPACE WITH PROJECTION APPLIED
def worldSpaceTransform(self,vec3,w,h):
if vec3.z == 0:
vec3.z = 0.001
zInverse = 1/ vec3.z
xTransformed = ((vec3.x * zInverse) + 1) * (w/2)
yTransformed = ((-vec3.y * zInverse) + 1) * (h/2)
xTransformed = str(xTransformed)[:6]
yTransformed = str(yTransformed)[:6]
return Vec2(float(xTransformed),float(yTransformed))
像这样:
# TRANSLATING THE SQUARE SHEET INTO THE SCREEN SPACE
point1 = transform.worldSpaceTransform(p1,SCREENWIDTH,SCREENHEIGHT)
point2 = transform.worldSpaceTransform(p2,SCREENHEIGHT)
point3 = transform.worldSpaceTransform(p3,SCREENHEIGHT)
point4 = transform.worldSpaceTransform(p4,SCREENHEIGHT)
并指出要点:
# STORING THE POINTS TO A TUPLE SO IT CAN BE DRAWN USING pygame.draw.lines
points = ((point1.x,point1.y),(point2.x,point2.y),(point3.x,point3.y),(point4.x,point4.y),(point1.x,point1.y))
pygame.draw.lines(D,(0,0),False,points)
(我认为)到目前为止,所有方法都可以正常工作,因为它按照预期的方式绘制了一个正方形。
现在旋转。我尝试了所有轴的旋转,但没有一个起作用,但是为了具体起见,我将讨论x轴。以下是旋转类。我从维基百科复制了旋转矩阵。我不确定它们如何工作,因此我也不知道它是否与我上面描述的系统兼容。
def multVecMatrix(vec3,mat3):
# MULTIPLIES A Vec3 OBJECT WITH Mat3 OBJECT AND RETURNS A NEW Vec3 ?
x = vec3.x * mat3.matrix[0][0] + vec3.y * mat3.matrix[0][1] + vec3.z * mat3.matrix[0][2]
y = vec3.x * mat3.matrix[1][0] + vec3.y * mat3.matrix[1][1] + vec3.z * mat3.matrix[1][2]
z = vec3.x * mat3.matrix[2][0] + vec3.y * mat3.matrix[2][1] + vec3.z * mat3.matrix[2][2]
return Vec3(x,z)
class Rotation:
def rotateX(self,theta):
# ROTATION MATRIX IN X AXIS ??
sinTheta = sin(theta)
cosTheta = cos(theta)
m = Mat3()
m.matrix = [[1,0],[0,cosTheta,sinTheta],-sinTheta,cosTheta]]
return m
def rotate(self,theta,axis=None):
# ROTATES A Vec3 BY GIVEN THETA AND AXIS ??
if axis == "x":
return multVecMatrix(vec3,self.rotateX(theta))
if axis == "y":
return multVecMatrix(vec3,self.rotateY(theta))
if axis == "z":
return multVecMatrix(vec3,self.rotateZ(theta))
在将屏幕填满白色之后,再将点从标准化空间缩放到屏幕空间之前,这样称呼它。
# screen is filled with white color
# ROTATING THE POINTS AROUND X AXIS ?????
p1.x = rotation.rotate(p1,thetax,axis='x').x
p1.y = rotation.rotate(p1,thetay,axis='x').y
p1.z = rotation.rotate(p1,axis='x').z
p2.x = rotation.rotate(p2,axis='x').x
p2.y = rotation.rotate(p2,axis='x').y
p2.z = rotation.rotate(p2,axis='x').z
p3.x = rotation.rotate(p3,axis='x').x
p3.y = rotation.rotate(p3,axis='x').y
p3.z = rotation.rotate(p3,axis='x').z
p4.x = rotation.rotate(p4,axis='x').x
p4.y = rotation.rotate(p4,axis='x').y
p4.z = rotation.rotate(p4,axis='x').z
# then the points are translated into world space
应用旋转后,看起来它正在移动并绕着x轴旋转,但没有旋转。我希望它旋转并保持原样。我在做什么错了?
完整的复制粘贴代码以供参考:
import pygame
from math import sin,cos,radians
pygame.init()
### PYGAME STUFF ######################################
SCREENWIDTH = 600
SCREENHEIGHT = 600
D = pygame.display.set_mode((SCREENWIDTH,SCREENHEIGHT))
pygame.display.set_caption("PRESS SPACE TO ROTATE AROUND X")
######### MATH FUNCTIONS AND CLASSES ####################
class Mat3:
# 3X3 MATRIX INITIALIZED WITH ALL 0's
def __init__(self):
self.matrix = [[0 for i in range(3)],[0 for i in range(3)],[0 for i in range(3)]]
class Vec2:
# 2D VECTOR
def __init__(self,y):
self.x = x
self.y = y
class Vec3:
# 3D VECTOR
def __init__(self,z):
self.x = x
self.y = y
self.z = z
def multVecMatrix(vec3,mat3):
# MULTIPLIES A Vec3 OBJECT WITH Mat3 OBJECT AND RETURNS A NEW Vec3
x = vec3.x * mat3.matrix[0][0] + vec3.y * mat3.matrix[0][1] + vec3.z * mat3.matrix[0][2]
y = vec3.x * mat3.matrix[1][0] + vec3.y * mat3.matrix[1][1] + vec3.z * mat3.matrix[1][2]
z = vec3.x * mat3.matrix[2][0] + vec3.y * mat3.matrix[2][1] + vec3.z * mat3.matrix[1][2]
return Vec3(x,z)
class Transform:
# IT TRANSFORMS THE X AND Y FROM NORMALIZED SPACE TO SCREEN SPACE WITH PROJECTION APPLIED
def worldSpaceTransform(self,float(yTransformed))
class Rotation:
def rotateX(self,theta):
# ROTATION MATRIX IN X AXIS
sinTheta = sin(theta)
cosTheta = cos(theta)
m = Mat3()
m.matrix = [[1,axis=None):
# ROTATES A Vec3 BY GIVEN THETA AND AXIS
if axis == "x":
return multVecMatrix(vec3,self.rotateZ(theta))
transform = Transform()
rotation = Rotation()
# ASSIGNING 4 Vec3's FOR 4 SIDES OF SQUARE IN NORMALIZED SPACE
s = 1
p1 = Vec3(-s,-s)
# TRANSLATING THE POINTS OF THE CUBE A LITTLE BIT INTO THE SCREEN
p1.z += 6
p2.z += 6
p3.z += 6
p4.z += 6
# ASSIGNING THE ROTATION ANGLES
thetax = 0
# APPLICATION LOOP
while True:
pygame.event.get()
D.fill((255,255,255))
# ROTATING THE POINTS AROUND X AXIS
p1.x = rotation.rotate(p1,axis='x').z
# TRANSLATING THE SQUARE SHEET INTO THE SCREEN SPACE
point1 = transform.worldSpaceTransform(p1,SCREENHEIGHT)
# STORING THE POINTS TO A TUPLE SO IT CAN BE DRAWN USING pygame.draw.lines
points = ((point1.x,point1.y))
keys = pygame.key.get_pressed()
# ROTATE X ?
if keys[pygame.K_SPACE]:
thetax -= 0.005
pygame.draw.lines(D,points)
pygame.display.flip()
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)