首页 > 解决方案 > 使用矩阵的坏点变换 (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++directxtransformsfmltransformation

解决方案


推荐阅读