mirror of
				https://github.com/thunderbrewhq/thunderbrew
				synced 2025-11-04 10:16:02 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			242 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//-------------------------------------------------------------------------------------
 | 
						|
// DirectXMatrixStack.h -- DirectXMath C++ Matrix Stack
 | 
						|
//
 | 
						|
// Copyright (c) Microsoft Corporation.
 | 
						|
// Licensed under the MIT License.
 | 
						|
//
 | 
						|
// http://go.microsoft.com/fwlink/?LinkID=615560
 | 
						|
//-------------------------------------------------------------------------------------
 | 
						|
 | 
						|
#pragma once
 | 
						|
 | 
						|
#include <cassert>
 | 
						|
#include <cstddef>
 | 
						|
#include <cstdint>
 | 
						|
#include <cstring>
 | 
						|
#include <memory>
 | 
						|
#include <new>
 | 
						|
 | 
						|
#ifdef _WIN32
 | 
						|
#include <malloc.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <DirectXMath.h>
 | 
						|
 | 
						|
 | 
						|
namespace DirectX
 | 
						|
{
 | 
						|
    class MatrixStack
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        MatrixStack(size_t startSize = 16) noexcept(false) :
 | 
						|
            m_stackSize(0),
 | 
						|
            m_current(0),
 | 
						|
            m_stack(nullptr)
 | 
						|
        {
 | 
						|
            assert(startSize > 0);
 | 
						|
            Allocate(startSize);
 | 
						|
            LoadIdentity();
 | 
						|
        }
 | 
						|
 | 
						|
        MatrixStack(MatrixStack&&) = default;
 | 
						|
        MatrixStack& operator= (MatrixStack&&) = default;
 | 
						|
 | 
						|
        MatrixStack(MatrixStack const&) = delete;
 | 
						|
        MatrixStack& operator= (MatrixStack const&) = delete;
 | 
						|
 | 
						|
        const XMMATRIX XM_CALLCONV Top() const noexcept { return m_stack[m_current]; }
 | 
						|
        const XMMATRIX* GetTop() const noexcept { return &m_stack[m_current]; }
 | 
						|
 | 
						|
        size_t Size() const noexcept { return (m_current + 1); }
 | 
						|
 | 
						|
        void Pop()
 | 
						|
        {
 | 
						|
            if (m_current > 0)
 | 
						|
            {
 | 
						|
                --m_current;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void Push()
 | 
						|
        {
 | 
						|
            ++m_current;
 | 
						|
 | 
						|
            if (m_current >= m_stackSize)
 | 
						|
            {
 | 
						|
                Allocate(m_stackSize * 2);
 | 
						|
            }
 | 
						|
 | 
						|
            // Replicate the original top of the matrix stack.
 | 
						|
            m_stack[m_current] = m_stack[m_current - 1];
 | 
						|
        }
 | 
						|
 | 
						|
        // Loads identity into the top of the matrix stack.
 | 
						|
        void LoadIdentity() noexcept
 | 
						|
        {
 | 
						|
            m_stack[m_current] = XMMatrixIdentity();
 | 
						|
        }
 | 
						|
 | 
						|
        // Load a matrix into the top of the matrix stack.
 | 
						|
        void XM_CALLCONV LoadMatrix(FXMMATRIX matrix) noexcept
 | 
						|
        {
 | 
						|
            m_stack[m_current] = matrix;
 | 
						|
        }
 | 
						|
 | 
						|
        // Multiply a matrix by the top of the stack, store result in top.
 | 
						|
        void XM_CALLCONV MultiplyMatrix(FXMMATRIX matrix) noexcept
 | 
						|
        {
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(m_stack[m_current], matrix);
 | 
						|
        }
 | 
						|
 | 
						|
        // Pre-multiplies a matrix by the top of the stack, store result in top.
 | 
						|
        void XM_CALLCONV MultiplyMatrixLocal(FXMMATRIX matrix) noexcept
 | 
						|
        {
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(matrix, m_stack[m_current]);
 | 
						|
        }
 | 
						|
 | 
						|
        // Add a rotation about X to stack top.
 | 
						|
        void XM_CALLCONV RotateX(float angle) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationX(angle);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(m_stack[m_current], mat);
 | 
						|
        }
 | 
						|
 | 
						|
        void XM_CALLCONV RotateXLocal(float angle) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationX(angle);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(mat, m_stack[m_current]);
 | 
						|
        }
 | 
						|
 | 
						|
        // Add a rotation about Y to stack top.
 | 
						|
        void XM_CALLCONV RotateY(float angle) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationY(angle);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(m_stack[m_current], mat);
 | 
						|
        }
 | 
						|
 | 
						|
        void XM_CALLCONV RotateYLocal(float angle) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationY(angle);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(mat, m_stack[m_current]);
 | 
						|
        }
 | 
						|
 | 
						|
        // Add a rotation about Z to stack top.
 | 
						|
        void XM_CALLCONV RotateZ(float angle) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationZ(angle);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(m_stack[m_current], mat);
 | 
						|
        }
 | 
						|
 | 
						|
        void XM_CALLCONV RotateZLocal(float angle) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationZ(angle);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(mat, m_stack[m_current]);
 | 
						|
        }
 | 
						|
 | 
						|
        // Add a rotation around an axis to stack top.
 | 
						|
        void XM_CALLCONV RotateAxis(FXMVECTOR axis, float angle) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationAxis(axis, angle);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(m_stack[m_current], mat);
 | 
						|
        }
 | 
						|
 | 
						|
        void XM_CALLCONV RotateAxisLocal(FXMVECTOR axis, float angle) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationAxis(axis, angle);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(mat, m_stack[m_current]);
 | 
						|
        }
 | 
						|
 | 
						|
        // Add a rotation by roll/pitch/yaw to the stack top.
 | 
						|
        void RotateRollPitchYaw(float pitch, float yaw, float roll) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationRollPitchYaw(pitch, yaw, roll);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(m_stack[m_current], mat);
 | 
						|
        }
 | 
						|
 | 
						|
        void RotateRollPitchYawLocal(float pitch, float yaw, float roll) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationRollPitchYaw(pitch, yaw, roll);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(mat, m_stack[m_current]);
 | 
						|
        }
 | 
						|
 | 
						|
        // Add a rotation by a quaternion stack top.
 | 
						|
        void XM_CALLCONV RotateByQuaternion(FXMVECTOR quat) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationQuaternion(quat);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(m_stack[m_current], mat);
 | 
						|
        }
 | 
						|
 | 
						|
        void XM_CALLCONV RotateByQuaternionLocal(FXMVECTOR quat) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixRotationQuaternion(quat);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(mat, m_stack[m_current]);
 | 
						|
        }
 | 
						|
 | 
						|
        // Add a scale to the stack top.
 | 
						|
        void Scale(float x, float y, float z) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixScaling(x, y, z);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(m_stack[m_current], mat);
 | 
						|
        }
 | 
						|
 | 
						|
        void ScaleLocal(float x, float y, float z) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixScaling(x, y, z);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(mat, m_stack[m_current]);
 | 
						|
        }
 | 
						|
 | 
						|
        // Add a translation to the stack top.
 | 
						|
        void Translate(float x, float y, float z) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixTranslation(x, y, z);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(m_stack[m_current], mat);
 | 
						|
        }
 | 
						|
 | 
						|
        void TranslateLocal(float x, float y, float z) noexcept
 | 
						|
        {
 | 
						|
            XMMATRIX mat = XMMatrixTranslation(x, y, z);
 | 
						|
            m_stack[m_current] = XMMatrixMultiply(mat, m_stack[m_current]);
 | 
						|
        }
 | 
						|
 | 
						|
    private:
 | 
						|
 | 
						|
        struct matrix_deleter
 | 
						|
        {
 | 
						|
            void operator()(void* p) noexcept
 | 
						|
            {
 | 
						|
#ifdef _WIN32
 | 
						|
                _aligned_free(p);
 | 
						|
#else
 | 
						|
                free(p);
 | 
						|
#endif
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        void Allocate(size_t newSize)
 | 
						|
        {
 | 
						|
#ifdef _WIN32
 | 
						|
            void* ptr = _aligned_malloc(newSize * sizeof(XMMATRIX), 16);
 | 
						|
#else
 | 
						|
            // This C++17 Standard Library function is currently NOT
 | 
						|
            // implemented for the Microsoft Standard C++ Library.
 | 
						|
            void* ptr = aligned_alloc(16, newSize * sizeof(XMMATRIX));
 | 
						|
#endif
 | 
						|
            if (!ptr)
 | 
						|
                throw std::bad_alloc();
 | 
						|
 | 
						|
            if (m_stack)
 | 
						|
            {
 | 
						|
                assert(newSize >= m_stackSize);
 | 
						|
                memcpy(ptr, m_stack.get(), sizeof(XMMATRIX) * m_stackSize);
 | 
						|
            }
 | 
						|
 | 
						|
            m_stack.reset(reinterpret_cast<XMMATRIX*>(ptr));
 | 
						|
            m_stackSize = newSize;
 | 
						|
        }
 | 
						|
 | 
						|
        size_t										m_stackSize;
 | 
						|
        size_t										m_current;
 | 
						|
        std::unique_ptr<XMMATRIX[], matrix_deleter>	m_stack;
 | 
						|
    };
 | 
						|
} // namespace DirectX
 |