mirror of
https://github.com/JulianGro/overte.git
synced 2025-07-14 13:26:38 +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
|
@ -2866,6 +2866,12 @@ void Application::setupWorldLight(Camera& whichCamera) {
|
||||||
glMateriali(GL_FRONT, GL_SHININESS, 96);
|
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,
|
void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near,
|
||||||
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const {
|
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);
|
glm::vec3 axis = glm::axis(rotation);
|
||||||
glRotatef(-glm::angle(rotation), axis.x, axis.y, axis.z);
|
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)
|
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
|
||||||
setupWorldLight(whichCamera);
|
setupWorldLight(whichCamera);
|
||||||
|
|
|
@ -152,6 +152,10 @@ public:
|
||||||
|
|
||||||
void setupWorldLight(Camera& whichCamera);
|
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.
|
/// 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,
|
void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near,
|
||||||
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
|
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
|
||||||
|
@ -337,6 +341,9 @@ private:
|
||||||
QRect _mirrorViewRect;
|
QRect _mirrorViewRect;
|
||||||
RearMirrorTools* _rearMirrorTools;
|
RearMirrorTools* _rearMirrorTools;
|
||||||
|
|
||||||
|
glm::mat4 _untranslatedViewMatrix;
|
||||||
|
glm::vec3 _viewMatrixTranslation;
|
||||||
|
|
||||||
Environment _environment;
|
Environment _environment;
|
||||||
|
|
||||||
int _headMouseX, _headMouseY;
|
int _headMouseX, _headMouseY;
|
||||||
|
|
|
@ -62,7 +62,7 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ
|
||||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
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 front = glm::vec3(inverse * glm::vec4(_owningHead->getOrientation() * IDENTITY_FRONT, 0.0f));
|
||||||
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
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);
|
glm::quat between = rotationBetween(front, lookAt);
|
||||||
const float MAX_ANGLE = 30.0f;
|
const float MAX_ANGLE = 30.0f;
|
||||||
state.rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
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 <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
#include "SkeletonModel.h"
|
#include "SkeletonModel.h"
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ bool SkeletonModel::render(float alpha) {
|
||||||
|
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
getJointPosition(i, position);
|
getJointPosition(i, position);
|
||||||
glTranslatef(position.x, position.y, position.z);
|
Application::getInstance()->loadTranslatedViewMatrix(position);
|
||||||
|
|
||||||
glm::quat rotation;
|
glm::quat rotation;
|
||||||
getJointRotation(i, rotation);
|
getJointRotation(i, rotation);
|
||||||
|
@ -85,9 +86,9 @@ void SkeletonModel::updateJointState(int index) {
|
||||||
|
|
||||||
if (index == _geometry->getFBXGeometry().rootJointIndex) {
|
if (index == _geometry->getFBXGeometry().rootJointIndex) {
|
||||||
JointState& state = _jointStates[index];
|
JointState& state = _jointStates[index];
|
||||||
state.transform[3][0] = _translation.x;
|
state.transform[3][0] = 0.0f;
|
||||||
state.transform[3][1] = _translation.y;
|
state.transform[3][1] = 0.0f;
|
||||||
state.transform[3][2] = _translation.z;
|
state.transform[3][2] = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ void Model::simulate(float deltaTime) {
|
||||||
}
|
}
|
||||||
sourceVertices = _blendedVertices.constData();
|
sourceVertices = _blendedVertices.constData();
|
||||||
}
|
}
|
||||||
glm::mat4 transform;
|
glm::mat4 transform = glm::translate(_translation);
|
||||||
if (mesh.clusters.size() > 1) {
|
if (mesh.clusters.size() > 1) {
|
||||||
_blendedVertices.resize(max(_blendedVertices.size(), vertexCount));
|
_blendedVertices.resize(max(_blendedVertices.size(), vertexCount));
|
||||||
|
|
||||||
|
@ -283,6 +283,9 @@ bool Model::render(float alpha) {
|
||||||
ProgramObject* activeProgram = program;
|
ProgramObject* activeProgram = program;
|
||||||
int tangentLocation = _normalMapTangentLocation;
|
int tangentLocation = _normalMapTangentLocation;
|
||||||
if (state.worldSpaceVertices.isEmpty()) {
|
if (state.worldSpaceVertices.isEmpty()) {
|
||||||
|
glPushMatrix();
|
||||||
|
Application::getInstance()->loadTranslatedViewMatrix(_translation);
|
||||||
|
|
||||||
if (state.clusterMatrices.size() > 1) {
|
if (state.clusterMatrices.size() > 1) {
|
||||||
skinProgram->bind();
|
skinProgram->bind();
|
||||||
glUniformMatrix4fvARB(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
|
glUniformMatrix4fvARB(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
|
||||||
|
@ -298,8 +301,7 @@ bool Model::render(float alpha) {
|
||||||
activeProgram = skinProgram;
|
activeProgram = skinProgram;
|
||||||
tangentLocation = skinLocations->tangent;
|
tangentLocation = skinLocations->tangent;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
glPushMatrix();
|
|
||||||
glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]);
|
glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]);
|
||||||
program->bind();
|
program->bind();
|
||||||
}
|
}
|
||||||
|
@ -427,11 +429,9 @@ bool Model::render(float alpha) {
|
||||||
if (state.worldSpaceVertices.isEmpty()) {
|
if (state.worldSpaceVertices.isEmpty()) {
|
||||||
if (state.clusterMatrices.size() > 1) {
|
if (state.clusterMatrices.size() > 1) {
|
||||||
skinProgram->disableAttributeArray(skinLocations->clusterIndices);
|
skinProgram->disableAttributeArray(skinLocations->clusterIndices);
|
||||||
skinProgram->disableAttributeArray(skinLocations->clusterWeights);
|
skinProgram->disableAttributeArray(skinLocations->clusterWeights);
|
||||||
|
}
|
||||||
} else {
|
glPopMatrix();
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
activeProgram->release();
|
activeProgram->release();
|
||||||
}
|
}
|
||||||
|
@ -513,8 +513,7 @@ void Model::updateJointState(int index) {
|
||||||
const FBXJoint& joint = geometry.joints.at(index);
|
const FBXJoint& joint = geometry.joints.at(index);
|
||||||
|
|
||||||
if (joint.parentIndex == -1) {
|
if (joint.parentIndex == -1) {
|
||||||
glm::mat4 baseTransform = glm::translate(_translation) * glm::mat4_cast(_rotation) *
|
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset);
|
||||||
glm::scale(_scale) * glm::translate(_offset);
|
|
||||||
|
|
||||||
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
|
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
|
||||||
state.transform = baseTransform * geometry.offset * joint.preTransform *
|
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()) {
|
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
position = extractTranslation(_jointStates[jointIndex].transform);
|
position = _translation + extractTranslation(_jointStates[jointIndex].transform);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,6 +571,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position) {
|
||||||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
glm::vec3 relativePosition = position - _translation;
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;
|
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);
|
glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].transform);
|
||||||
for (int j = 1; j < freeLineage.size(); j++) {
|
for (int j = 1; j < freeLineage.size(); j++) {
|
||||||
int index = freeLineage.at(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
|
return true; // close enough to target position
|
||||||
}
|
}
|
||||||
const FBXJoint& joint = geometry.joints.at(index);
|
const FBXJoint& joint = geometry.joints.at(index);
|
||||||
|
@ -593,7 +593,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position) {
|
||||||
JointState& state = _jointStates[index];
|
JointState& state = _jointStates[index];
|
||||||
glm::vec3 jointPosition = extractTranslation(state.transform);
|
glm::vec3 jointPosition = extractTranslation(state.transform);
|
||||||
glm::vec3 jointVector = endPosition - jointPosition;
|
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;
|
state.rotation = state.rotation * glm::inverse(state.combinedRotation) * deltaRotation * state.combinedRotation;
|
||||||
endPosition = deltaRotation * jointVector + jointPosition;
|
endPosition = deltaRotation * jointVector + jointPosition;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue