first cut at 3D TV support

This commit is contained in:
ZappoMan 2013-12-28 10:07:33 -08:00
parent ebdf80a4ed
commit a43844447c
6 changed files with 208 additions and 12 deletions

View file

@ -57,6 +57,7 @@
#include "Util.h"
#include "devices/LeapManager.h"
#include "devices/OculusManager.h"
#include "devices/TV3DManager.h"
#include "renderer/ProgramObject.h"
#include "ui/TextRenderer.h"
#include "InfoView.h"
@ -439,7 +440,10 @@ void Application::paintGL() {
if (OculusManager::isConnected()) {
OculusManager::display(whichCamera);
} else if (TV3DManager::isConnected()) {
_glowEffect.prepare();
TV3DManager::display(whichCamera);
_glowEffect.render();
} else {
_glowEffect.prepare();
@ -474,8 +478,13 @@ void Application::paintGL() {
_mirrorCamera.update(1.0f/_fps);
// set the bounds of rear mirror view
glViewport(_mirrorViewRect.x(), _glWidget->height() - _mirrorViewRect.y() - _mirrorViewRect.height(), _mirrorViewRect.width(), _mirrorViewRect.height());
glScissor(_mirrorViewRect.x(), _glWidget->height() - _mirrorViewRect.y() - _mirrorViewRect.height(), _mirrorViewRect.width(), _mirrorViewRect.height());
float mirrorX = _mirrorViewRect.x();
float mirrorY = _glWidget->height() - _mirrorViewRect.y() - _mirrorViewRect.height();
float mirrorW = _mirrorViewRect.width();
float mirrorH = _mirrorViewRect.height();
glViewport(mirrorX, mirrorY, mirrorW, mirrorH);
glScissor(mirrorX, mirrorY, mirrorW, mirrorH);
bool updateViewFrustum = false;
updateProjectionMatrix(_mirrorCamera, updateViewFrustum);
glEnable(GL_SCISSOR_TEST);
@ -501,14 +510,18 @@ void Application::paintGL() {
_myAvatar.getSkeletonModel().setTranslation(_myAvatar.getHead().getFaceModel().getTranslation() -
neckPosition);
displaySide(_mirrorCamera, true);
//displaySide(_mirrorCamera, true);
displaySide(whichCamera);
// restore absolute translations
_myAvatar.getSkeletonModel().setTranslation(absoluteSkeletonTranslation);
_myAvatar.getHead().getFaceModel().setTranslation(absoluteFaceTranslation);
} else {
displaySide(_mirrorCamera, true);
//displaySide(_mirrorCamera, true);
displaySide(whichCamera);
}
glPopMatrix();
@ -531,7 +544,8 @@ void Application::paintGL() {
void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) {
if (OculusManager::isConnected()) {
OculusManager::configureCamera(camera, width, height);
} else if (TV3DManager::isConnected()) {
TV3DManager::configureCamera(camera, width, height);
} else {
camera.setAspectRatio((float)width / height);
camera.setFieldOfView(Menu::getInstance()->getFieldOfView());
@ -910,7 +924,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_J:
if (isShifted) {
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f);
if (TV3DManager::isConnected()) {
TV3DManager::configureCamera(_myCamera, _glWidget->width(),_glWidget->height());
}
} else {
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
}
@ -920,6 +936,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_M:
if (isShifted) {
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f);
if (TV3DManager::isConnected()) {
TV3DManager::configureCamera(_myCamera, _glWidget->width(),_glWidget->height());
}
} else {
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
@ -1828,6 +1847,13 @@ void Application::init() {
"trigger",
Qt::QueuedConnection);
}
TV3DManager::connect();
if (TV3DManager::isConnected()) {
QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen),
"trigger",
Qt::QueuedConnection);
}
LeapManager::initialize();
@ -2415,7 +2441,7 @@ void Application::updateCamera(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateCamera()");
if (!OculusManager::isConnected()) {
if (!OculusManager::isConnected() && !TV3DManager::isConnected()) {
if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
_myCamera.setMode(CAMERA_MODE_MIRROR);
@ -3800,7 +3826,7 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) {
return;
}
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... Avatars...");
"Application::renderAvatars()");
if (!selfAvatarOnly) {
// Render avatars of other nodes
@ -4089,7 +4115,7 @@ void Application::resetSensors() {
if (OculusManager::isConnected()) {
OculusManager::reset();
}
QCursor::setPos(_headMouseX, _headMouseY);
_myAvatar.reset();
_myTransmitter.resetLevels();

View file

@ -255,11 +255,13 @@ private slots:
void resetSensors();
private:
void resetCamerasOnResizeGL(Camera& camera, int width, int height);
public:
void updateProjectionMatrix();
void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true);
private:
void resetCamerasOnResizeGL(Camera& camera, int width, int height);
static bool sendVoxelsOperation(OctreeElement* node, void* extraData);
static void processAvatarURLsMessage(unsigned char* packetData, size_t dataBytes);
static void processAvatarFaceVideoMessage(unsigned char* packetData, size_t dataBytes);

View file

@ -232,6 +232,8 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, Qt::Key_P, true);
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H);
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H);
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0, false);
QMenu* avatarSizeMenu = viewMenu->addMenu("Avatar Size");

View file

@ -178,6 +178,7 @@ namespace MenuOption {
const QString FilterSixense = "Smooth Sixense Movement";
const QString DontRenderVoxels = "Don't call _voxels.render()";
const QString DontCallOpenGLForVoxels = "Don't call glDrawRangeElementsEXT() for Voxels";
const QString Enable3DTVMode = "Enable 3DTV Mode";
const QString EnableOcclusionCulling = "Enable Occlusion Culling";
const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression";
const QString EchoServerAudio = "Echo Server Audio";

View file

@ -0,0 +1,124 @@
//
// TV3DManager.cpp
// hifi
//
// Created by Stephen Birarda on 5/9/13.
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#include <QOpenGLFramebufferObject>
#include <glm/glm.hpp>
#include "Application.h"
#include "InterfaceConfig.h"
#include "TV3DManager.h"
#include "Menu.h"
int TV3DManager::_screenWidth = 1;
int TV3DManager::_screenHeight = 1;
double TV3DManager::_aspect = 1.0;
eyeFrustum TV3DManager::_leftEye;
eyeFrustum TV3DManager::_rightEye;
bool TV3DManager::isConnected() {
return Menu::getInstance()->isOptionChecked(MenuOption::Enable3DTVMode);
}
void TV3DManager::connect() {
}
void TV3DManager::setFrustum(Camera& whichCamera) {
const double DTR = 0.0174532925; // degree to radians
const double IOD = 0.05; //intraocular distance
double fovy = whichCamera.getFieldOfView(); // field of view in y-axis
double nearZ = whichCamera.getNearClip(); // near clipping plane
double screenZ = Application::getInstance()->getViewFrustum()->getFocalLength(); // screen projection plane
double top = nearZ * tan(DTR * fovy / 2); //sets top of frustum based on fovy and near clipping plane
double right = _aspect * top; // sets right of frustum based on aspect ratio
double frustumshift = (IOD / 2) * nearZ / screenZ;
_leftEye.top = top;
_leftEye.bottom = -top;
_leftEye.left = -right + frustumshift;
_leftEye.right = right + frustumshift;
_leftEye.modelTranslation = IOD / 2;
_rightEye.top = top;
_rightEye.bottom = -top;
_rightEye.left = -right - frustumshift;
_rightEye.right = right - frustumshift;
_rightEye.modelTranslation = -IOD / 2;
}
void TV3DManager::configureCamera(Camera& whichCamera, int screenWidth, int screenHeight) {
if (screenHeight == 0) {
screenHeight = 1; // prevent divide by 0
}
_screenWidth = screenWidth;
_screenHeight = screenHeight;
_aspect= (double)_screenWidth / (double)_screenHeight;
setFrustum(whichCamera);
glViewport (0, 0, _screenWidth, _screenHeight); // sets drawing viewport
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void TV3DManager::display(Camera& whichCamera) {
double nearZ = whichCamera.getNearClip(); // near clipping plane
double farZ = whichCamera.getFarClip(); // far clipping plane
// left eye portal
int portalX = 0;
int portalY = 0;
int portalW = Application::getInstance()->getGLWidget()->width() / 2;
int portalH = Application::getInstance()->getGLWidget()->height();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
// render left side view
glViewport(portalX, portalY, portalW, portalH);
glScissor(portalX, portalY, portalW, portalH);
glPushMatrix();
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // reset projection matrix
glFrustum(_leftEye.left, _leftEye.right, _leftEye.bottom, _leftEye.top, nearZ, farZ); // set left view frustum
glTranslatef(_leftEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Application::getInstance()->displaySide(whichCamera);
}
glPopMatrix();
glDisable(GL_SCISSOR_TEST);
// render right side view
portalX = Application::getInstance()->getGLWidget()->width() / 2;
glEnable(GL_SCISSOR_TEST);
// render left side view
glViewport(portalX, portalY, portalW, portalH);
glScissor(portalX, portalY, portalW, portalH);
glPushMatrix();
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // reset projection matrix
glFrustum(_rightEye.left, _rightEye.right, _rightEye.bottom, _rightEye.top, nearZ, farZ); // set left view frustum
glTranslatef(_rightEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Application::getInstance()->displaySide(whichCamera);
}
glPopMatrix();
glDisable(GL_SCISSOR_TEST);
// reset the viewport to how we started
glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height());
}

View file

@ -0,0 +1,41 @@
//
// TV3DManager.h
// hifi
//
// Created by Brad Hefta-Gaub on 12/24/2013
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__TV3DManager__
#define __hifi__TV3DManager__
#include <iostream>
class Camera;
struct eyeFrustum {
double left;
double right;
double bottom;
double top;
float modelTranslation;
};
/// Handles interaction with 3D TVs
class TV3DManager {
public:
static void connect();
static bool isConnected();
static void configureCamera(Camera& camera, int screenWidth, int screenHeight);
static void display(Camera& whichCamera);
private:
static void setFrustum(Camera& whichCamera);
static int _screenWidth;
static int _screenHeight;
static double _aspect;
static eyeFrustum _leftEye;
static eyeFrustum _rightEye;
};
#endif /* defined(__hifi__TV3DManager__) */