move the transform class files to the Shared library, still problem with negative scale composition

This commit is contained in:
Sam Gateau 2014-11-11 09:54:35 -08:00
parent 7ccb7495c7
commit ad51416c28
8 changed files with 147 additions and 92 deletions

View file

@ -2890,12 +2890,15 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
// transform by eye offset
gpu::Transform viewTransform;
// load the view frustum
loadViewFrustum(whichCamera, _displayViewFrustum);
// flip x if in mirror mode (also requires reversing winding order for backface culling)
if (whichCamera.getMode() == CAMERA_MODE_MIRROR) {
glScalef(-1.0f, 1.0f, 1.0f);
viewTransform.setScale(gpu::Transform::Vec3(-1.0f, 1.0f, 1.0f));
glFrontFace(GL_CW);
} else {
@ -2906,7 +2909,9 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
glm::quat eyeOffsetOrient = whichCamera.getEyeOffsetOrientation();
glm::vec3 eyeOffsetAxis = glm::axis(eyeOffsetOrient);
glRotatef(-glm::degrees(glm::angle(eyeOffsetOrient)), eyeOffsetAxis.x, eyeOffsetAxis.y, eyeOffsetAxis.z);
glTranslatef(-eyeOffsetPos.x, -eyeOffsetPos.y, -eyeOffsetPos.z);
viewTransform.preRotate(glm::quat(-glm::angle(eyeOffsetOrient), glm::vec3(eyeOffsetAxis.x, eyeOffsetAxis.y, eyeOffsetAxis.z)));
glTranslatef(-eyeOffsetPos.x, -eyeOffsetPos.y, -eyeOffsetPos.z);
viewTransform.preTranslate(glm::vec3(-eyeOffsetPos.x, -eyeOffsetPos.y, -eyeOffsetPos.z));
// transform view according to whichCamera
// could be myCamera (if in normal mode)
@ -2915,9 +2920,11 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
glm::quat rotation = whichCamera.getRotation();
glm::vec3 axis = glm::axis(rotation);
glRotatef(-glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
viewTransform.preRotate(glm::quat(-glm::angle(rotation), axis));
// store view matrix without translation, which we'll use for precision-sensitive objects
updateUntranslatedViewMatrix(-whichCamera.getPosition());
viewTransform.preTranslate(-whichCamera.getPosition());
glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z);

View file

@ -14,10 +14,11 @@
#include <assert.h>
#include "InterfaceConfig.h"
#include "Transform.h"
#include <vector>
#include "gpu/Stream.h"
#include "gpu/Transform.h"
#if defined(NSIGHT_FOUND)
#include "nvToolsExt.h"
@ -49,6 +50,10 @@ enum Primitive {
NUM_PRIMITIVES,
};
typedef ::Transform Transform;
typedef QSharedPointer<::gpu::Transform> TransformPointer;
typedef std::vector< TransformPointer > Transforms;
class Batch {
public:
typedef Stream::Slot Slot;

View file

@ -476,7 +476,9 @@ void GLBackend::updateTransform() {
_transform._lastMode = GL_MODELVIEW;
}
if (!_transform._view.isNull()) {
Transform::Mat4 mv = _transform._view->getMatrix() * _transform._model->getMatrix();
Transform mvx;
Transform::mult(mvx, (*_transform._view), (*_transform._model));
Transform::Mat4 mv = mvx.getMatrix();
glLoadMatrixf((const GLfloat*) &mv[0]);
} else {
glLoadMatrixf((const GLfloat*) &_transform._model->getMatrix());

View file

@ -1,74 +0,0 @@
//
// 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"
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);
}
Transform::Mat4& Transform::evalRelativeTransform( Mat4& result, const Vec3& origin) {
updateCache();
result = _matrix;
result[3] = Vec4(_translation - origin, 1.f);
return result;
}
void Transform::evalRotationScale(const Mat3& rotationScaleMatrix) {
Vec3 scale(glm::length(rotationScaleMatrix[0]), glm::length(rotationScaleMatrix[1]), glm::length(rotationScaleMatrix[2]));
if (scale.x < 0.00001f) scale.x = 0.00001f;
if (scale.y < 0.00001f) scale.y = 0.00001f;
if (scale.z < 0.00001f) scale.z = 0.00001f;
Mat3 matRotScale(
rotationScaleMatrix[0] / scale.x,
rotationScaleMatrix[1] / scale.y,
rotationScaleMatrix[2] / scale.z);
setRotation(glm::quat_cast(matRotScale));
float determinant = glm::determinant(matRotScale);
if (determinant < 0.f) {
scale.x = -scale.x;
}
setScale(scale);
}
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]));
evalRotationScale(Mat3(matrix));
}
}
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;
}

View file

@ -565,7 +565,10 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
_transforms[0]->evalFromRawMatrix(Application::getInstance()->getUntranslatedViewMatrix());
gpu::TransformPointer currentView(Application::getInstance()->getViewTransform());
currentView->getMatrix();
gpu::Transform::Mat4 glview = Application::getInstance()->getUntranslatedViewMatrix();
_transforms[0]->setTranslation(currentView->getTranslation());
_transforms[0]->setRotation(currentView->getRotation());
_transforms[0]->setScale(currentView->getScale());

