rot2d ломает и изменяет позицию
я пишу с нуля 3д движок со своей координатной системой и я застрял на повороте точек. Если смотреть на этот куб достаточно долго, то можно увидеть, что он превращается в параллелепипед.
import pygame
from math import *
(width, height) = (1280, 960)
screen = pygame.display.set_mode((width, height))
running = True
"""
k=open('/storage/emulated/0/Download/airboat.obj')
n=k.readlines()
k.close()
vert=[]
for i in n:
if len(i.split())!=0:
if i.split()[0]=="v":
vert.append(list(map(float,i.split()[1:4])))
"""
d=[[1,1,1],
[1,1,-1],
[1,-1,1],
[1,-1,-1],
[-1,1,1],
[-1,1,-1],
[-1,-1,1],
[-1,-1,-1]]
l=[[0,0,0,0,999,0,(0,255,0)],
[0,0,0,999,0,0,(255,0,0)],
[0,0,0,0,0,999,(0,0,255)],
[0,0,0,0,-999,0,(255,0,255)],
[0,0,0,-999,0,0,(0,255,255)],
[0,0,0,0,0,-999,(255,255,0)]]
import math
def rot2d(ox, oy, theta, px, py):
px = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox
py = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy
return [px,py]
def mul2d(vec2d,n): # z is not used
k=[]
for i in range(0,2):
k.append(vec2d[i]*n)
return k
def div2d(vec2d,n): # z is not used
k=[]
for i in range(0,2):
k.append(vec2d[i]/n)
return k
def add2d(vec2d,vec2db): # z is not used
k=[]
for i in range(0,2):
k.append(vec2d[i]+vec2db[i])
return k
def sub2d(vec2d,vec2db): # z is not used
k=[]
for i in range(0,2):
k.append(vec2d[i]-vec2db[i])
return k
def center2d(h,w,vec2d):
return [vec2d[0]+w/2,vec2d[1]+h/2]
class Vec3d:
def __init__(self, x:int, y:int, z:int):
self.x=x
self.y=y
self.z=z
def getXY(self,factor=180,safe=True): #todo: vyebat
if self.z>0:
return [self.x/(self.z/factor),self.y/(self.z/factor)]
def __add__(self,vec):
return Vec3d(vec.x+self.x,vec.y+self.y,vec.z+self.z)
def __sub__(self,vec):
return Vec3d(vec.x-self.x,vec.y-self.y,vec.z-self.z)
def __mul__(self,num):
return Vec3d(self.x*num,self.y*num,self.z*num)
def __div__(self,num):
return Vec3d(self.x/num,self.y/num,self.z/num)
def __repr__(self):
return f"Vec3d({self.x}, {self.y}, {self.z})"
def __str__(self):
return f"Vec3d({self.x}, {self.y}, {self.z})"
def listToVec3d(l):
return Vec3d(l[0],l[1],l[2])
camerapos=Vec3d(0,0,6)
dtime=0
time=0
rot=0
clk= pygame.time.Clock()
pygame.font.init()
font = pygame.font.SysFont('Consolas', 50)
def rotate(model: list, axis: str, center: list, deg: int):
d=model
deg=radians(deg)
if axis=="xy" or axis=="yx":
for k in d:
n=rot2d(center[0],center[1],deg,k[0],k[1])
k[0]=n[0]
k[1]=n[1]
if axis=="yz" or axis=="zy":
for k in d:
n=rot2d(center[1],center[2],deg,k[1],k[2])
k[1]=n[0]
k[2]=n[1]
if axis=="zx" or axis=="xz":
for k in d:
n=rot2d(center[2],center[0],deg,k[2],k[0])
k[2]=n[0]
k[0]=n[1]
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((16,16,16))
pygame.draw.line(screen, (255,255,255),[width,0],[width,height])
pygame.draw.line(screen, (255,255,255),[0,height],[width,height])
fps=clk.get_fps()
for k in d:
a=(listToVec3d(k)-camerapos).getXY()
if a!=None:
c=center2d(height,width,mul2d(a,2))
screen.set_at(list(map(int,c)),(255,255,255))
pygame.draw.circle(screen, (255,255,255), c,5)
for lin in l:
ai=(listToVec3d(lin[0:3])-camerapos).getXY()
bi=(listToVec3d(lin[3:6])-camerapos).getXY()
if ai!=None:
a=center2d(height,width,mul2d(ai,2))
if bi!=None:
b=center2d(height,width,mul2d(bi,2))
if a!=None and b!=None: pygame.draw.line(screen, lin[6],a,b)
text_surface= font.render(f"fps: {round(fps,2)}", (255,0,255),True)
screen.blit(text_surface, (50, 50))
text_surface= font.render(f"sec: {round(1/(fps+0.01),2)}", (255,0,255),True)
screen.blit(text_surface, (50, 100))
text_surface= font.render(f"rot: {rot}", (255,0,255),True)
screen.blit(text_surface, (50, 150))
dtime=1/(fps+0.001)
clk.tick()
time+=dtime
rot+=1
rotate(d, "xz", [0,0,0], 1)
if rot>360:
rotate(d, "xz", [0,0,0], -rot)
rot=0
pygame.display.flip()
Ответы (1 шт):
Автор решения: MBo
→ Ссылка
def rot2d(ox, oy, theta, px, py):
px = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox
py = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy
=>
def rot2d(ox, oy, theta, px, py):
t = px
px = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox
py = sin(theta) * (t-ox) + cos(theta) * (py-oy) + oy
Из мелочей - один раз посчитайте синус и косинус, и используйте в качестве параметров rot2d, вместо того, чтобы для каждой точки, да ещё дважды считать