矩阵变换问题 - Z 轴旋转倾斜
对于我正在制作的一个简单的 2d 游戏,我尝试使用矩阵绕 z 轴旋转精灵。我显然做错了什么,因为当我尝试旋转精灵时,它看起来像是围绕屏幕原点(底部,左侧)而不是精灵原点旋转。我很困惑,因为我的四边形已经在原点了,所以我认为我不需要翻译 ->旋转并平移回来。这是一个代码片段和一个小视频或错误的转换
void MatrixMultiply(
MATRIX &mOut,
const MATRIX &mA,
const MATRIX &mB);
/*!***************************************************************************
@Function TransTransformArray
@Output pTransformedVertex Destination for transformed vectors
@Input pV Input vector array
@Input nNumberOfVertices Number of vectors to transform
@Input pMatrix Matrix to transform the vectors of input vector (e.g. use 1 for position, 0 for normal)
@Description Transform all vertices in pVertex by pMatrix and store them in
pTransformedVertex
- pTransformedVertex is the pointer that will receive transformed vertices.
- pVertex is the pointer to untransformed object vertices.
- nNumberOfVertices is the number of vertices of the object.
- pMatrix is the matrix used to transform the object.
*****************************************************************************/
void TransTransformArray(
VECTOR3 * const pTransformedVertex,
const VECTOR3 * const pV,
const int nNumberOfVertices,
const MATRIX * const pMatrix);
RenderQuad CreateRenderQuad(
const Texture2D & texture,
float x,
float y,
float scaleX,
float scaleY,
float rotateRadians,
int zIndex,
const Color & color,
const Quad2 & textureCoord,
const char * name
) {
MATRIX mT;
MATRIX mS;
MATRIX concat;
MATRIX mR;
MatrixTranslation(mT, x, y, 0.0f);
MatrixRotationZ(mR, rotateRadians);
MatrixScaling(mS, scaleX, scaleY, 1.0f);
VECTOR3 quad[] = {
{-0.5f, 0.5f, 0.f}, //tl
{0.5f, 0.5f, 0.f}, //tr
{-0.5, -0.5f, 0.0f}, //bl
{0.5f, -0.5f, 0.0f}, //br
};
MatrixMultiply(concat, mR, mT);
MatrixMultiply(concat, concat, mS);
// apply to all the points in the quad
TransTransformArray(quad, quad, 4, &concat);
==更新:
这里是结构和渲染代码:
我正在使用 oolongengine code.google.com/p/oolongengine/source/browse/trunk/Oolong%20Engine2/Math/Matrix.cpp 中的矩阵类,
我转换所有四边形,然后使用OpenGL。这是我的数据结构和渲染代码:
typedef struct _RenderData {
VECTOR3 vertex;
RenderColor3D color;
RenderTextureCoord textureCoord;
float zIndex;
GLuint textureId;
} RenderData;
typedef struct _RenderQuad {
//! top left
RenderData tl;
//! top right
RenderData tr;
//! bottom left
RenderData bl;
//! bottom right
RenderData br;
float zIndex;
Texture2D * texture; // render quad draws a source rect from here
ESpriteBlendMode blendMode;
} RenderQuad ;
/// Draw
class QuadBatch {
GLushort * m_indices;
const Texture2D * m_texture;
GLuint m_vbos[2];
RenderData * m_vertices;
};
QuadBatch::Draw () {
int offset = (int)&m_vertices[startIndex];
// vertex
int diff = offsetof( RenderData, vertex);
glVertexPointer(3, GL_FLOAT, kRenderDataSize, (void*) (offset + diff) );
// color
diff = offsetof( RenderData, color);
glColorPointer(4, GL_FLOAT, kRenderDataSize, (void*)(offset + diff));
// tex coords
diff = offsetof( RenderData, textureCoord);
glTexCoordPointer(2, GL_FLOAT, kRenderDataSize, (void*)(offset + diff));
// each quad has 6 indices
glDrawElements(GL_TRIANGLES, vertexCount * elementMultiplier, GL_UNSIGNED_SHORT, m_indices);
For a simple 2d game I'm making I'm trying to rotate sprites around the z axis using matrices. I'm clearly doing something wrong as when I attempt to rotate my sprite it looks like it's being rotated around the screen origin (bottom, left) and not the sprite origin. I'm confused as my quad is at the origin already so I didn't think I need to translate -> rotate and translate back. Here's a code snippet and a small video or the erroneous transformation
void MatrixMultiply(
MATRIX &mOut,
const MATRIX &mA,
const MATRIX &mB);
/*!***************************************************************************
@Function TransTransformArray
@Output pTransformedVertex Destination for transformed vectors
@Input pV Input vector array
@Input nNumberOfVertices Number of vectors to transform
@Input pMatrix Matrix to transform the vectors of input vector (e.g. use 1 for position, 0 for normal)
@Description Transform all vertices in pVertex by pMatrix and store them in
pTransformedVertex
- pTransformedVertex is the pointer that will receive transformed vertices.
- pVertex is the pointer to untransformed object vertices.
- nNumberOfVertices is the number of vertices of the object.
- pMatrix is the matrix used to transform the object.
*****************************************************************************/
void TransTransformArray(
VECTOR3 * const pTransformedVertex,
const VECTOR3 * const pV,
const int nNumberOfVertices,
const MATRIX * const pMatrix);
RenderQuad CreateRenderQuad(
const Texture2D & texture,
float x,
float y,
float scaleX,
float scaleY,
float rotateRadians,
int zIndex,
const Color & color,
const Quad2 & textureCoord,
const char * name
) {
MATRIX mT;
MATRIX mS;
MATRIX concat;
MATRIX mR;
MatrixTranslation(mT, x, y, 0.0f);
MatrixRotationZ(mR, rotateRadians);
MatrixScaling(mS, scaleX, scaleY, 1.0f);
VECTOR3 quad[] = {
{-0.5f, 0.5f, 0.f}, //tl
{0.5f, 0.5f, 0.f}, //tr
{-0.5, -0.5f, 0.0f}, //bl
{0.5f, -0.5f, 0.0f}, //br
};
MatrixMultiply(concat, mR, mT);
MatrixMultiply(concat, concat, mS);
// apply to all the points in the quad
TransTransformArray(quad, quad, 4, &concat);
== Update:
here's the structs and render code:
I'm using the matrix class from the oolongengine code.google.com/p/oolongengine/source/browse/trunk/Oolong%20Engine2/Math/Matrix.cpp
I transform all the quads then later render them using OpenGL. Here are my data structs and render code:
typedef struct _RenderData {
VECTOR3 vertex;
RenderColor3D color;
RenderTextureCoord textureCoord;
float zIndex;
GLuint textureId;
} RenderData;
typedef struct _RenderQuad {
//! top left
RenderData tl;
//! top right
RenderData tr;
//! bottom left
RenderData bl;
//! bottom right
RenderData br;
float zIndex;
Texture2D * texture; // render quad draws a source rect from here
ESpriteBlendMode blendMode;
} RenderQuad ;
/// Draw
class QuadBatch {
GLushort * m_indices;
const Texture2D * m_texture;
GLuint m_vbos[2];
RenderData * m_vertices;
};
QuadBatch::Draw () {
int offset = (int)&m_vertices[startIndex];
// vertex
int diff = offsetof( RenderData, vertex);
glVertexPointer(3, GL_FLOAT, kRenderDataSize, (void*) (offset + diff) );
// color
diff = offsetof( RenderData, color);
glColorPointer(4, GL_FLOAT, kRenderDataSize, (void*)(offset + diff));
// tex coords
diff = offsetof( RenderData, textureCoord);
glTexCoordPointer(2, GL_FLOAT, kRenderDataSize, (void*)(offset + diff));
// each quad has 6 indices
glDrawElements(GL_TRIANGLES, vertexCount * elementMultiplier, GL_UNSIGNED_SHORT, m_indices);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据定义,“旋转”是围绕原点 (0,0,0) 的。如果您想要不同的旋转轴,则必须应用平移组件。假设您要围绕 a 轴应用旋转 R。应用于任意向量 x 的变换为:
(这可能需要一些凝视才能消化)。因此,应用旋转后(正如您所观察到的,旋转围绕原点旋转),您必须添加常数向量 (a - Ra)。
[编辑:]这个答案与语言和平台无关——无论你看什么,数学都是一样的。特定的库包含不同的结构和 API 来应用转换。例如,DirectX 和 OpenGL 都维护 4x4 矩阵变换,以将旋转和平移统一为单个矩阵乘法(通过称为齐次坐标的装置)。
'Rotation', by definition, is around the origin (0,0,0). If you want a different axis of rotation, you have to apply a Translation component. Say you want to apply a rotation R around an axis a. The transformation to apply to an arbitrary vector x is:
(This might take some staring to digest). So, after applying your rotation - which, as you observed, rotates around the origin - you have to add the constant vector (a - Ra).
[Edit:] This answer is language and platform agnostic - the math is the same wherever you look. Specific libraries contain different structures and API to apply transformations. Both DirectX and OpenGL, for example, maintain 4x4 matrix transforms, to unify rotations and translations into a single matrix multiplication (via an apparatus called homogeneous coordinates).