c++ - 使用矩阵的坏点变换 (Direct3D)
问题描述
我的问题有点广泛。我正在尝试使用 DirectX 11 打印精灵并使用转换矩阵来处理缩放和旋转。我从开源库SFML中提取了这段代码,并且翻译工作正常。然而,旋转和缩放并没有像我接下来展示的那样工作。
- 当我旋转穿过中心时,一切都是正确的。
- 当我移动精灵然后旋转时,精灵围绕“未知”点旋转。
- 当我缩放精灵时也会发生同样的情况,它会从“未知”点缩放自己。
- 如果我旋转精灵,那么平移轴是相同的,但是精灵旋转了,所以我不能正确移动它。
我给你留了一段关于正在发生的事情的小视频。[视频]
我认为这个问题与我如何转换精灵有关,但我不能保证。我将我认为与此错误有关的代码部分留在这里,但您也可以查看 GitHub 项目以深入了解。[GITHUB项目]
可变形的.cpp
const Transform& Transformable::GetTransform() const
{
if (_transformNeedUpdate)
{
float angle = -_rotation * 3.141592654f / 180.f;
float cosine = static_cast<float>(std::cos(angle));
float sine = static_cast<float>(std::sin(angle));
float sxc = _scale.x * cosine;
float syc = _scale.y * cosine;
float sxs = _scale.x * sine;
float sys = _scale.y * sine;
float tx = -_origin.x * sxc - _origin.y * sys + _position.x;
float ty = _origin.x * sxs - _origin.y * syc + _position.y;
_transform = Transform(sxc, sys, tx,
-sxs, syc, ty,
0.f, 0.f, 1.f);
_transformNeedUpdate = false;
}
return _transform;
}
变换.cpp
Transform::Transform(
float a00, float a01, float a02,
float a10, float a11, float a12,
float a20, float a21, float a22
)
{
_matrix[0] = a00; _matrix[4] = a01; _matrix[8] = 0.f; _matrix[12] = a02;
_matrix[1] = a10; _matrix[5] = a11; _matrix[9] = 0.f; _matrix[13] = a12;
_matrix[2] = 0.f; _matrix[6] = 0.f; _matrix[10] = 1.f; _matrix[14] = 0.f;
_matrix[3] = a20; _matrix[7] = a21; _matrix[11] = 0.f; _matrix[15] = a22;
}
D3DXVECTOR2 Transform::TransformPoint(float x, float y) const
{
return D3DXVECTOR2(_matrix[0] * x + _matrix[4] * y + _matrix[12],
_matrix[1] * x + _matrix[5] * y + _matrix[13]);
}
D3DXVECTOR2 operator *(const Transform& left, const D3DXVECTOR2& right)
{
return left.TransformPoint(right);
}
Bitmap.cpp(我设置要绘制的顶点)
HRESULT Bitmap::UpdateBuffers(ID3D11DeviceContext* deviceContext)
{
if (_transform == _previousTransform && _bounds == _previousBounds)
{
return S_OK;
}
VertexType* vertices;
D3D11_MAPPED_SUBRESOURCE mappedResource;
VertexType* verticesPtr;
HRESULT result;
_previousTransform = _transform;
_previousBounds = _bounds;
vertices = new VertexType[_vertexCount];
if (!vertices)
{
return CO_E_ERRORINAPP;
}
float left = _bounds.left();
float right = left + _bounds.width();
float top = _bounds.top();
float bottom = top + _bounds.height();
D3DXVECTOR2 topLeft = { left, top };
D3DXVECTOR2 bottomRight = { right, bottom };
D3DXVECTOR2 topRight = { right, top };
D3DXVECTOR2 bottomLeft = { left, bottom };
topLeft = _transform * topLeft;
bottomRight = _transform * bottomRight;
topRight = _transform * topRight;
bottomLeft = _transform * bottomLeft;
vertices[0].position = D3DXVECTOR3(topLeft.x, topLeft.y, 0.0f);
vertices[0].texture = D3DXVECTOR2(0.0f, 0.0f);
vertices[1].position = D3DXVECTOR3(bottomRight.x, bottomRight.y, 0.0f);
vertices[1].texture = D3DXVECTOR2(1.0f, 1.0f);
vertices[2].position = D3DXVECTOR3(bottomLeft.x, bottomLeft.y, 0.0f);
vertices[2].texture = D3DXVECTOR2(0.0f, 1.0f);
vertices[3].position = D3DXVECTOR3(topLeft.x, topLeft.y, 0.0f);
vertices[3].texture = D3DXVECTOR2(0.0f, 0.0f);
vertices[4].position = D3DXVECTOR3(topRight.x, topRight.y, 0.0f);
vertices[4].texture = D3DXVECTOR2(1.0f, 0.0f);
vertices[5].position = D3DXVECTOR3(bottomRight.x, bottomRight.y, 0.0f);
vertices[5].texture = D3DXVECTOR2(1.0f, 1.0f);
result = deviceContext->Map(_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
return CO_E_ERRORINAPP;
}
verticesPtr = (VertexType*)mappedResource.pData;
memcpy(verticesPtr, (void*)vertices, (sizeof(VertexType) * _vertexCount));
deviceContext->Unmap(_vertexBuffer, 0);
delete[] vertices;
vertices = 0;
return S_OK;
}
坐标系如下图所示;屏幕的中心是 (0,0) 位置。
代码流
当actor的位置、比例、旋转或原点发生变化时,会生成一个新的Transform。然后,我用生成的变换变换actor的局部边界以获得顶点的正确位置,并将它们设置到顶点缓冲区中。
解决方案
推荐阅读
- c++ - Mingw32 无法静态链接到 libgcc_s_dw2-1、libstdc++-6、libwinpthread-1 (Qt 5.7.1)
- bash - 如何替换文本文件中周期性出现的数组
- python - 创建包含给定值和日期范围的所有可能性的字典的最佳方法是什么?
- console - 自几周前 Google 更新以来,是否有人在他们的操作中也遇到过故障?
- go - 使用切片的动态结构(包含外键)和 go-gorm 将数据插入数据库
- xslt - 如何使用 XSLT 将所有标题文本转换为标题大小写?
- javascript - 如何在 React 的 return 语句中使用获取结果?
- tensorflow - 我想在我的自定义层中使用 keras 层,但我无法将层的输出作为张量而不是对象返回
- javascript - 使用 bootstrap-vue 中的传单删除标记单击时弹出的默认对话框
- asp.net-mvc - 有没有办法在 Visual Studio 2019 for Mac 的上下文中获取 ViewBag、Layout 和 Model?