mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 17:00:13 +02:00
Merge pull request #2894 from Barnold1953/master
Oculus camera mode and mirror view fixes
This commit is contained in:
commit
21b89b9940
7 changed files with 33 additions and 43 deletions
|
@ -553,14 +553,6 @@ void Application::paintGL() {
|
||||||
PerformanceWarning warn(showWarnings, "Application::paintGL()");
|
PerformanceWarning warn(showWarnings, "Application::paintGL()");
|
||||||
|
|
||||||
glEnable(GL_LINE_SMOOTH);
|
glEnable(GL_LINE_SMOOTH);
|
||||||
|
|
||||||
float pushback = 0.0f;
|
|
||||||
float pushbackFocalLength = 0.0f;
|
|
||||||
if (OculusManager::isConnected()) {
|
|
||||||
_myCamera.setUpShift(0.0f);
|
|
||||||
_myCamera.setDistance(0.0f);
|
|
||||||
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||||
_myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay
|
_myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay
|
||||||
|
@ -576,39 +568,25 @@ void Application::paintGL() {
|
||||||
_myCamera.setTightness(0.0f);
|
_myCamera.setTightness(0.0f);
|
||||||
glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition();
|
glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition();
|
||||||
float headHeight = eyePosition.y - _myAvatar->getPosition().y;
|
float headHeight = eyePosition.y - _myAvatar->getPosition().y;
|
||||||
_myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar->getScale() * _scaleMirror);
|
_myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
||||||
_myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight + (_raiseMirror * _myAvatar->getScale()), 0));
|
_myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight + (_raiseMirror * _myAvatar->getScale()), 0));
|
||||||
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
||||||
|
|
||||||
// if the head would intersect the near clip plane, we must push the camera out
|
|
||||||
glm::vec3 relativePosition = glm::inverse(_myCamera.getTargetRotation()) *
|
|
||||||
(eyePosition - _myCamera.getTargetPosition());
|
|
||||||
const float BASE_PUSHBACK_RADIUS = 0.2f;
|
|
||||||
float pushbackRadius = _myCamera.getNearClip() + _myAvatar->getScale() * BASE_PUSHBACK_RADIUS;
|
|
||||||
pushback = relativePosition.z + pushbackRadius - _myCamera.getDistance();
|
|
||||||
pushbackFocalLength = _myCamera.getDistance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle pushback, if any
|
if (OculusManager::isConnected()) {
|
||||||
if (pushbackFocalLength > 0.0f) {
|
// Oculus in third person causes nausea, so only allow it if option is checked in dev menu
|
||||||
const float PUSHBACK_DECAY = 0.5f;
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::AllowOculusCameraModeChange) || _myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||||
_cameraPushback = qMax(pushback, _cameraPushback * PUSHBACK_DECAY);
|
_myCamera.setDistance(0.0f);
|
||||||
if (_cameraPushback > EPSILON) {
|
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
|
||||||
_myCamera.setTargetPosition(_myCamera.getTargetPosition() +
|
_myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
|
||||||
_myCamera.getTargetRotation() * glm::vec3(0.0f, 0.0f, _cameraPushback));
|
|
||||||
float enlargement = pushbackFocalLength / (pushbackFocalLength + _cameraPushback);
|
|
||||||
_myCamera.setFieldOfView(glm::degrees(2.0f * atanf(enlargement * tanf(
|
|
||||||
glm::radians(Menu::getInstance()->getFieldOfView() * 0.5f)))));
|
|
||||||
} else {
|
|
||||||
_myCamera.setFieldOfView(Menu::getInstance()->getFieldOfView());
|
|
||||||
}
|
}
|
||||||
updateProjectionMatrix(_myCamera, true);
|
_myCamera.setUpShift(0.0f);
|
||||||
|
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update camera position
|
// Update camera position
|
||||||
_myCamera.update( 1.f/_fps );
|
_myCamera.update( 1.f/_fps );
|
||||||
|
|
||||||
|
|
||||||
// Note: whichCamera is used to pick between the normal camera myCamera for our
|
// Note: whichCamera is used to pick between the normal camera myCamera for our
|
||||||
// main camera, vs, an alternate camera. The alternate camera we support right now
|
// main camera, vs, an alternate camera. The alternate camera we support right now
|
||||||
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
|
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
|
||||||
|
|
|
@ -202,7 +202,7 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
|
||||||
CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pMMDeviceEnumerator);
|
CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pMMDeviceEnumerator);
|
||||||
IMMDevice* pEndpoint;
|
IMMDevice* pEndpoint;
|
||||||
hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(mode == QAudio::AudioOutput ? eRender : eCapture, eMultimedia, &pEndpoint);
|
hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(mode == QAudio::AudioOutput ? eRender : eCapture, eMultimedia, &pEndpoint);
|
||||||
if (hr == E_NOTFOUND){
|
if (hr == E_NOTFOUND) {
|
||||||
printf("Audio Error: device not found\n");
|
printf("Audio Error: device not found\n");
|
||||||
deviceName = QString("NONE");
|
deviceName = QString("NONE");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -329,6 +329,7 @@ Menu::Menu() :
|
||||||
|
|
||||||
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
||||||
|
|
||||||
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::AllowOculusCameraModeChange, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true);
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true);
|
||||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderSkeletonCollisionShapes);
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderSkeletonCollisionShapes);
|
||||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderHeadCollisionShapes);
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderHeadCollisionShapes);
|
||||||
|
|
|
@ -270,6 +270,7 @@ private:
|
||||||
namespace MenuOption {
|
namespace MenuOption {
|
||||||
const QString AboutApp = "About Interface";
|
const QString AboutApp = "About Interface";
|
||||||
const QString AlignForearmsWithWrists = "Align Forearms with Wrists";
|
const QString AlignForearmsWithWrists = "Align Forearms with Wrists";
|
||||||
|
const QString AllowOculusCameraModeChange = "Allow Oculus Camera Mode Change (Nausea)";
|
||||||
const QString AlternateIK = "Alternate IK";
|
const QString AlternateIK = "Alternate IK";
|
||||||
const QString AmbientOcclusion = "Ambient Occlusion";
|
const QString AmbientOcclusion = "Ambient Occlusion";
|
||||||
const QString Animations = "Animations...";
|
const QString Animations = "Animations...";
|
||||||
|
|
|
@ -237,11 +237,15 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
||||||
// If this is the avatar being looked at, render a little ball above their head
|
// If this is the avatar being looked at, render a little ball above their head
|
||||||
if (_isLookAtTarget) {
|
if (_isLookAtTarget) {
|
||||||
const float LOOK_AT_INDICATOR_RADIUS = 0.03f;
|
const float LOOK_AT_INDICATOR_RADIUS = 0.03f;
|
||||||
const float LOOK_AT_INDICATOR_HEIGHT = 0.60f;
|
const float LOOK_AT_INDICATOR_OFFSET = 0.22f;
|
||||||
const float LOOK_AT_INDICATOR_COLOR[] = { 0.8f, 0.0f, 0.0f, 0.5f };
|
const float LOOK_AT_INDICATOR_COLOR[] = { 0.8f, 0.0f, 0.0f, 0.75f };
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glColor4fv(LOOK_AT_INDICATOR_COLOR);
|
glColor4fv(LOOK_AT_INDICATOR_COLOR);
|
||||||
glTranslatef(_position.x, _position.y + (getSkeletonHeight() * LOOK_AT_INDICATOR_HEIGHT), _position.z);
|
if (_displayName.isEmpty() || _displayNameAlpha == 0.0f) {
|
||||||
|
glTranslatef(_position.x, getDisplayNamePosition().y, _position.z);
|
||||||
|
} else {
|
||||||
|
glTranslatef(_position.x, getDisplayNamePosition().y + LOOK_AT_INDICATOR_OFFSET, _position.z);
|
||||||
|
}
|
||||||
glutSolidSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15);
|
glutSolidSphere(LOOK_AT_INDICATOR_RADIUS, 15, 15);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
@ -460,6 +464,17 @@ float Avatar::getBillboardSize() const {
|
||||||
return _scale * BILLBOARD_DISTANCE * tanf(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
|
return _scale * BILLBOARD_DISTANCE * tanf(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 Avatar::getDisplayNamePosition() {
|
||||||
|
glm::vec3 namePosition;
|
||||||
|
if (getSkeletonModel().getNeckPosition(namePosition)) {
|
||||||
|
namePosition += getBodyUpDirection() * getHeadHeight() * 1.1f;
|
||||||
|
} else {
|
||||||
|
const float HEAD_PROPORTION = 0.75f;
|
||||||
|
namePosition = _position + getBodyUpDirection() * (getBillboardSize() * HEAD_PROPORTION);
|
||||||
|
}
|
||||||
|
return namePosition;
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::renderDisplayName() {
|
void Avatar::renderDisplayName() {
|
||||||
|
|
||||||
if (_displayName.isEmpty() || _displayNameAlpha == 0.0f) {
|
if (_displayName.isEmpty() || _displayNameAlpha == 0.0f) {
|
||||||
|
@ -469,13 +484,7 @@ void Avatar::renderDisplayName() {
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glm::vec3 textPosition;
|
glm::vec3 textPosition = getDisplayNamePosition();
|
||||||
if (getSkeletonModel().getNeckPosition(textPosition)) {
|
|
||||||
textPosition += getBodyUpDirection() * getHeadHeight() * 1.1f;
|
|
||||||
} else {
|
|
||||||
const float HEAD_PROPORTION = 0.75f;
|
|
||||||
textPosition = _position + getBodyUpDirection() * (getBillboardSize() * HEAD_PROPORTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
glTranslatef(textPosition.x, textPosition.y, textPosition.z);
|
glTranslatef(textPosition.x, textPosition.y, textPosition.z);
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,7 @@ protected:
|
||||||
float getHeadHeight() const;
|
float getHeadHeight() const;
|
||||||
float getPelvisFloatingHeight() const;
|
float getPelvisFloatingHeight() const;
|
||||||
float getPelvisToHeadLength() const;
|
float getPelvisToHeadLength() const;
|
||||||
|
glm::vec3 getDisplayNamePosition();
|
||||||
|
|
||||||
void renderDisplayName();
|
void renderDisplayName();
|
||||||
virtual void renderBody(RenderMode renderMode, float glowLevel = 0.0f);
|
virtual void renderBody(RenderMode renderMode, float glowLevel = 0.0f);
|
||||||
|
|
|
@ -266,7 +266,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
|
||||||
|
|
||||||
|
|
||||||
Head* head = getHead();
|
Head* head = getHead();
|
||||||
if (OculusManager::isConnected()){
|
if (OculusManager::isConnected()) {
|
||||||
head->setDeltaPitch(estimatedRotation.x);
|
head->setDeltaPitch(estimatedRotation.x);
|
||||||
head->setDeltaYaw(estimatedRotation.y);
|
head->setDeltaYaw(estimatedRotation.y);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue