mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 20:13:09 +02:00
first take at the Transform encapsulating a transform matrix
This commit is contained in:
parent
67535a386c
commit
4a73b0773b
2 changed files with 222 additions and 0 deletions
109
interface/src/gpu/Transform.cpp
Normal file
109
interface/src/gpu/Transform.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
//
|
||||
// Transform.cpp
|
||||
// interface/src/gpu
|
||||
//
|
||||
// Created by Sam Gateau on 11/4/2014.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Transform.h"
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
using namespace gpu;
|
||||
|
||||
Transform::Transform() :
|
||||
_translation(0),
|
||||
_rotation(1.f, 0, 0, 0),
|
||||
_scale(1.f),
|
||||
_flags(1) // invalid cache
|
||||
{
|
||||
}
|
||||
Transform::Transform(const Mat4& raw) {
|
||||
evalFromRawMatrix(raw);
|
||||
}
|
||||
|
||||
void Transform::updateCache() const {
|
||||
if (isCacheInvalid()) {
|
||||
glm::mat3x3 rot = glm::mat3_cast(_rotation);
|
||||
|
||||
if ((_scale.x != 1.f) || (_scale.y != 1.f) || (_scale.z != 1.f)) {
|
||||
rot[0] *= _scale.x;
|
||||
rot[1] *= _scale.y;
|
||||
rot[2] *= _scale.z;
|
||||
}
|
||||
|
||||
_matrix[0] = Vec4(rot[0], 0.f);
|
||||
_matrix[1] = Vec4(rot[1], 0.f);
|
||||
_matrix[2] = Vec4(rot[2], 0.f);
|
||||
|
||||
_matrix[3] = Vec4(_translation, 0.f);
|
||||
|
||||
validCache();
|
||||
}
|
||||
}
|
||||
|
||||
void Transform::localTranslate( Vec3 const & translation) {
|
||||
Vec3 tt = glm::rotate(_rotation, translation);
|
||||
_translation += tt * _scale;
|
||||
}
|
||||
|
||||
Transform::Mat4& Transform::evalRelativeTransform( Mat4& result, const Vec3& origin) {
|
||||
updateCache();
|
||||
result = _matrix;
|
||||
result[3] = Vec4(_translation - origin, 0.f);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Transform::evalFromRawMatrix(const Mat4& matrix) {
|
||||
if ((matrix[0][3] == 0) && (matrix[1][3] == 0) && (matrix[2][3] == 0) && (matrix[3][3] == 1.f)) {
|
||||
setTranslation(Vec3(matrix[3]));
|
||||
|
||||
Mat3 matRS = Mat3(matrix);
|
||||
|
||||
Vec3 scale(glm::length(matRS[0]), glm::length(matRS[1]), glm::length(matRS[2]));
|
||||
|
||||
matRS[0] *= 1/scale.x;
|
||||
matRS[1] *= 1/scale.y;
|
||||
matRS[2] *= 1/scale.z;
|
||||
|
||||
setRotation(glm::quat_cast(matRS));
|
||||
setScale(scale);
|
||||
}
|
||||
}
|
||||
|
||||
Transform& Transform::evalInverseTranspose(Transform& result) {
|
||||
result.setTranslation(-_translation);
|
||||
result.setRotation(-_rotation);
|
||||
|
||||
if (isScaling()) {
|
||||
result.setScale(Vec3(1.f/_scale.x, 1.f/_scale.y, 1.f/_scale.z));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Transform& Transform::mult( Transform& result, const Transform& left, const Transform& right) {
|
||||
right.updateCache();
|
||||
left.updateCache();
|
||||
|
||||
result.setTranslation(Vec3(left.getMatrix() * Vec4(right.getTranslation(), 1.f)));
|
||||
|
||||
Mat4 mat = left.getMatrix() * right.getMatrix();
|
||||
Mat3 matRS = Mat3(mat);
|
||||
|
||||
Vec3 scale(glm::length(matRS[0]), glm::length(matRS[1]), glm::length(matRS[2]));
|
||||
|
||||
matRS[0] *= 1/scale.x;
|
||||
matRS[1] *= 1/scale.y;
|
||||
matRS[2] *= 1/scale.z;
|
||||
|
||||
result.setRotation(glm::quat_cast(matRS));
|
||||
result.setScale(scale);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
113
interface/src/gpu/Transform.h
Normal file
113
interface/src/gpu/Transform.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
//
|
||||
// Transform.h
|
||||
// interface/src/gpu
|
||||
//
|
||||
// Created by Sam Gateau on 11/4/2014.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_gpu_Transform_h
|
||||
#define hifi_gpu_Transform_h
|
||||
|
||||
#include <assert.h>
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "gpu/Format.h"
|
||||
|
||||
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <bitset>
|
||||
|
||||
namespace gpu {
|
||||
|
||||
class Transform {
|
||||
public:
|
||||
typedef glm::mat4 Mat4;
|
||||
typedef glm::mat3 Mat3;
|
||||
typedef glm::vec4 Vec4;
|
||||
typedef glm::vec3 Vec3;
|
||||
typedef glm::vec2 Vec2;
|
||||
typedef glm::quat Quat;
|
||||
|
||||
Transform();
|
||||
Transform(const Mat4& raw);
|
||||
~Transform() {}
|
||||
|
||||
void setTranslation(const Vec3& translation) { invalidCache(); flagTranslation(); _translation = translation; }
|
||||
const Vec3& getTranslation() const { return _translation; }
|
||||
void parentTranslate(const Vec3& translation) { _translation += translation; }
|
||||
void localTranslate( Vec3 const & translation);
|
||||
|
||||
void setRotation(const Quat& rotation) { invalidCache(); flagRotation(); _rotation = rotation; }
|
||||
const Quat& getRotation() const { return _rotation; }
|
||||
|
||||
void setNoScale() { invalidCache(); flagNoScaling(); _scale = Vec3(1.f); }
|
||||
void setScale(float scale) { invalidCache(); flagUniformScaling(); _scale = Vec3(scale); }
|
||||
void setScale(const Vec3& scale) { invalidCache(); flagNonUniformScaling(); _scale = scale; }
|
||||
const Vec3& getScale() const { return _scale; }
|
||||
|
||||
const Mat4& getMatrix() const { updateCache(); return _matrix; }
|
||||
|
||||
Mat4& evalRelativeTransform(Mat4& result, const Vec3& origin);
|
||||
|
||||
Transform& evalInverseTranspose(Transform& result);
|
||||
void evalFromRawMatrix(const Mat4& matrix);
|
||||
|
||||
static Transform& mult( Transform& result, const Transform& left, const Transform& right);
|
||||
|
||||
bool isScaling() const { return _flags[FLAG_UNIFORM_SCALING] || _flags[FLAG_NON_UNIFORM_SCALING]; }
|
||||
protected:
|
||||
|
||||
enum Flag {
|
||||
FLAG_CACHE_INVALID = 0,
|
||||
|
||||
FLAG_TRANSLATION,
|
||||
FLAG_ROTATION,
|
||||
FLAG_UNIFORM_SCALING,
|
||||
FLAG_NON_UNIFORM_SCALING,
|
||||
FLAG_SHEARING,
|
||||
|
||||
FLAG_PROJECTION,
|
||||
|
||||
NUM_FLAGS,
|
||||
};
|
||||
|
||||
typedef std::bitset<NUM_FLAGS> Flags;
|
||||
|
||||
|
||||
// TRS
|
||||
Vec3 _translation;
|
||||
Quat _rotation;
|
||||
Vec3 _scale;
|
||||
|
||||
mutable Flags _flags;
|
||||
|
||||
// Cached transform
|
||||
mutable Mat4 _matrix;
|
||||
bool isCacheInvalid() const { return _flags[FLAG_CACHE_INVALID]; }
|
||||
void validCache() const { _flags.set(FLAG_CACHE_INVALID, false); }
|
||||
void invalidCache() const { _flags.set(FLAG_CACHE_INVALID, true); }
|
||||
|
||||
void flagTranslation() { _flags.set(FLAG_TRANSLATION, true); }
|
||||
void flagRotation() { _flags.set(FLAG_ROTATION, true); }
|
||||
|
||||
void flagNoScaling() { _flags.set(FLAG_UNIFORM_SCALING, false); _flags.set(FLAG_NON_UNIFORM_SCALING, false); }
|
||||
void flagUniformScaling() { _flags.set(FLAG_UNIFORM_SCALING, true); _flags.set(FLAG_NON_UNIFORM_SCALING, false); }
|
||||
void flagNonUniformScaling() { _flags.set(FLAG_UNIFORM_SCALING, false); _flags.set(FLAG_NON_UNIFORM_SCALING, true); }
|
||||
|
||||
void updateCache() const;
|
||||
};
|
||||
|
||||
typedef QSharedPointer< Transform > TransformPointer;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue