diff --git a/libraries/render-utils/src/MatrixStack.cpp b/libraries/render-utils/src/MatrixStack.cpp new file mode 100644 index 0000000000..16177f3076 --- /dev/null +++ b/libraries/render-utils/src/MatrixStack.cpp @@ -0,0 +1,7 @@ +#include "MatrixStack.h" + +QMatrix4x4 fromGlm(const glm::mat4 & m) { + return QMatrix4x4(&m[0][0]).transposed(); + return QMatrix4x4(&m[0][0]); +} + diff --git a/libraries/render-utils/src/MatrixStack.h b/libraries/render-utils/src/MatrixStack.h new file mode 100644 index 0000000000..49ce119810 --- /dev/null +++ b/libraries/render-utils/src/MatrixStack.h @@ -0,0 +1,205 @@ +/************************************************************************************ + + Authors : Bradley Austin Davis + Copyright : Copyright Brad Davis. All Rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ************************************************************************************/ + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + + +class MatrixStack : public std::stack { + +public: + + MatrixStack() { + push(glm::mat4()); + } + + explicit MatrixStack(const MatrixStack & other) { + *((std::stack*)this) = *((std::stack*)&other); + } + + operator const glm::mat4 & () const { + return top(); + } + + MatrixStack & pop() { + std::stack::pop(); + assert(!empty()); + return *this; + } + + MatrixStack & push() { + emplace(top()); + return *this; + } + + MatrixStack & identity() { + top() = glm::mat4(); + return *this; + } + + MatrixStack & push(const glm::mat4 & mat) { + std::stack::push(mat); + return *this; + } + + MatrixStack & rotate(const glm::mat3 & rotation) { + return postMultiply(glm::mat4(rotation)); + } + + MatrixStack & rotate(const glm::quat & rotation) { + return postMultiply(glm::mat4_cast(rotation)); + } + + MatrixStack & rotate(float theta, const glm::vec3 & axis) { + return postMultiply(glm::rotate(glm::mat4(), theta, axis)); + } + + MatrixStack & translate(float translation) { + return translate(glm::vec3(translation, 0, 0)); + } + + MatrixStack & translate(const glm::vec2 & translation) { + return translate(glm::vec3(translation, 0)); + } + + MatrixStack & translate(const glm::vec3 & translation) { + return postMultiply(glm::translate(glm::mat4(), translation)); + } + + MatrixStack & preTranslate(const glm::vec3 & translation) { + return preMultiply(glm::translate(glm::mat4(), translation)); + } + + + MatrixStack & scale(float factor) { + return scale(glm::vec3(factor)); + } + + MatrixStack & scale(const glm::vec3 & scale) { + return postMultiply(glm::scale(glm::mat4(), scale)); + } + + MatrixStack & transform(const glm::mat4 & xfm) { + return postMultiply(xfm); + } + + MatrixStack & preMultiply(const glm::mat4 & xfm) { + top() = xfm * top(); + return *this; + } + + MatrixStack & postMultiply(const glm::mat4 & xfm) { + top() *= xfm; + return *this; + } + + // Remove the rotation component of a matrix. useful for billboarding + MatrixStack & unrotate() { + glm::quat inverse = glm::inverse(glm::quat_cast(top())); + top() = top() * glm::mat4_cast(inverse); + return *this; + } + + // Remove the translation component of a matrix. useful for skyboxing + MatrixStack & untranslate() { + top()[3] = glm::vec4(0, 0, 0, 1); + return *this; + } + + template + void withPush(Function f) { + size_t startingDepth = size(); + push(); + f(); + pop(); + assert(startingDepth = size()); + } + + template + void withIdentity(Function f) { + withPush([&] { + identity(); + f(); + }); + } + + static MatrixStack & projection() { + static MatrixStack projection; + return projection; + } + + static MatrixStack & modelview() { + static MatrixStack modelview; + return modelview; + } + + template + static void withPushAll(Function f) { + withPush(projection(), modelview(), f); + } + + template + static void withIdentityAll(Function f) { + withPush(projection(), modelview(), [=] { + projection().identity(); + modelview().identity(); + f(); + }); + } + + template + static void withPush(MatrixStack & stack, Function f) { + stack.withPush(f); + } + + template + static void withPush(MatrixStack & stack1, MatrixStack & stack2, Function f) { + stack1.withPush([&]{ + stack2.withPush(f); + }); + } + + template + static void withGlMatrices(Function f) { + // Push the current stack, and then copy the values out of OpenGL + withPushAll([&] { + // Fetch the current matrices out of GL stack + // FIXME, eliminate the usage of deprecated GL + MatrixStack & mv = MatrixStack::modelview(); + MatrixStack & pr = MatrixStack::projection(); + glm::mat4 & mvm = mv.top(); + glGetFloatv(GL_MODELVIEW_MATRIX, &(mvm[0][0])); + + glm::mat4 & prm = pr.top(); + glGetFloatv(GL_PROJECTION_MATRIX, &(prm[0][0])); + f(); + }); + } + +}; + +QMatrix4x4 fromGlm(const glm::mat4 & m); +