mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-30 20:43:21 +02:00
Work around precision issues with multiplying matrices with high translation
magnitudes (by using relative translation).
This commit is contained in:
parent
4cc650835d
commit
b2ed29dbff
5 changed files with 37 additions and 19 deletions
interface/src
|
@ -2866,6 +2866,12 @@ void Application::setupWorldLight(Camera& whichCamera) {
|
|||
glMateriali(GL_FRONT, GL_SHININESS, 96);
|
||||
}
|
||||
|
||||
void Application::loadTranslatedViewMatrix(const glm::vec3& translation) {
|
||||
glLoadMatrixf((const GLfloat*)&_untranslatedViewMatrix);
|
||||
glTranslatef(translation.x + _viewMatrixTranslation.x, translation.y + _viewMatrixTranslation.y,
|
||||
translation.z + _viewMatrixTranslation.z);
|
||||
}
|
||||
|
||||
void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near,
|
||||
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const {
|
||||
|
||||
|
@ -2899,7 +2905,11 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(-glm::angle(rotation), axis.x, axis.y, axis.z);
|
||||
|
||||
glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z);
|
||||
// store view matrix without translation, which we'll use for precision-sensitive objects
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix);
|
||||
_viewMatrixTranslation = -whichCamera.getPosition();
|
||||
|
||||
glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z);
|
||||
|
||||
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
|
||||
setupWorldLight(whichCamera);
|
||||
|
|
|
@ -152,6 +152,10 @@ public:
|
|||
|
||||
void setupWorldLight(Camera& whichCamera);
|
||||
|
||||
/// Loads a view matrix that incorporates the specified model translation without the precision issues that can
|
||||
/// result from matrix multiplication at high translation magnitudes.
|
||||
void loadTranslatedViewMatrix(const glm::vec3& translation);
|
||||
|
||||
/// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account.
|
||||
void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near,
|
||||
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
|
||||
|
@ -337,6 +341,9 @@ private:
|
|||
QRect _mirrorViewRect;
|
||||
RearMirrorTools* _rearMirrorTools;
|
||||
|
||||
glm::mat4 _untranslatedViewMatrix;
|
||||
glm::vec3 _viewMatrixTranslation;
|
||||
|
||||
Environment _environment;
|
||||
|
||||
int _headMouseX, _headMouseY;
|
||||
|
|
|
@ -62,7 +62,7 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ
|
|||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
||||
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getOrientation() * IDENTITY_FRONT, 0.0f));
|
||||
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
||||
_owningHead->getSaccade(), 1.0f));
|
||||
_owningHead->getSaccade() - _translation, 1.0f));
|
||||
glm::quat between = rotationBetween(front, lookAt);
|
||||
const float MAX_ANGLE = 30.0f;
|
||||
state.rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Avatar.h"
|
||||
#include "SkeletonModel.h"
|
||||
|
||||
|
@ -47,7 +48,7 @@ bool SkeletonModel::render(float alpha) {
|
|||
|
||||
glm::vec3 position;
|
||||
getJointPosition(i, position);
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
Application::getInstance()->loadTranslatedViewMatrix(position);
|
||||
|
||||
glm::quat rotation;
|
||||
getJointRotation(i, rotation);
|
||||
|
@ -85,9 +86,9 @@ void SkeletonModel::updateJointState(int index) {
|
|||
|
||||
if (index == _geometry->getFBXGeometry().rootJointIndex) {
|
||||
JointState& state = _jointStates[index];
|
||||
state.transform[3][0] = _translation.x;
|
||||
state.transform[3][1] = _translation.y;
|
||||
state.transform[3][2] = _translation.z;
|
||||
state.transform[3][0] = 0.0f;
|
||||
state.transform[3][1] = 0.0f;
|
||||
state.transform[3][2] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ void Model::simulate(float deltaTime) {
|
|||
}
|
||||
sourceVertices = _blendedVertices.constData();
|
||||
}
|
||||
glm::mat4 transform;
|
||||
glm::mat4 transform = glm::translate(_translation);
|
||||
if (mesh.clusters.size() > 1) {
|
||||
_blendedVertices.resize(max(_blendedVertices.size(), vertexCount));
|
||||
|
||||
|
@ -283,6 +283,9 @@ bool Model::render(float alpha) {
|
|||
ProgramObject* activeProgram = program;
|
||||
int tangentLocation = _normalMapTangentLocation;
|
||||
if (state.worldSpaceVertices.isEmpty()) {
|
||||
glPushMatrix();
|
||||
Application::getInstance()->loadTranslatedViewMatrix(_translation);
|
||||
|
||||
if (state.clusterMatrices.size() > 1) {
|
||||
skinProgram->bind();
|
||||
glUniformMatrix4fvARB(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
|
||||
|
@ -298,8 +301,7 @@ bool Model::render(float alpha) {
|
|||
activeProgram = skinProgram;
|
||||
tangentLocation = skinLocations->tangent;
|
||||
|
||||
} else {
|
||||
glPushMatrix();
|
||||
} else {
|
||||
glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]);
|
||||
program->bind();
|
||||
}
|
||||
|
@ -427,11 +429,9 @@ bool Model::render(float alpha) {
|
|||
if (state.worldSpaceVertices.isEmpty()) {
|
||||
if (state.clusterMatrices.size() > 1) {
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterIndices);
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterWeights);
|
||||
|
||||
} else {
|
||||
glPopMatrix();
|
||||
}
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterWeights);
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
activeProgram->release();
|
||||
}
|
||||
|
@ -513,8 +513,7 @@ void Model::updateJointState(int index) {
|
|||
const FBXJoint& joint = geometry.joints.at(index);
|
||||
|
||||
if (joint.parentIndex == -1) {
|
||||
glm::mat4 baseTransform = glm::translate(_translation) * glm::mat4_cast(_rotation) *
|
||||
glm::scale(_scale) * glm::translate(_offset);
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset);
|
||||
|
||||
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
|
||||
state.transform = baseTransform * geometry.offset * joint.preTransform *
|
||||
|
@ -555,7 +554,7 @@ bool Model::getJointPosition(int jointIndex, glm::vec3& position) const {
|
|||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
position = extractTranslation(_jointStates[jointIndex].transform);
|
||||
position = _translation + extractTranslation(_jointStates[jointIndex].transform);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -572,6 +571,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position) {
|
|||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
glm::vec3 relativePosition = position - _translation;
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;
|
||||
|
||||
|
@ -583,7 +583,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position) {
|
|||
glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].transform);
|
||||
for (int j = 1; j < freeLineage.size(); j++) {
|
||||
int index = freeLineage.at(j);
|
||||
if (glm::distance(endPosition, position) < EPSILON) {
|
||||
if (glm::distance(endPosition, relativePosition) < EPSILON) {
|
||||
return true; // close enough to target position
|
||||
}
|
||||
const FBXJoint& joint = geometry.joints.at(index);
|
||||
|
@ -593,7 +593,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position) {
|
|||
JointState& state = _jointStates[index];
|
||||
glm::vec3 jointPosition = extractTranslation(state.transform);
|
||||
glm::vec3 jointVector = endPosition - jointPosition;
|
||||
glm::quat deltaRotation = rotationBetween(jointVector, position - jointPosition);
|
||||
glm::quat deltaRotation = rotationBetween(jointVector, relativePosition - jointPosition);
|
||||
state.rotation = state.rotation * glm::inverse(state.combinedRotation) * deltaRotation * state.combinedRotation;
|
||||
endPosition = deltaRotation * jointVector + jointPosition;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue