Anonymous
Вращение оси Y в Python
Сообщение
Anonymous » 03 ноя 2025, 18:22
Итак, я пытался создать 3D-движок с нуля на Python, когда пытался повернуть плоскость. Все оси были в порядке как предопределенные повороты в трехмерном пространстве, но при обновлении вращения в коде работали только оси x и z. Но что касается оси Y, то при обновлении вращения она выглядела как восьмиугольный беспорядок оригами.
Хотя он выглядит нормально, он продолжает трястись. Я не могу показать вам видео, но вы, скорее всего, поняли идею.
Вот весь код, который я написал на данный момент:
Код: Выделить всё
# imports
import pygame as pg
from vec import Vec3, Vec2
from math import sin, cos, tau
pg.init()
# screen
screen_dim: tuple[int, int] = (480, 360)
screen = pg.display.set_mode(screen_dim)
origin: Vec2 = Vec2(screen_dim[0] / 2, screen_dim[1] / 2)
# undertale
clock = pg.time.Clock()
delta: float = 1000 / clock.tick(60)
running: bool = True
# camera
class Camera:
def __init__(self, pos: Vec3, fov: float) -> None:
self.pos: Vec3 = pos
self.fov: float = fov
camera: Camera = Camera(Vec3(0, 0, -1), 120)
# vertex
class Vertex:
def __init__(self, pos: Vec3) -> None:
self.pos: Vec3 = pos
vertices = []
# creation
def create_vertex(pos: Vec3) -> None:
vertices.append(Vertex(pos))
def create_line(pos1: Vec3, pos2: Vec3) -> None:
vertices.append(Vertex(pos1))
vertices.append(Vertex(pos2))
def create_plane(pos: Vec3, dim: Vec2, rot: Vec3) -> None:
for i in range(-1, 2, 2):
for j in range(-1, 2, 2):
x_pos: float = dim.x / 2 * i
y_pos: float = dim.y / 2 * j
z_pos: float = 0
vertices.append(Vertex(Vec3(
pos.x + \
x_pos*(cos(rot.y)*cos(rot.z)) + \
y_pos*(cos(rot.z)*sin(rot.x)*sin(rot.y) - cos(rot.x)*sin(rot.z)) + \
z_pos*(cos(rot.x)*cos(rot.z)*sin(rot.y) + sin(rot.x)*sin(rot.z)), # y * z
pos.y + \
x_pos*(cos(rot.y)*sin(rot.z)) + \
y_pos*(cos(rot.x)*cos(rot.z) + sin(rot.x)*sin(rot.y)*sin(rot.z)) + \
z_pos*(cos(rot.x)*sin(rot.y)*sin(rot.z) - cos(rot.z)*sin(rot.x)), # x * z
pos.z + \
x_pos*(-sin(rot.y)) + \
y_pos*(cos(rot.y)*sin(rot.x)) + \
z_pos*(cos(rot.x)*cos(rot.y)) # x * y
)))
def calculate_vertex(vertex: Vertex) -> tuple[float, float]:
return (origin.x + (vertex.pos.x-camera.pos.x) * camera.fov/(vertex.pos.z-camera.pos.z),
origin.y + (vertex.pos.y-camera.pos.y) * camera.fov/(vertex.pos.z-camera.pos.z))
n: Vec3 = Vec3(0, 0, 0)
# drawing
def draw_vertex(vert_id: int, color: str, radius: float) -> None:
# NOTE: "vert_id" refers to the index of a vertex in th list
vertex: Vertex = vertices[vert_id]
pg.draw.circle(screen, color, calculate_vertex(vertex), radius)
def draw_line(vert_id: int, other_vert_id: int, color: str, width: float) -> None:
vertex: Vertex = vertices[vert_id]
other_vertex: Vertex = vertices[other_vert_id]
pg.draw.line(
screen, color,
calculate_vertex(vertex),
calculate_vertex(other_vertex),
width
)
# wireframe
def draw_plane_wf(vert_id: int, color: str, width: float) -> None:
if width == 0:
raise ValueError('it has wf for a reason')
pg.draw.polygon(
screen, color,
[calculate_vertex(vertices[vert_id]),
calculate_vertex(vertices[vert_id + 2]),
calculate_vertex(vertices[vert_id + 1]),
calculate_vertex(vertices[vert_id + 3])],
width
)
# filled in color
def draw_plane(vert_id, color: str) -> None:
vertex: Vertex = vertices[vert_id]
create_line(Vec3(1, 1, 1), Vec3(-1, -1, 1))
create_plane(Vec3(0, 0, 1), Vec2(1, 1), Vec3.zero())
while running:
delta: float = clock.tick(60) / 1000
# loop
for ev in pg.event.get():
if ev.type == pg.QUIT:
running = False
# update
del vertices[2:-1]
create_plane(Vec3(0, 0, 1), Vec2(1, 1), n)
n += Vec3(0, tau, 0) * delta
# draw
screen.fill('black')
for i in range(len(vertices)):
draw_vertex(i, 'white', 2)
draw_line(0, 1, 'red', 1)
draw_plane_wf(2, 'green', 2)
pg.display.flip()
И еще, при обновлении глючит только ось Y, а не остальные оси.
Подробнее здесь:
https://stackoverflow.com/questions/798 ... -in-python
1762183378
Anonymous
Итак, я пытался создать 3D-движок с нуля на Python, когда пытался повернуть плоскость. Все оси были в порядке как предопределенные повороты в трехмерном пространстве, но при обновлении вращения в коде работали только оси x и z. Но что касается оси Y, то при обновлении вращения она выглядела как восьмиугольный беспорядок оригами. [img]https://i.sstatic.net/1ifeO23L.png[/img] Хотя он выглядит нормально, он продолжает трястись. Я не могу показать вам видео, но вы, скорее всего, поняли идею. Вот весь код, который я написал на данный момент: [code]# imports import pygame as pg from vec import Vec3, Vec2 from math import sin, cos, tau pg.init() # screen screen_dim: tuple[int, int] = (480, 360) screen = pg.display.set_mode(screen_dim) origin: Vec2 = Vec2(screen_dim[0] / 2, screen_dim[1] / 2) # undertale clock = pg.time.Clock() delta: float = 1000 / clock.tick(60) running: bool = True # camera class Camera: def __init__(self, pos: Vec3, fov: float) -> None: self.pos: Vec3 = pos self.fov: float = fov camera: Camera = Camera(Vec3(0, 0, -1), 120) # vertex class Vertex: def __init__(self, pos: Vec3) -> None: self.pos: Vec3 = pos vertices = [] # creation def create_vertex(pos: Vec3) -> None: vertices.append(Vertex(pos)) def create_line(pos1: Vec3, pos2: Vec3) -> None: vertices.append(Vertex(pos1)) vertices.append(Vertex(pos2)) def create_plane(pos: Vec3, dim: Vec2, rot: Vec3) -> None: for i in range(-1, 2, 2): for j in range(-1, 2, 2): x_pos: float = dim.x / 2 * i y_pos: float = dim.y / 2 * j z_pos: float = 0 vertices.append(Vertex(Vec3( pos.x + \ x_pos*(cos(rot.y)*cos(rot.z)) + \ y_pos*(cos(rot.z)*sin(rot.x)*sin(rot.y) - cos(rot.x)*sin(rot.z)) + \ z_pos*(cos(rot.x)*cos(rot.z)*sin(rot.y) + sin(rot.x)*sin(rot.z)), # y * z pos.y + \ x_pos*(cos(rot.y)*sin(rot.z)) + \ y_pos*(cos(rot.x)*cos(rot.z) + sin(rot.x)*sin(rot.y)*sin(rot.z)) + \ z_pos*(cos(rot.x)*sin(rot.y)*sin(rot.z) - cos(rot.z)*sin(rot.x)), # x * z pos.z + \ x_pos*(-sin(rot.y)) + \ y_pos*(cos(rot.y)*sin(rot.x)) + \ z_pos*(cos(rot.x)*cos(rot.y)) # x * y ))) def calculate_vertex(vertex: Vertex) -> tuple[float, float]: return (origin.x + (vertex.pos.x-camera.pos.x) * camera.fov/(vertex.pos.z-camera.pos.z), origin.y + (vertex.pos.y-camera.pos.y) * camera.fov/(vertex.pos.z-camera.pos.z)) n: Vec3 = Vec3(0, 0, 0) # drawing def draw_vertex(vert_id: int, color: str, radius: float) -> None: # NOTE: "vert_id" refers to the index of a vertex in th list vertex: Vertex = vertices[vert_id] pg.draw.circle(screen, color, calculate_vertex(vertex), radius) def draw_line(vert_id: int, other_vert_id: int, color: str, width: float) -> None: vertex: Vertex = vertices[vert_id] other_vertex: Vertex = vertices[other_vert_id] pg.draw.line( screen, color, calculate_vertex(vertex), calculate_vertex(other_vertex), width ) # wireframe def draw_plane_wf(vert_id: int, color: str, width: float) -> None: if width == 0: raise ValueError('it has wf for a reason') pg.draw.polygon( screen, color, [calculate_vertex(vertices[vert_id]), calculate_vertex(vertices[vert_id + 2]), calculate_vertex(vertices[vert_id + 1]), calculate_vertex(vertices[vert_id + 3])], width ) # filled in color def draw_plane(vert_id, color: str) -> None: vertex: Vertex = vertices[vert_id] create_line(Vec3(1, 1, 1), Vec3(-1, -1, 1)) create_plane(Vec3(0, 0, 1), Vec2(1, 1), Vec3.zero()) while running: delta: float = clock.tick(60) / 1000 # loop for ev in pg.event.get(): if ev.type == pg.QUIT: running = False # update del vertices[2:-1] create_plane(Vec3(0, 0, 1), Vec2(1, 1), n) n += Vec3(0, tau, 0) * delta # draw screen.fill('black') for i in range(len(vertices)): draw_vertex(i, 'white', 2) draw_line(0, 1, 'red', 1) draw_plane_wf(2, 'green', 2) pg.display.flip() [/code] И еще, при обновлении глючит только ось Y, а не остальные оси. Подробнее здесь: [url]https://stackoverflow.com/questions/79807734/y-axis-rotation-in-python[/url]