Преобразование плохой точки с использованием матрицы (Direct3D) - PullRequest
0 голосов
/ 16 апреля 2020

Моя проблема немного растянута. Я пытаюсь напечатать спрайт, используя DirectX 11, и для обработки масштаба и поворотов я использую матрицу преобразования. Я извлек этот код из SFML , библиотеки с открытым исходным кодом, и для перевода отлично работает. Однако вращение и масштаб не работают должным образом, как я покажу далее.

  • Когда я вращаюсь по центру, все правильно.
  • Когда я перемещаю спрайт, а затем вращаться, спрайт вращается вокруг «неизвестной» точки.
  • То же самое происходит, когда я масштабирую спрайт, он масштабируется от «неизвестной» точки.
  • Если я вращаю спрайт, то ось перевода та же, но со повернутым спрайтом, поэтому я не могу правильно его переместить.

Я оставляю вам небольшое видео о том, что происходит. [ВИДЕО]

Я думаю, что проблема связана с тем, как я трансформирую спрайт, но я не могу в этом убедиться. Я оставляю вам здесь части кода, которые, я думаю, связаны с этой ошибкой, но вы также можете взглянуть на проект GitHub, чтобы глубже взглянуть. [GITHUB PROJECT]

с возможностью преобразования. 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);
}

Растровое изображение. 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).

Coordinate System Image

Поток кода

Когда положение, масштаб, вращение или происхождение актера изменяется, генерируется новое преобразование. Затем я преобразовываю локальные границы актера с помощью созданного преобразования, чтобы получить правильные положения вершины, и устанавливаю их в буфер вершин.

...