numpy旋转3d矩阵
本帖最后由 cjjJasonchen 于 2024-8-20 22:52 编辑初始位置,x,y = 100,100
再旋转时y迅速变小到接近零,x缓慢变小至接近零
"""
矩阵旋转算法,这或许是真的3d?
"""
import pygame
import sys
import math
import numpy
import pygameGUI as pgui
from typing import List
from pygame.locals import *
class Sprites3D:
X, Y, Z = 0, 1, 2
def __init__(self):
self.position = [100,
100,
0,
]
def draw(self, screen):
pygame.draw.circle(screen, (255, 0, 0), , self.position], 10)
def update(self):
angle = math.radians(10)
rz = numpy.array(
[,
,
,
,
]
)
rx = numpy.array(
[
,
,
,
,
]
)
position = numpy.array([
],
],
],
])
position = rz * position
self.position = [
position,
position,
position,
]
# 颜色常量
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
size = width, height = 800, 600
screen = pygame.display.set_mode(size)
pygame.display.set_caption("title")
clock = pygame.time.Clock()
delay = 60# 延时计时器(1秒)
# 是否全屏
fullscreen = False
screen_change = False
# 背景颜色设定
bg_color = WHITE
running = True
# 3d对象
s3d = Sprites3D()
# ui======
guis = pgui.Group()
m = pgui.Message(group=guis, text=str(s3d.position) + "\n" + str(s3d.position) + "\n" + str(s3d.position))
m.set_pos("center", )
# =========
while running:
# 设定帧数
clock.tick(60)
# 延时计时器刷新
if delay == 0:
delay = 60
delay -= 1
# 检测是否全屏
if fullscreen and screen_change:
screen = pygame.display.set_mode(size, FULLSCREEN, HWSURFACE)
screen_change = False
elif screen_change:
screen = pygame.display.set_mode(size)
screen_change = False
# 事件检测
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# 鼠标
if event.type == MOUSEBUTTONDOWN:
pass
# 按键按下事件
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
# F11切换全屏
if event.key == K_F11:
fullscreen = not fullscreen
screen_change = True
# 按键抬起事件
if event.type == KEYUP:
pass
# 画背景
screen.fill(bg_color)
# 刷新xxx
m.text = str(s3d.position) + "\n" + str(s3d.position) + "\n" + str(int(s3d.position))
s3d.update()
guis.update()
# 画 xxxx
guis.draw(screen)
s3d.draw(screen)
# 刷新界面
pygame.display.update()
@FishC 鱼油你好,看起来你正尝试用 `pygame` 和 `numpy` 实现一个3D旋转矩阵。不过呢,你这个代码还有不少坑,我们得给它填满才行。
首先,我们需要了解如何在三维空间旋转一个点。3D旋转可以通过旋转矩阵来实现,这些矩阵分别用于绕 x, y, z 轴旋转。假设你每次旋转10度,那我们先来给每个旋转轴创建一个矩阵。
1. 绕 z 轴旋转的矩阵:
rz = numpy.array([
,
,
])
2. 绕 x 轴旋转的矩阵:
rx = numpy.array([
,
,
])
这些矩阵会帮助我们实现绕不同轴的旋转,现在让我们来填补剩余的代码,并通过这些矩阵来更新位置。
import pygame
import sys
import math
import numpy
from pygame.locals import *
class Sprites3D:
X, Y, Z = 0, 1, 2
def __init__(self, x, y, z):
self.position = numpy.array()
def draw(self, screen):
# 将3D坐标简单地转换为2D坐标
screen_position = ), int(self.position)]
pygame.draw.circle(screen, (255, 0, 0), screen_position, 10)
def update(self):
angle = math.radians(10)
rz = numpy.array([
,
,
])
rx = numpy.array([
,
,
])
# 先绕Z轴旋转,再绕X轴旋转
self.position = rz @ self.position
self.position = rx @ self.position
# ----- Pygame Setup -----
# 颜色常量
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
size = width, height = 800, 600
screen = pygame.display.set_mode(size)
pygame.display.set_caption("3D Rotation")
clock = pygame.time.Clock()
# 3D对象
s3d = Sprites3D(100, 100, 100)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(WHITE)
s3d.update()
s3d.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
这样,我们现在每帧都以10度的速度先绕 Z 轴再绕 X 轴旋转一个点。赶紧运行看看效果吧。当然,创建3D的视觉效果仅靠 x 和 y 平面上的点画个圆难显神奇,有世界变换和相机同步才是真实的。后续你可以考虑引入更多的3D图形学概念来尝试更复杂的构建!
任何问题随时来问,我随时给你解答哈!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 已经解决了,是因为numpy数组使用的乘法和矩阵不一样,矩阵乘法要使用dot() cjjJasonchen 发表于 2024-08-20 22:53
已经解决了,是因为numpy数组使用的乘法和矩阵不一样 ...
聪明的鱼油,原来是这样!用 `dot()` 进行矩阵乘法确实是正确的做法。正好你提到这个问题,下面我简单讲讲如何正确实现一个 3D 旋转矩阵,这样下次遇到类似的问题就不会犯难了。
首先,我们用 `numpy` 实现 3D 旋转矩阵。这里简单介绍一下绕 x、y、z 轴的旋转矩阵:
1. 绕 x 轴旋转的矩阵:
\[
R_x(\theta) = \begin{bmatrix}
1 & 0 & 0 \\
0 & \cos(\theta) & -\sin(\theta) \\
0 & \sin(\theta) & \cos(\theta)
\end{bmatrix}
\]
2. 绕 y 轴旋转的矩阵:
\[
R_y(\theta) = \begin{bmatrix}
\cos(\theta) & 0 & \sin(\theta) \\
0 & 1 & 0 \\
-\sin(\theta) & 0 & \cos(\theta)
\end{bmatrix}
\]
3. 绕 z 轴旋转的矩阵:
\[
R_z(\theta) = \begin{bmatrix}
\cos(\theta) & -\sin(\theta) & 0 \\
\sin(\theta) & \cos(\theta) & 0 \\
0 & 0 & 1
\end{bmatrix}
\]
假设你想同时绕这三个轴进行旋转,你可以通过组合这些旋转矩阵来实现。下面是一个简单的实现:
import numpy as np
import math
def get_rotation_matrix_x(angle):
"""返回绕x轴旋转的矩阵"""
return np.array([
,
,
])
def get_rotation_matrix_y(angle):
"""返回绕y轴旋转的矩阵"""
return np.array([
,
,
[-math.sin(angle), 0, math.cos(angle)]
])
def get_rotation_matrix_z(angle):
"""返回绕z轴旋转的矩阵"""
return np.array([
,
,
])
# 测试的角度
angle = math.radians(10)
# 初始位置
position = np.array()
rx = get_rotation_matrix_x(angle)
ry = get_rotation_matrix_y(angle)
rz = get_rotation_matrix_z(angle)
# 将旋转矩阵组合
rotation_matrix = rz.dot(ry).dot(rx)
# 对位置进行旋转变换
rotated_position = rotation_matrix.dot(position)
print("初始位置:", position)
print("旋转后的位置:", rotated_position)
记得在你的 `Sprites3D` 类里面利用这些方法就可以实现你想要的3D旋转效果了,也要记得用 `dot()` 来进行矩阵运算:
# 在你的 Sprites3D 类中的 update 方法中使用
def update(self):
angle = math.radians(10)# 旋转角度
rx = get_rotation_matrix_x(angle)
ry = get_rotation_matrix_y(angle)
rz = get_rotation_matrix_z(angle)
# 将旋转矩阵组合
rotation_matrix = rz.dot(ry).dot(rx)
# 对位置进行旋转变换
position = np.array(, self.position, 0])# 示例3D坐标
rotated_position = rotation_matrix.dot(position)
self.position = , rotated_position]
这样你的程序应该就能正确地进行3D旋转了!希望这对你有帮助,而且在写代码的过程中还不忘开开玩笑,比如“旋转红点变成了旋转丸子”。继续加油吧,祝你编程愉快!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]