View file

@ -16,6 +16,7 @@
#include <QObject>
#include <QUrl>
#include "Transform.h"
#include <AABox.h>
#include <AnimationCache.h>
#include <PhysicsEntity.h>
@ -38,7 +39,6 @@ typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
#include "gpu/Stream.h"
#include "gpu/Transform.h"
#include "gpu/Batch.h"
/// A generic 3D model displaying geometry loaded from a URL.

View file

@ -0,0 +1,118 @@
//
// Transform.cpp
// shared/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"
Transform::Transform() :
_translation(0),
_rotation(1.f, 0, 0, 0),
_scale(1.f),
_flags(1) // invalid cache
{
}
Transform::Transform(const Mat4& raw) {
evalFromRawMatrix(raw);
}
Transform::Mat4& Transform::evalRelativeTransform( Mat4& result, const Vec3& origin) {
updateCache();
result = _matrix;
result[3] = Vec4(_translation - origin, 1.f);
return result;
}
void Transform::evalRotationScale(const Mat3& rotationScaleMatrix) {
const float ACCURACY_THREASHOLD = 0.00001f;
// Extract the rotation component - this is done using polar decompostion, where
// we successively average the matrix with its inverse transpose until there is
// no/a very small difference between successive averages
float norm;
int count = 0;
Mat3 rotationMat = rotationScaleMatrix;
do {
Mat3 nextRotation;
Mat3 currInvTranspose =
glm::inverse(glm::transpose(rotationMat));
// Go through every component in the matrices and find the next matrix
for (int i = 0; i < 3; i++) {
for (int j = 0; j <3; j++) {
nextRotation[j][i] = 0.5f *
(rotationMat[j][i] + currInvTranspose[j][i]);
}
}
norm = 0.0;
for (int i = 0; i < 3; i++) {
float n = static_cast<float>(
fabs(rotationMat[0][i] - nextRotation[0][i]) +
fabs(rotationMat[1][i] - nextRotation[1][i]) +
fabs(rotationMat[2][i] - nextRotation[2][i]));
norm = (norm > n ? norm : n);
}
rotationMat = nextRotation;
} while (count < 100 && norm > ACCURACY_THREASHOLD);
// extract scale of the matrix as the length of each axis
Mat3 scaleMat = glm::inverse(rotationMat) * rotationScaleMatrix;
Vec3 scale2(glm::length(rotationScaleMatrix[0]), glm::length(rotationScaleMatrix[1]), glm::length(rotationScaleMatrix[2]));
Vec3 scale(scaleMat[0][0], scaleMat[1][1], scaleMat[2][2]);
if (scale.x < ACCURACY_THREASHOLD) scale.x = ACCURACY_THREASHOLD;
if (scale.y < ACCURACY_THREASHOLD) scale.y = ACCURACY_THREASHOLD;
if (scale.z < ACCURACY_THREASHOLD) scale.z = ACCURACY_THREASHOLD;
// Let's work on a local matrix containing rotation only
Mat3 matRot(
rotationScaleMatrix[0] / scale.x,
rotationScaleMatrix[1] / scale.y,
rotationScaleMatrix[2] / scale.z);
// Beware!!! needs to detect for the case there is a negative scale
// Based on the determinant sign we just can flip the scale sign of one component: we choose X axis
float determinant = glm::determinant(matRot);
if (determinant < 0.f) {
scale.x = -scale.x;
// matRot[0] *= -1.f;
}
// Beware: even though the matRot is supposed to be normalized at that point,
// glm::quat_cast doesn't always return a normalized quaternion...
setRotation(glm::normalize(glm::quat_cast(matRot)));
// and assign the scale
setScale(scale);
}
void Transform::evalFromRawMatrix(const Mat4& matrix) {
// for now works only in the case of TRS transformation
if ((matrix[0][3] == 0) && (matrix[1][3] == 0) && (matrix[2][3] == 0) && (matrix[3][3] == 1.f)) {
setTranslation(Vec3(matrix[3]));
evalRotationScale(Mat3(matrix));
}
}
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;
}

View file

@ -1,6 +1,6 @@
//
// Transform.h
// interface/src/gpu
// shared/src/gpu
//
// Created by Sam Gateau on 11/4/2014.
// Copyright 2014 High Fidelity, Inc.
@ -12,12 +12,6 @@
#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>
@ -26,8 +20,6 @@
#include <bitset>
namespace gpu {
class Transform {
public:
typedef glm::mat4 Mat4;
@ -113,6 +105,13 @@ public:
if ( right.isTranslating()) result.postTranslate(right.getTranslation());
if ( right.isRotating()) result.postRotate(right.getRotation());
if (right.isScaling()) result.postScale(right.getScale());
Transform::Mat4 mv = left.getMatrix() * right.getMatrix();
Transform::Mat4 mv2 = result.getMatrix();
result.evalFromRawMatrix(mv);
Transform::Mat4 mv3 = result.getMatrix();
return result;
}
@ -181,10 +180,5 @@ protected:
}
};
typedef QSharedPointer< Transform > TransformPointer;
typedef std::vector< TransformPointer > Transforms;
};
#endif