pull from upstream

This commit is contained in:
Seth Alves 2015-05-06 14:31:22 -07:00
commit fe06ce2931
41 changed files with 824 additions and 636 deletions

View file

@ -817,7 +817,12 @@ void Application::initializeUi() {
void Application::paintGL() {
PROFILE_RANGE(__FUNCTION__);
_glWidget->makeCurrent();
PerformanceTimer perfTimer("paintGL");
//Need accurate frame timing for the oculus rift
if (OculusManager::isConnected()) {
OculusManager::beginFrameTiming();
}
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
@ -880,12 +885,10 @@ void Application::paintGL() {
if (OculusManager::isConnected()) {
//When in mirror mode, use camera rotation. Otherwise, use body rotation
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
OculusManager::display(_myCamera.getRotation(), _myCamera.getPosition(), _myCamera);
OculusManager::display(_glWidget, _myCamera.getRotation(), _myCamera.getPosition(), _myCamera);
} else {
OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera);
OculusManager::display(_glWidget, _myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera);
}
_myCamera.update(1.0f / _fps);
} else if (TV3DManager::isConnected()) {
TV3DManager::display(_myCamera);
@ -904,8 +907,7 @@ void Application::paintGL() {
glPopMatrix();
if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
_rearMirrorTools->render(true);
_rearMirrorTools->render(true, _glWidget->mapFromGlobal(QCursor::pos()));
} else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
renderRearViewMirror(_mirrorViewRect);
}
@ -919,6 +921,13 @@ void Application::paintGL() {
}
}
if (!OculusManager::isConnected() || OculusManager::allowSwap()) {
_glWidget->swapBuffers();
}
if (OculusManager::isConnected()) {
OculusManager::endFrameTiming();
}
_frameCount++;
}
@ -960,6 +969,7 @@ void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height)
}
void Application::resizeGL(int width, int height) {
DependencyManager::get<TextureCache>()->setFrameBufferSize(QSize(width, height));
resetCamerasOnResizeGL(_myCamera, width, height);
glViewport(0, 0, width, height); // shouldn't this account for the menu???
@ -1310,8 +1320,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
if (!event->isAutoRepeat()) {
// this starts an HFActionEvent
HFActionEvent startActionEvent(HFActionEvent::startType(),
_myCamera.computePickRay(getTrueMouseX(),
getTrueMouseY()));
computePickRay(getTrueMouseX(), getTrueMouseY()));
sendEvent(this, &startActionEvent);
}
@ -1366,8 +1375,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
if (!event->isAutoRepeat()) {
// this ends the HFActionEvent
HFActionEvent endActionEvent(HFActionEvent::endType(),
_myCamera.computePickRay(getTrueMouseX(),
getTrueMouseY()));
computePickRay(getTrueMouseX(), getTrueMouseY()));
sendEvent(this, &endActionEvent);
}
break;
@ -1475,7 +1483,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
// nobody handled this - make it an action event on the _window object
HFActionEvent actionEvent(HFActionEvent::startType(),
_myCamera.computePickRay(event->x(), event->y()));
computePickRay(event->x(), event->y()));
sendEvent(this, &actionEvent);
} else if (event->button() == Qt::RightButton) {
@ -1530,7 +1538,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
// fire an action end event
HFActionEvent actionEvent(HFActionEvent::endType(),
_myCamera.computePickRay(event->x(), event->y()));
computePickRay(event->x(), event->y()));
sendEvent(this, &actionEvent);
}
}
@ -2137,19 +2145,16 @@ void Application::init() {
_entityClipboardRenderer.setViewFrustum(getViewFrustum());
_entityClipboardRenderer.setTree(&_entityClipboard);
_rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect);
_rearMirrorTools = new RearMirrorTools(_mirrorViewRect);
connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView()));
connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView()));
connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView()));
connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors()));
// make sure our texture cache knows about window size changes
DependencyManager::get<TextureCache>()->associateWithWidget(_glWidget);
// initialize the GlowEffect with our widget
DependencyManager::get<GlowEffect>()->init(_glWidget,
Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect));
bool glow = Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect);
DependencyManager::get<GlowEffect>()->init(glow);
}
void Application::closeMirrorView() {
@ -2200,7 +2205,7 @@ void Application::updateMouseRay() {
// make sure the frustum is up-to-date
loadViewFrustum(_myCamera, _viewFrustum);
PickRay pickRay = _myCamera.computePickRay(getTrueMouseX(), getTrueMouseY());
PickRay pickRay = computePickRay(getTrueMouseX(), getTrueMouseY());
_mouseRayOrigin = pickRay.origin;
_mouseRayDirection = pickRay.direction;
@ -3028,8 +3033,17 @@ int Application::getBoundaryLevelAdjust() const {
return DependencyManager::get<LODManager>()->getBoundaryLevelAdjust();
}
PickRay Application::computePickRay(float x, float y) {
return getCamera()->computePickRay(x, y);
PickRay Application::computePickRay(float x, float y) const {
glm::vec2 size = getCanvasSize();
x /= size.x;
y /= size.y;
PickRay result;
if (isHMDMode()) {
ApplicationOverlay::computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction);
} else {
getViewFrustum()->computePickRay(x, y, result.origin, result.direction);
}
return result;
}
QImage Application::renderAvatarBillboard() {
@ -3062,6 +3076,16 @@ ViewFrustum* Application::getViewFrustum() {
return &_viewFrustum;
}
const ViewFrustum* Application::getViewFrustum() const {
#ifdef DEBUG
if (QThread::currentThread() == activeRenderingThread) {
// FIXME, should this be an assert?
qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?";
}
#endif
return &_viewFrustum;
}
ViewFrustum* Application::getDisplayViewFrustum() {
#ifdef DEBUG
if (QThread::currentThread() != activeRenderingThread) {
@ -3434,7 +3458,6 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
_mirrorCamera.setAspectRatio((float)region.width() / region.height());
_mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f)));
_mirrorCamera.update(1.0f/_fps);
// set the bounds of rear mirror view
if (billboard) {
@ -3460,7 +3483,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
glPopMatrix();
if (!billboard) {
_rearMirrorTools->render(false);
_rearMirrorTools->render(false, _glWidget->mapFromGlobal(QCursor::pos()));
}
// reset Viewport and projection matrix
@ -4344,7 +4367,7 @@ void Application::takeSnapshot() {
player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath()));
player->play();
QString fileName = Snapshot::saveSnapshot();
QString fileName = Snapshot::saveSnapshot(_glWidget->grabFrameBuffer());
AccountManager& accountManager = AccountManager::getInstance();
if (!accountManager.isLoggedIn()) {
@ -4533,3 +4556,51 @@ void Application::postLambdaEvent(std::function<void()> f) {
QCoreApplication::postEvent(this, new LambdaEvent(f));
}
void Application::initPlugins() {
OculusManager::init();
}
void Application::shutdownPlugins() {
OculusManager::deinit();
}
glm::vec3 Application::getHeadPosition() const {
return OculusManager::getRelativePosition();
}
glm::quat Application::getHeadOrientation() const {
return OculusManager::getOrientation();
}
glm::uvec2 Application::getCanvasSize() const {
return glm::uvec2(_glWidget->width(), _glWidget->height());
}
QSize Application::getDeviceSize() const {
return _glWidget->getDeviceSize();
}
int Application::getTrueMouseX() const {
return _glWidget->mapFromGlobal(QCursor::pos()).x();
}
int Application::getTrueMouseY() const {
return _glWidget->mapFromGlobal(QCursor::pos()).y();
}
bool Application::isThrottleRendering() const {
return _glWidget->isThrottleRendering();
}
PickRay Application::computePickRay() const {
return computePickRay(getTrueMouseX(), getTrueMouseY());
}
bool Application::hasFocus() const {
return _glWidget->hasFocus();
}
void Application::resizeGL() {
this->resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
}

View file

@ -148,6 +148,8 @@ public:
static glm::quat getOrientationForPath() { return getInstance()->_myAvatar->getOrientation(); }
static glm::vec3 getPositionForAudio() { return getInstance()->_myAvatar->getHead()->getPosition(); }
static glm::quat getOrientationForAudio() { return getInstance()->_myAvatar->getHead()->getFinalOrientationInWorldFrame(); }
static void initPlugins();
static void shutdownPlugins();
Application(int& argc, char** argv, QElapsedTimer &startup_time);
~Application();
@ -163,6 +165,8 @@ public:
void paintGL();
void resizeGL(int width, int height);
void resizeEvent(QResizeEvent * size);
void keyPressEvent(QKeyEvent* event);
void keyReleaseEvent(QKeyEvent* event);
@ -185,12 +189,19 @@ public:
bool event(QEvent* event);
bool eventFilter(QObject* object, QEvent* event);
GLCanvas* getGLWidget() { return _glWidget; }
bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); }
glm::uvec2 getCanvasSize() const;
QSize getDeviceSize() const;
bool hasFocus() const;
PickRay computePickRay() const;
PickRay computeViewPickRay(float xRatio, float yRatio) const;
void resizeGL();
bool isThrottleRendering() const;
Camera* getCamera() { return &_myCamera; }
// Represents the current view frustum of the avatar.
ViewFrustum* getViewFrustum();
const ViewFrustum* getViewFrustum() const;
// Represents the view frustum of the current rendering pass,
// which might be different from the viewFrustum, i.e. shadowmap
// passes, mirror window passes, etc
@ -212,8 +223,9 @@ public:
bool mouseOnScreen() const;
int getMouseX() const;
int getMouseY() const;
int getTrueMouseX() const { return _glWidget->mapFromGlobal(QCursor::pos()).x(); }
int getTrueMouseY() const { return _glWidget->mapFromGlobal(QCursor::pos()).y(); }
glm::ivec2 getTrueMousePosition() const;
int getTrueMouseX() const;
int getTrueMouseY() const;
int getMouseDragStartedX() const;
int getMouseDragStartedY() const;
int getTrueMouseDragStartedX() const { return _mouseDragStartedX; }
@ -225,6 +237,7 @@ public:
QSystemTrayIcon* getTrayIcon() { return _trayIcon; }
ApplicationOverlay& getApplicationOverlay() { return _applicationOverlay; }
const ApplicationOverlay& getApplicationOverlay() const { return _applicationOverlay; }
Overlays& getOverlays() { return _overlays; }
float getFps() const { return _fps; }
@ -284,7 +297,7 @@ public:
virtual QThread* getMainThread() { return thread(); }
virtual float getSizeScale() const;
virtual int getBoundaryLevelAdjust() const;
virtual PickRay computePickRay(float x, float y);
virtual PickRay computePickRay(float x, float y) const;
virtual const glm::vec3& getAvatarPosition() const { return _myAvatar->getPosition(); }
virtual void overrideEnvironmentData(const EnvironmentData& newData) { _environment.override(newData); }
virtual void endOverrideEnvironmentData() { _environment.endOverride(); }
@ -294,8 +307,8 @@ public:
FileLogger* getLogger() { return _logger; }
glm::vec2 getViewportDimensions() const { return glm::vec2(_glWidget->getDeviceWidth(),
_glWidget->getDeviceHeight()); }
glm::vec2 getViewportDimensions() const;
NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; }
void skipVersion(QString latestVersion);
@ -317,7 +330,9 @@ public:
// rendering of several elements depend on that
// TODO: carry that information on the Camera as a setting
bool isHMDMode() const;
glm::quat getHeadOrientation() const;
glm::vec3 getHeadPosition() const;
QRect getDesirableApplicationGeometry();
RunningScriptsWidget* getRunningScriptsWidget() { return _runningScriptsWidget; }

View file

@ -17,7 +17,6 @@
#include "Camera.h"
#include "Menu.h"
#include "Util.h"
#include "devices/OculusManager.h"
CameraMode stringToMode(const QString& mode) {
@ -121,18 +120,7 @@ void Camera::setFarClip(float f) {
}
PickRay Camera::computePickRay(float x, float y) {
auto glCanvas = Application::getInstance()->getGLWidget();
return computeViewPickRay(x / glCanvas->width(), y / glCanvas->height());
}
PickRay Camera::computeViewPickRay(float xRatio, float yRatio) {
PickRay result;
if (OculusManager::isConnected()) {
Application::getInstance()->getApplicationOverlay().computeOculusPickRay(xRatio, yRatio, result.origin, result.direction);
} else {
Application::getInstance()->getViewFrustum()->computePickRay(xRatio, yRatio, result.origin, result.direction);
}
return result;
return qApp->computePickRay(x, y);
}
void Camera::setModeString(const QString& mode) {

View file

@ -77,7 +77,6 @@ public slots:
glm::quat getOrientation() const { return getRotation(); }
PickRay computePickRay(float x, float y);
PickRay computeViewPickRay(float xRatio, float yRatio);
// These only work on independent cameras
/// one time change to what the camera is looking at

View file

@ -16,7 +16,6 @@
#include "Application.h"
#include "GLCanvas.h"
#include "MainWindow.h"
#include "devices/OculusManager.h"
const int MSECS_PER_FRAME_WHEN_THROTTLED = 66;
@ -60,21 +59,7 @@ void GLCanvas::initializeGL() {
void GLCanvas::paintGL() {
if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) {
//Need accurate frame timing for the oculus rift
if (OculusManager::isConnected()) {
OculusManager::beginFrameTiming();
}
Application::getInstance()->paintGL();
if (!OculusManager::isConnected()) {
swapBuffers();
} else {
if (OculusManager::allowSwap()) {
swapBuffers();
}
OculusManager::endFrameTiming();
}
}
}
@ -110,18 +95,7 @@ void GLCanvas::activeChanged(Qt::ApplicationState state) {
void GLCanvas::throttleRender() {
_frameTimer.start(_idleRenderInterval);
if (!Application::getInstance()->getWindow()->isMinimized()) {
//Need accurate frame timing for the oculus rift
if (OculusManager::isConnected()) {
OculusManager::beginFrameTiming();
}
makeCurrent();
Application::getInstance()->paintGL();
swapBuffers();
if (OculusManager::isConnected()) {
OculusManager::endFrameTiming();
}
}
}

View file

@ -15,6 +15,7 @@
#include <GLCanvas.h>
#include <PathUtils.h>
#include <GeometryCache.h>
#include <gpu/GLBackend.h>
#include "Application.h"
#include "AudioToolBox.h"
@ -38,15 +39,14 @@ bool AudioToolBox::mousePressEvent(int x, int y) {
void AudioToolBox::render(int x, int y, int padding, bool boxed) {
glEnable(GL_TEXTURE_2D);
auto glCanvas = Application::getInstance()->getGLWidget();
if (_micTextureId == 0) {
_micTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/mic.svg"));
if (!_micTexture) {
_micTexture = DependencyManager::get<TextureCache>()->getImageTexture(PathUtils::resourcesPath() + "images/mic.svg");
}
if (_muteTextureId == 0) {
_muteTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/mic-mute.svg"));
if (!_muteTexture) {
_muteTexture = DependencyManager::get<TextureCache>()->getImageTexture(PathUtils::resourcesPath() + "images/mic-mute.svg");
}
if (_boxTextureId == 0) {
_boxTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/audio-box.svg"));
if (_boxTexture) {
_boxTexture = DependencyManager::get<TextureCache>()->getImageTexture(PathUtils::resourcesPath() + "images/audio-box.svg");
}
auto audioIO = DependencyManager::get<AudioClient>();
@ -59,11 +59,8 @@ void AudioToolBox::render(int x, int y, int padding, bool boxed) {
const int BOX_HEIGHT = 44;
QRect boxBounds = QRect(x - BOX_LEFT_PADDING, y - BOX_TOP_PADDING, BOX_WIDTH, BOX_HEIGHT);
glBindTexture(GL_TEXTURE_2D, _boxTextureId);
glm::vec4 quadColor;
if (isClipping) {
quadColor = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
} else {
@ -71,9 +68,9 @@ void AudioToolBox::render(int x, int y, int padding, bool boxed) {
}
glm::vec2 topLeft(boxBounds.left(), boxBounds.top());
glm::vec2 bottomRight(boxBounds.right(), boxBounds.bottom());
glm::vec2 texCoordTopLeft(1,1);
glm::vec2 texCoordBottomRight(0,0);
static const glm::vec2 texCoordTopLeft(1,1);
static const glm::vec2 texCoordBottomRight(0, 0);
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_boxTexture));
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor);
}
@ -81,10 +78,10 @@ void AudioToolBox::render(int x, int y, int padding, bool boxed) {
_iconBounds = QRect(x + padding, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE);
if (!audioIO->isMuted()) {
glBindTexture(GL_TEXTURE_2D, _micTextureId);
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_micTexture));
iconColor = 1.0f;
} else {
glBindTexture(GL_TEXTURE_2D, _muteTextureId);
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_muteTexture));
// Make muted icon pulsate
static const float PULSE_MIN = 0.4f;
@ -112,6 +109,6 @@ void AudioToolBox::render(int x, int y, int padding, bool boxed) {
}
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor, _boxQuadID);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}

View file

@ -14,6 +14,7 @@
#include <DependencyManager.h>
#include <GeometryCache.h>
#include <QOpenGLTexture>
class AudioToolBox : public Dependency {
SINGLETON_DEPENDENCY
@ -24,9 +25,9 @@ public:
protected:
AudioToolBox();
private:
GLuint _micTextureId = 0;
GLuint _muteTextureId = 0;
GLuint _boxTextureId = 0;
gpu::TexturePointer _micTexture;
gpu::TexturePointer _muteTexture;
gpu::TexturePointer _boxTexture;
int _boxQuadID = GeometryCache::UNKNOWN_ID;
QRect _iconBounds;
qint64 _iconPulseTimeReference = 0;

View file

@ -46,7 +46,6 @@
#include "Recorder.h"
#include "Util.h"
#include "world.h"
#include "devices/OculusManager.h"
#include "InterfaceLogging.h"
using namespace std;

View file

@ -22,7 +22,6 @@
#include "Util.h"
#include "devices/DdeFaceTracker.h"
#include "devices/Faceshift.h"
#include "devices/OculusManager.h"
using namespace std;
@ -309,7 +308,7 @@ glm::quat Head::getCameraOrientation() const {
// to change the driving direction while in Oculus mode. It is used to support driving toward where you're
// head is looking. Note that in oculus mode, your actual camera view and where your head is looking is not
// always the same.
if (OculusManager::isConnected()) {
if (qApp->isHMDMode()) {
return getOrientation();
}
Avatar* owningAvatar = static_cast<Avatar*>(_owningAvatar);

View file

@ -42,7 +42,6 @@
#include "Physics.h"
#include "Recorder.h"
#include "devices/Faceshift.h"
#include "devices/OculusManager.h"
#include "Util.h"
#include "InterfaceLogging.h"
@ -230,12 +229,14 @@ void MyAvatar::simulate(float deltaTime) {
void MyAvatar::updateFromTrackers(float deltaTime) {
glm::vec3 estimatedPosition, estimatedRotation;
if (isPlaying() && !OculusManager::isConnected()) {
bool inHmd = qApp->isHMDMode();
if (isPlaying() && inHmd) {
return;
}
if (OculusManager::isConnected()) {
estimatedPosition = OculusManager::getRelativePosition();
if (inHmd) {
estimatedPosition = qApp->getHeadPosition();
estimatedPosition.x *= -1.0f;
_trackedHeadPosition = estimatedPosition;
@ -273,7 +274,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
Head* head = getHead();
if (OculusManager::isConnected() || isPlaying()) {
if (inHmd || isPlaying()) {
head->setDeltaPitch(estimatedRotation.x);
head->setDeltaYaw(estimatedRotation.y);
} else {
@ -293,7 +294,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
// NOTE: this is kinda a hack, it's the same hack we use to make the head tilt. But it's not really a mirror
// it just makes you feel like you're looking in a mirror because the body movements of the avatar appear to
// match your body movements.
if (OculusManager::isConnected() && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) {
if (inHmd && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) {
relativePosition.x = -relativePosition.x;
}
@ -882,8 +883,10 @@ void MyAvatar::updateLookAtTargetAvatar() {
howManyLookingAtMe++;
// Have that avatar look directly at my camera
// Philip TODO: correct to look at left/right eye
if (OculusManager::isConnected()) {
avatar->getHead()->setCorrectedLookAtPosition(OculusManager::getLeftEyePosition());
if (qApp->isHMDMode()) {
avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition());
// FIXME what is the point of this?
// avatar->getHead()->setCorrectedLookAtPosition(OculusManager::getLeftEyePosition());
} else {
avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition());
}
@ -1213,7 +1216,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
// Gather rotation information from keyboard
const float TIME_BETWEEN_HMD_TURNS = 0.5f;
const float HMD_TURN_DEGREES = 22.5f;
if (!OculusManager::isConnected()) {
if (!qApp->isHMDMode()) {
// Smoothly rotate body with arrow keys if not in HMD
_bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime;
_bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime;
@ -1247,29 +1250,23 @@ void MyAvatar::updateOrientation(float deltaTime) {
float MINIMUM_ROTATION_RATE = 2.0f;
if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.0f; }
if (OculusManager::isConnected()) {
if (qApp->isHMDMode()) {
// these angles will be in radians
float yaw, pitch, roll;
OculusManager::getEulerAngles(yaw, pitch, roll);
glm::quat orientation = qApp->getHeadOrientation();
// ... so they need to be converted to degrees before we do math...
yaw *= DEGREES_PER_RADIAN;
pitch *= DEGREES_PER_RADIAN;
roll *= DEGREES_PER_RADIAN;
glm::vec3 euler = glm::eulerAngles(orientation) * DEGREES_PER_RADIAN;
//Invert yaw and roll when in mirror mode
Head* head = getHead();
if (Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) {
head->setBaseYaw(-yaw);
head->setBasePitch(pitch);
head->setBaseRoll(-roll);
} else {
head->setBaseYaw(yaw);
head->setBasePitch(pitch);
head->setBaseRoll(roll);
YAW(euler) *= -1.0;
ROLL(euler) *= -1.0;
}
Head* head = getHead();
head->setBaseYaw(YAW(euler));
head->setBasePitch(PITCH(euler));
head->setBaseRoll(ROLL(euler));
}
}
glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVelocity, bool isHovering) {

View file

@ -14,6 +14,7 @@
#include <GLCanvas.h>
#include <PathUtils.h>
#include "gpu/GLBackend.h"
#include "Application.h"
#include "CameraToolBox.h"
#include "FaceTracker.h"
@ -74,21 +75,20 @@ void CameraToolBox::toggleMute() {
void CameraToolBox::render(int x, int y, bool boxed) {
glEnable(GL_TEXTURE_2D);
auto glCanvas = Application::getInstance()->getGLWidget();
if (_enabledTextureId == 0) {
_enabledTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/face.svg"));
if (!_enabledTexture) {
_enabledTexture = DependencyManager::get<TextureCache>()->getImageTexture(PathUtils::resourcesPath() + "images/face.svg");
}
if (_mutedTextureId == 0) {
_mutedTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/face-mute.svg"));
if (!_mutedTexture) {
_mutedTexture = DependencyManager::get<TextureCache>()->getImageTexture(PathUtils::resourcesPath() + "images/face-mute.svg");
}
const int MUTE_ICON_SIZE = 24;
_iconBounds = QRect(x, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE);
float iconColor = 1.0f;
if (!Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking)) {
glBindTexture(GL_TEXTURE_2D, _enabledTextureId);
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_enabledTexture));
} else {
glBindTexture(GL_TEXTURE_2D, _mutedTextureId);
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_mutedTexture));
// Make muted icon pulsate
static const float PULSE_MIN = 0.4f;

View file

@ -34,8 +34,8 @@ private slots:
void toggleMute();
private:
GLuint _enabledTextureId = 0;
GLuint _mutedTextureId = 0;
gpu::TexturePointer _enabledTexture;
gpu::TexturePointer _mutedTexture;
int _boxQuadID = GeometryCache::UNKNOWN_ID;
QRect _iconBounds;
qint64 _iconPulseTimeReference = 0;

View file

@ -455,8 +455,7 @@ void OculusManager::configureCamera(Camera& camera, int screenWidth, int screenH
}
//Displays everything for the oculus, frame timing must be active
void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera) {
auto glCanvas = Application::getInstance()->getGLWidget();
void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera) {
#ifdef DEBUG
// Ensure the frame counter always increments by exactly 1
@ -617,7 +616,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
_camera->setEyeOffsetPosition(glm::vec3(-_eyeRenderDesc[eye].HmdToEyeViewOffset.x, -_eyeRenderDesc[eye].HmdToEyeViewOffset.y, -_eyeRenderDesc[eye].HmdToEyeViewOffset.z));
Application::getInstance()->displaySide(*_camera, false, RenderArgs::MONO);
applicationOverlay.displayOverlayTextureOculus(*_camera);
applicationOverlay.displayOverlayTextureHmd(*_camera);
});
_activeEye = ovrEye_Count;
@ -638,7 +637,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
glPopMatrix();
// restore our normal viewport
glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight());
auto deviceSize = qApp->getDeviceSize();
glViewport(0, 0, deviceSize.width(), deviceSize.height());
#if 0
if (debugFrame && !timerActive) {
@ -707,8 +707,8 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
void OculusManager::renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]) {
glLoadIdentity();
auto glCanvas = Application::getInstance()->getGLWidget();
glOrtho(0, glCanvas->getDeviceWidth(), 0, glCanvas->getDeviceHeight(), -1.0, 1.0);
auto deviceSize = qApp->getDeviceSize();
glOrtho(0, deviceSize.width(), 0, deviceSize.height(), -1.0, 1.0);
glDisable(GL_DEPTH_TEST);
@ -794,8 +794,12 @@ void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
glm::vec3 OculusManager::getRelativePosition() {
ovrTrackingState trackingState = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds());
ovrVector3f headPosition = trackingState.HeadPose.ThePose.Position;
return glm::vec3(headPosition.x, headPosition.y, headPosition.z);
return toGlm(trackingState.HeadPose.ThePose.Position);
}
glm::quat OculusManager::getOrientation() {
ovrTrackingState trackingState = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds());
return toGlm(trackingState.HeadPose.ThePose.Orientation);
}
//Used to set the size of the glow framebuffers

View file

@ -61,7 +61,7 @@ public:
static void endFrameTiming();
static bool allowSwap();
static void configureCamera(Camera& camera, int screenWidth, int screenHeight);
static void display(const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera);
static void display(QGLWidget * glCanvas, const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera);
static void reset();
/// param \yaw[out] yaw in radians
@ -69,6 +69,7 @@ public:
/// param \roll[out] roll in radians
static void getEulerAngles(float& yaw, float& pitch, float& roll);
static glm::vec3 getRelativePosition();
static glm::quat getOrientation();
static QSize getRenderTargetSize();
static void overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal,

View file

@ -16,7 +16,6 @@
#include "Application.h"
#include "SixenseManager.h"
#include "devices/OculusManager.h"
#include "UserActivityLogger.h"
#include "InterfaceLogging.h"
@ -473,7 +472,6 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers)
//Injecting mouse movements and clicks
void SixenseManager::emulateMouse(PalmData* palm, int index) {
MyAvatar* avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto glCanvas = Application::getInstance()->getGLWidget();
QPoint pos;
Qt::MouseButton bumperButton;
@ -499,12 +497,12 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) {
// Get the angles, scaled between (-0.5,0.5)
float xAngle = (atan2(direction.z, direction.x) + M_PI_2);
float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2));
auto canvasSize = qApp->getCanvasSize();
// Get the pixel range over which the xAngle and yAngle are scaled
float cursorRange = glCanvas->width() * getCursorPixelRangeMult();
float cursorRange = canvasSize.x * getCursorPixelRangeMult();
pos.setX(glCanvas->width() / 2.0f + cursorRange * xAngle);
pos.setY(glCanvas->height() / 2.0f + cursorRange * yAngle);
pos.setX(canvasSize.x / 2.0f + cursorRange * xAngle);
pos.setY(canvasSize.y / 2.0f + cursorRange * yAngle);
}

View file

@ -33,12 +33,8 @@ bool TV3DManager::isConnected() {
}
void TV3DManager::connect() {
auto glCanvas = Application::getInstance()->getGLWidget();
int width = glCanvas->getDeviceWidth();
int height = glCanvas->getDeviceHeight();
Camera& camera = *Application::getInstance()->getCamera();
configureCamera(camera, width, height);
auto deviceSize = qApp->getDeviceSize();
configureCamera(*(qApp->getCamera()), deviceSize.width(), deviceSize.height());
}
@ -91,9 +87,8 @@ void TV3DManager::display(Camera& whichCamera) {
// left eye portal
int portalX = 0;
int portalY = 0;
auto glCanvas = Application::getInstance()->getGLWidget();
QSize deviceSize = glCanvas->getDeviceSize() *
Application::getInstance()->getRenderResolutionScale();
QSize deviceSize = qApp->getDeviceSize() *
qApp->getRenderResolutionScale();
int portalW = deviceSize.width() / 2;
int portalH = deviceSize.height();
@ -122,8 +117,9 @@ void TV3DManager::display(Camera& whichCamera) {
glLoadIdentity(); // reset projection matrix
glFrustum(_leftEye.left, _leftEye.right, _leftEye.bottom, _leftEye.top, nearZ, farZ); // set left view frustum
GLfloat p[4][4];
// Really?
glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0]));
GLfloat cotangent = p[1][1];
float cotangent = p[1][1];
GLfloat fov = atan(1.0f / cotangent);
glTranslatef(_leftEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
@ -132,7 +128,7 @@ void TV3DManager::display(Camera& whichCamera) {
eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0));
Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO);
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
applicationOverlay.displayOverlayTextureStereo(whichCamera, _aspect, fov);
_activeEye = NULL;
}
glPopMatrix();
@ -161,7 +157,7 @@ void TV3DManager::display(Camera& whichCamera) {
eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0));
Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO);
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
applicationOverlay.displayOverlayTextureStereo(whichCamera, _aspect, fov);
_activeEye = NULL;
}
glPopMatrix();

View file

@ -18,7 +18,6 @@
#include "AddressManager.h"
#include "Application.h"
#include "devices/OculusManager.h"
#include "InterfaceLogging.h"
#ifdef Q_OS_WIN
@ -97,8 +96,8 @@ int main(int argc, const char* argv[]) {
// Oculus initialization MUST PRECEDE OpenGL context creation.
// The nature of the Application constructor means this has to be either here,
// or in the main window ctor, before GL startup.
OculusManager::init();
Application::initPlugins();
int exitCode;
{
QSettings::setDefaultFormat(QSettings::IniFormat);
@ -112,7 +111,7 @@ int main(int argc, const char* argv[]) {
exitCode = app.exec();
}
OculusManager::deinit();
Application::shutdownPlugins();
#ifdef Q_OS_WIN
ReleaseMutex(mutex);
#endif

View file

@ -286,8 +286,7 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) {
}
glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
auto glCanvas = Application::getInstance()->getGLWidget();
return glm::vec2(glCanvas->width(), glCanvas->height());
return Application::getInstance()->getCanvasSize();
}
AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) {

View file

@ -15,7 +15,6 @@
#include <GLMHelpers.h>
#include "Application.h"
#include "devices/OculusManager.h"
class HMDScriptingInterface : public QObject {
Q_OBJECT

View file

@ -41,7 +41,7 @@ WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title
}
QScriptValue WindowScriptingInterface::hasFocus() {
return Application::getInstance()->getGLWidget()->hasFocus();
return Application::getInstance()->hasFocus();
}
void WindowScriptingInterface::setFocus() {

View file

@ -12,10 +12,13 @@
#include "InterfaceConfig.h"
#include <QOpenGLFramebufferObject>
#include <QOpenGLTexture>
#include <avatar/AvatarManager.h>
#include <GLMHelpers.h>
#include <PathUtils.h>
#include <gpu/GLBackend.h>
#include <GLMHelpers.h>
#include <PerfStat.h>
#include <OffscreenUi.h>
@ -26,7 +29,6 @@
#include "Application.h"
#include "ApplicationOverlay.h"
#include "devices/CameraToolBox.h"
#include "devices/OculusManager.h"
#include "Util.h"
#include "ui/Stats.h"
@ -46,7 +48,7 @@ const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f;
static const float MOUSE_PITCH_RANGE = 1.0f * PI;
static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI;
static const glm::vec2 MOUSE_RANGE(MOUSE_YAW_RANGE, MOUSE_PITCH_RANGE);
// Return a point's cartesian coordinates on a sphere from pitch and yaw
glm::vec3 getPoint(float yaw, float pitch) {
@ -134,7 +136,7 @@ void ApplicationOverlay::renderReticle(glm::quat orientation, float alpha) {
}
ApplicationOverlay::ApplicationOverlay() :
_textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)),
_textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)),
_textureAspectRatio(1.0f),
_lastMouseMove(0),
_magnifier(true),
@ -186,10 +188,10 @@ ApplicationOverlay::~ApplicationOverlay() {
void ApplicationOverlay::renderOverlay() {
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()");
Overlays& overlays = qApp->getOverlays();
auto glCanvas = Application::getInstance()->getGLWidget();
_textureFov = glm::radians(_oculusUIAngularSize);
_textureAspectRatio = (float)glCanvas->getDeviceWidth() / (float)glCanvas->getDeviceHeight();
_textureFov = glm::radians(_hmdUIAngularSize);
auto deviceSize = Application::getInstance()->getDeviceSize();
_textureAspectRatio = (float)deviceSize.width() / (float)deviceSize.height();
//Handle fading and deactivation/activation of UI
@ -202,12 +204,12 @@ void ApplicationOverlay::renderOverlay() {
_overlays.buildFramebufferObject();
_overlays.bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix(); {
const float NEAR_CLIP = -10000;
const float FAR_CLIP = 10000;
glLoadIdentity();
glOrtho(0, glCanvas->width(), glCanvas->height(), 0, NEAR_CLIP, FAR_CLIP);
glOrtho(0, deviceSize.width(), deviceSize.height(), 0, NEAR_CLIP, FAR_CLIP);
glMatrixMode(GL_MODELVIEW);
@ -280,7 +282,7 @@ void ApplicationOverlay::displayOverlayTexture() {
}
// Draws the FBO texture for Oculus rift.
void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) {
if (_alpha == 0.0f) {
return;
}
@ -358,7 +360,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
}
// Draws the FBO texture for 3DTV.
void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov) {
void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov) {
if (_alpha == 0.0f) {
return;
}
@ -413,19 +415,19 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as
overlayColor);
});
auto glCanvas = Application::getInstance()->getGLWidget();
if (_crosshairTexture == 0) {
_crosshairTexture = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png"));
if (!_crosshairTexture) {
_crosshairTexture = DependencyManager::get<TextureCache>()->
getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
}
//draw the mouse pointer
glBindTexture(GL_TEXTURE_2D, _crosshairTexture);
const float reticleSize = 40.0f / glCanvas->width() * quadWidth;
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
glm::vec2 canvasSize = qApp->getCanvasSize();
const float reticleSize = 40.0f / canvasSize.x * quadWidth;
x -= reticleSize / 2.0f;
y += reticleSize / 2.0f;
const float mouseX = (qApp->getMouseX() / (float)glCanvas->width()) * quadWidth;
const float mouseY = (1.0 - (qApp->getMouseY() / (float)glCanvas->height())) * quadHeight;
const float mouseX = (qApp->getMouseX() / (float)canvasSize.x) * quadWidth;
const float mouseY = (1.0 - (qApp->getMouseY() / (float)canvasSize.y)) * quadHeight;
glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f };
@ -449,24 +451,23 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as
glEnable(GL_LIGHTING);
}
void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const {
void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) {
const MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
const float pitch = (0.5f - y) * MOUSE_PITCH_RANGE;
const float yaw = (0.5f - x) * MOUSE_YAW_RANGE;
const glm::quat orientation(glm::vec3(pitch, yaw, 0.0f));
cursorPos = 0.5f - cursorPos;
cursorPos *= MOUSE_RANGE;
const glm::quat orientation(glm::vec3(cursorPos, 0.0f));
const glm::vec3 localDirection = orientation * IDENTITY_FRONT;
// Get cursor position
const glm::vec3 cursorPos = myAvatar->getDefaultEyePosition() + myAvatar->getOrientation() * localDirection;
const glm::vec3 cursorDir = myAvatar->getDefaultEyePosition() + myAvatar->getOrientation() * localDirection;
// Ray start where the eye position is and stop where the cursor is
origin = myAvatar->getEyePosition();
direction = cursorPos - origin;
direction = cursorDir - origin;
}
//Caculate the click location using one of the sixense controllers. Scale is not applied
QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
auto glCanvas = Application::getInstance()->getGLWidget();
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm);
@ -477,8 +478,8 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
glm::vec3 tipPos = invOrientation * (tip - eyePos);
QPoint rv;
if (OculusManager::isConnected()) {
auto canvasSize = qApp->getCanvasSize();
if (qApp->isHMDMode()) {
float t;
//We back the ray up by dir to ensure that it will not start inside the UI.
@ -497,8 +498,8 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
float u = asin(collisionPos.x) / (_textureFov)+0.5f;
float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f);
rv.setX(u * glCanvas->width());
rv.setY(v * glCanvas->height());
rv.setX(u * canvasSize.x);
rv.setY(v * canvasSize.y);
}
} else {
//if they did not click on the overlay, just set the coords to INT_MAX
@ -515,8 +516,8 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
ndcSpacePos = glm::vec3(clipSpacePos) / clipSpacePos.w;
}
rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * glCanvas->width());
rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * glCanvas->height());
rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * canvasSize.x);
rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * canvasSize.y);
}
return rv;
}
@ -541,18 +542,17 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position,
//Renders optional pointers
void ApplicationOverlay::renderPointers() {
auto glCanvas = Application::getInstance()->getGLWidget();
//lazily load crosshair texture
if (_crosshairTexture == 0) {
_crosshairTexture = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png"));
_crosshairTexture = DependencyManager::get<TextureCache>()->
getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
}
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _crosshairTexture);
if (OculusManager::isConnected() && !qApp->getLastMouseMoveWasSimulated() && !qApp->isMouseHidden()) {
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
if (qApp->isHMDMode() && !qApp->getLastMouseMoveWasSimulated() && !qApp->isMouseHidden()) {
//If we are in oculus, render reticle later
if (_lastMouseMove == 0) {
_lastMouseMove = usecTimestampNow();
@ -563,9 +563,9 @@ void ApplicationOverlay::renderPointers() {
if (_reticlePosition[MOUSE] != position) {
_lastMouseMove = usecTimestampNow();
} else if (usecTimestampNow() - _lastMouseMove > MAX_IDLE_TIME * USECS_PER_SECOND) {
float pitch = 0.0f, yaw = 0.0f, roll = 0.0f; // radians
OculusManager::getEulerAngles(yaw, pitch, roll);
glm::quat orientation(glm::vec3(pitch, yaw, roll));
//float pitch = 0.0f, yaw = 0.0f, roll = 0.0f; // radians
//OculusManager::getEulerAngles(yaw, pitch, roll);
glm::quat orientation = qApp->getHeadOrientation(); // (glm::vec3(pitch, yaw, roll));
glm::vec3 result;
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
@ -576,7 +576,8 @@ void ApplicationOverlay::renderPointers() {
glm::vec2 spericalPos = directionToSpherical(glm::normalize(lookAtDirection));
glm::vec2 screenPos = sphericalToScreen(spericalPos);
position = QPoint(screenPos.x, screenPos.y);
glCanvas->cursor().setPos(glCanvas->mapToGlobal(position));
// FIXME
//glCanvas->cursor().setPos(glCanvas->mapToGlobal(position));
} else {
qDebug() << "No collision point";
}
@ -599,7 +600,6 @@ void ApplicationOverlay::renderPointers() {
}
void ApplicationOverlay::renderControllerPointers() {
auto glCanvas = Application::getInstance()->getGLWidget();
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
//Static variables used for storing controller state
@ -648,7 +648,7 @@ void ApplicationOverlay::renderControllerPointers() {
//if we have the oculus, we should make the cursor smaller since it will be
//magnified
if (OculusManager::isConnected()) {
if (qApp->isHMDMode()) {
QPoint point = getPalmClickLocation(palmData);
@ -663,6 +663,7 @@ void ApplicationOverlay::renderControllerPointers() {
continue;
}
auto canvasSize = qApp->getCanvasSize();
int mouseX, mouseY;
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {
QPoint res = getPalmClickLocation(palmData);
@ -677,14 +678,14 @@ void ApplicationOverlay::renderControllerPointers() {
float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2));
// Get the pixel range over which the xAngle and yAngle are scaled
float cursorRange = glCanvas->width() * SixenseManager::getInstance().getCursorPixelRangeMult();
float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult();
mouseX = (glCanvas->width() / 2.0f + cursorRange * xAngle);
mouseY = (glCanvas->height() / 2.0f + cursorRange * yAngle);
mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle);
mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle);
}
//If the cursor is out of the screen then don't render it
if (mouseX < 0 || mouseX >= glCanvas->width() || mouseY < 0 || mouseY >= glCanvas->height()) {
if (mouseX < 0 || mouseX >= canvasSize.x || mouseY < 0 || mouseY >= canvasSize.y) {
_reticleActive[index] = false;
continue;
}
@ -709,7 +710,7 @@ void ApplicationOverlay::renderControllerPointers() {
}
void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) {
glBindTexture(GL_TEXTURE_2D, _crosshairTexture);
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
@ -746,10 +747,10 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool
if (!_magnifier) {
return;
}
auto glCanvas = Application::getInstance()->getGLWidget();
auto canvasSize = qApp->getCanvasSize();
const int widgetWidth = glCanvas->width();
const int widgetHeight = glCanvas->height();
const int widgetWidth = canvasSize.x;
const int widgetHeight = canvasSize.y;
const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f;
const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f;
@ -819,7 +820,7 @@ void ApplicationOverlay::renderCameraToggle() {
}
int audioMeterY;
bool smallMirrorVisible = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !OculusManager::isConnected();
bool smallMirrorVisible = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !qApp->isHMDMode();
bool boxed = smallMirrorVisible &&
!Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror);
if (boxed) {
@ -832,7 +833,6 @@ void ApplicationOverlay::renderCameraToggle() {
}
void ApplicationOverlay::renderAudioMeter() {
auto glCanvas = Application::getInstance()->getGLWidget();
auto audio = DependencyManager::get<AudioClient>();
// Audio VU Meter and Mute Icon
@ -852,7 +852,7 @@ void ApplicationOverlay::renderAudioMeter() {
}
int audioMeterY;
bool smallMirrorVisible = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !OculusManager::isConnected();
bool smallMirrorVisible = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !qApp->isHMDMode();
bool boxed = smallMirrorVisible &&
!Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror);
if (boxed) {
@ -887,16 +887,17 @@ void ApplicationOverlay::renderAudioMeter() {
}
bool isClipping = ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME));
auto canvasSize = qApp->getCanvasSize();
if ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) {
const float MAX_MAGNITUDE = 0.7f;
float magnitude = MAX_MAGNITUDE * (1 - audio->getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME);
renderCollisionOverlay(glCanvas->width(), glCanvas->height(), magnitude, 1.0f);
renderCollisionOverlay(canvasSize.x, canvasSize.y, magnitude, 1.0f);
}
DependencyManager::get<AudioToolBox>()->render(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, cameraSpace, boxed);
DependencyManager::get<AudioScope>()->render(glCanvas->width(), glCanvas->height());
DependencyManager::get<AudioIOStatsRenderer>()->render(WHITE_TEXT, glCanvas->width(), glCanvas->height());
DependencyManager::get<AudioScope>()->render(canvasSize.x, canvasSize.y);
DependencyManager::get<AudioIOStatsRenderer>()->render(WHITE_TEXT, canvasSize.x, canvasSize.y);
audioMeterY += AUDIO_METER_HEIGHT;
@ -957,7 +958,6 @@ void ApplicationOverlay::renderStatsAndLogs() {
Application* application = Application::getInstance();
QSharedPointer<BandwidthRecorder> bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
auto glCanvas = Application::getInstance()->getGLWidget();
const OctreePacketProcessor& octreePacketProcessor = application->getOctreePacketProcessor();
NodeBounds& nodeBoundsDisplay = application->getNodeBoundsDisplay();
@ -980,12 +980,13 @@ void ApplicationOverlay::renderStatsAndLogs() {
// Show on-screen msec timer
if (Menu::getInstance()->isOptionChecked(MenuOption::FrameTimer)) {
auto canvasSize = qApp->getCanvasSize();
quint64 mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5);
QString frameTimer = QString("%1\n").arg((int)(mSecsNow % 1000));
int timerBottom =
(Menu::getInstance()->isOptionChecked(MenuOption::Stats))
? 80 : 20;
drawText(glCanvas->width() - 100, glCanvas->height() - timerBottom,
drawText(canvasSize.x - 100, canvasSize.y - timerBottom,
0.30f, 0.0f, 0, frameTimer.toUtf8().constData(), WHITE_TEXT);
}
nodeBoundsDisplay.drawOverlay();
@ -995,25 +996,22 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() {
auto nodeList = DependencyManager::get<NodeList>();
if (nodeList && !nodeList->getDomainHandler().isConnected()) {
auto glCanvas = Application::getInstance()->getGLWidget();
auto geometryCache = DependencyManager::get<GeometryCache>();
int width = glCanvas->width();
int height = glCanvas->height();
if (width != _previousBorderWidth || height != _previousBorderHeight) {
auto canvasSize = qApp->getCanvasSize();
if (canvasSize.x != _previousBorderWidth || canvasSize.y != _previousBorderHeight) {
glm::vec4 color(CONNECTION_STATUS_BORDER_COLOR[0],
CONNECTION_STATUS_BORDER_COLOR[1],
CONNECTION_STATUS_BORDER_COLOR[2], 1.0f);
QVector<glm::vec2> border;
border << glm::vec2(0, 0);
border << glm::vec2(0, height);
border << glm::vec2(width, height);
border << glm::vec2(width, 0);
border << glm::vec2(0, canvasSize.y);
border << glm::vec2(canvasSize.x, canvasSize.y);
border << glm::vec2(canvasSize.x, 0);
border << glm::vec2(0, 0);
geometryCache->updateVertices(_domainStatusBorder, border, color);
_previousBorderWidth = width;
_previousBorderHeight = height;
_previousBorderWidth = canvasSize.x;
_previousBorderHeight = canvasSize.y;
}
glLineWidth(CONNECTION_STATUS_BORDER_LINE_WIDTH);
@ -1131,8 +1129,8 @@ void ApplicationOverlay::TexturedHemisphere::cleanupVBO() {
}
void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() {
QSize size = Application::getInstance()->getGLWidget()->getDeviceSize();
if (_framebufferObject != NULL && size == _framebufferObject->size()) {
auto deviceSize = qApp->getDeviceSize();
if (_framebufferObject != NULL && deviceSize == _framebufferObject->size()) {
// Already build
return;
}
@ -1141,7 +1139,7 @@ void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() {
delete _framebufferObject;
}
_framebufferObject = new QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::Depth);
_framebufferObject = new QOpenGLFramebufferObject(deviceSize, QOpenGLFramebufferObject::Depth);
glBindTexture(GL_TEXTURE_2D, getTexture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -1184,7 +1182,7 @@ GLuint ApplicationOverlay::TexturedHemisphere::getTexture() {
return _framebufferObject->texture();
}
glm::vec2 ApplicationOverlay::directionToSpherical(glm::vec3 direction) const {
glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) {
glm::vec2 result;
// Compute yaw
glm::vec3 normalProjection = glm::normalize(glm::vec3(direction.x, 0.0f, direction.z));
@ -1200,47 +1198,57 @@ glm::vec2 ApplicationOverlay::directionToSpherical(glm::vec3 direction) const {
return result;
}
glm::vec3 ApplicationOverlay::sphericalToDirection(glm::vec2 sphericalPos) const {
glm::vec3 ApplicationOverlay::sphericalToDirection(const glm::vec2& sphericalPos) {
glm::quat rotation(glm::vec3(sphericalPos.y, sphericalPos.x, 0.0f));
return rotation * IDENTITY_FRONT;
}
glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const {
QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize();
float yaw = -(screenPos.x / screenSize.width() - 0.5f) * MOUSE_YAW_RANGE;
float pitch = (screenPos.y / screenSize.height() - 0.5f) * MOUSE_PITCH_RANGE;
glm::vec2 ApplicationOverlay::screenToSpherical(const glm::vec2& screenPos) {
auto screenSize = qApp->getCanvasSize();
glm::vec2 result;
result.x = -(screenPos.x / screenSize.x - 0.5f);
result.y = (screenPos.y / screenSize.y - 0.5f);
result.x *= MOUSE_YAW_RANGE;
result.y *= MOUSE_PITCH_RANGE;
return glm::vec2(yaw, pitch);
return result;
}
glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const {
QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize();
float x = (-sphericalPos.x / MOUSE_YAW_RANGE + 0.5f) * screenSize.width();
float y = (sphericalPos.y / MOUSE_PITCH_RANGE + 0.5f) * screenSize.height();
return glm::vec2(x, y);
glm::vec2 ApplicationOverlay::sphericalToScreen(const glm::vec2& sphericalPos) {
glm::vec2 result = sphericalPos;
result.x *= -1.0;
result /= MOUSE_RANGE;
result += 0.5f;
result *= qApp->getCanvasSize();
return result;
}
glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const {
QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize();
float x = (-sphericalPos.x / (_textureFov * _textureAspectRatio) + 0.5f) * screenSize.width();
float y = (sphericalPos.y / _textureFov + 0.5f) * screenSize.height();
return glm::vec2(x, y);
glm::vec2 ApplicationOverlay::sphericalToOverlay(const glm::vec2& sphericalPos) const {
glm::vec2 result = sphericalPos;
result.x *= -1.0;
result /= _textureFov;
result.x /= _textureAspectRatio;
result += 0.5f;
result.x = (-sphericalPos.x / (_textureFov * _textureAspectRatio) + 0.5f);
result.y = (sphericalPos.y / _textureFov + 0.5f);
result *= qApp->getCanvasSize();
return result;
}
glm::vec2 ApplicationOverlay::overlayToSpherical(glm::vec2 overlayPos) const {
QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize();
float yaw = -(overlayPos.x / screenSize.width() - 0.5f) * _textureFov * _textureAspectRatio;
float pitch = (overlayPos.y / screenSize.height() - 0.5f) * _textureFov;
return glm::vec2(yaw, pitch);
glm::vec2 ApplicationOverlay::overlayToSpherical(const glm::vec2& overlayPos) const {
glm::vec2 result = overlayPos;
result.x *= -1.0;
result /= qApp->getCanvasSize();
result -= 0.5f;
result *= _textureFov;
result.x *= _textureAspectRatio;
return result;
}
glm::vec2 ApplicationOverlay::screenToOverlay(glm::vec2 screenPos) const {
glm::vec2 ApplicationOverlay::screenToOverlay(const glm::vec2& screenPos) const {
return sphericalToOverlay(screenToSpherical(screenPos));
}
glm::vec2 ApplicationOverlay::overlayToScreen(glm::vec2 overlayPos) const {
glm::vec2 ApplicationOverlay::overlayToScreen(const glm::vec2& overlayPos) const {
return sphericalToScreen(overlayToSpherical(overlayPos));
}

View file

@ -12,6 +12,7 @@
#ifndef hifi_ApplicationOverlay_h
#define hifi_ApplicationOverlay_h
#include <gpu/Texture.h>
class Camera;
class Overlays;
class QOpenGLFramebufferObject;
@ -20,9 +21,11 @@ const float MAGNIFY_WIDTH = 220.0f;
const float MAGNIFY_HEIGHT = 100.0f;
const float MAGNIFY_MULT = 2.0f;
const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f;
const float DEFAULT_HMD_UI_ANGULAR_SIZE = 72.0f;
// Handles the drawing of the overlays to the screen
// TODO, move divide up the rendering, displaying and input handling
// facilities of this class
class ApplicationOverlay : public QObject {
Q_OBJECT
public:
@ -31,19 +34,18 @@ public:
void renderOverlay();
void displayOverlayTexture();
void displayOverlayTextureOculus(Camera& whichCamera);
void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov);
void computeOculusPickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const;
void displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov);
void displayOverlayTextureHmd(Camera& whichCamera);
QPoint getPalmClickLocation(const PalmData *palm) const;
bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const;
bool hasMagnifier() const { return _magnifier; }
void toggleMagnifier() { _magnifier = !_magnifier; }
float getOculusUIAngularSize() const { return _oculusUIAngularSize; }
void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; }
float getHmdUIAngularSize() const { return _hmdUIAngularSize; }
void setHmdUIAngularSize(float hmdUIAngularSize) { _hmdUIAngularSize = hmdUIAngularSize; }
// Converter from one frame of reference to another.
// Frame of reference:
// Direction: Ray that represents the spherical values
@ -52,14 +54,16 @@ public:
// Overlay: Position on the overlay (x,y)
// (x,y) in Overlay are similar than (x,y) in Screen except they can be outside of the bound of te screen.
// This allows for picking outside of the screen projection in 3D.
glm::vec2 directionToSpherical(glm::vec3 direction) const;
glm::vec3 sphericalToDirection(glm::vec2 sphericalPos) const;
glm::vec2 screenToSpherical(glm::vec2 screenPos) const;
glm::vec2 sphericalToScreen(glm::vec2 sphericalPos) const;
glm::vec2 sphericalToOverlay(glm::vec2 sphericalPos) const;
glm::vec2 overlayToSpherical(glm::vec2 overlayPos) const;
glm::vec2 screenToOverlay(glm::vec2 screenPos) const;
glm::vec2 overlayToScreen(glm::vec2 overlayPos) const;
glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const;
glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const;
glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const;
glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const;
static glm::vec2 directionToSpherical(const glm::vec3 & direction);
static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos);
static glm::vec2 screenToSpherical(const glm::vec2 & screenPos);
static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos);
static void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction);
private:
// Interleaved vertex data
@ -91,7 +95,7 @@ private:
VerticesIndices _vbo;
};
float _oculusUIAngularSize = DEFAULT_OCULUS_UI_ANGULAR_SIZE;
float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE;
void renderReticle(glm::quat orientation, float alpha);
void renderPointers();;
@ -122,9 +126,8 @@ private:
float _oculusUIRadius;
float _trailingAudioLoudness;
GLuint _crosshairTexture;
// TODO, move divide up the rendering, displaying and input handling
// facilities of this class
gpu::TexturePointer _crosshairTexture;
GLuint _newUiTexture{ 0 };
int _reticleQuad;

View file

@ -19,12 +19,10 @@
#include <QScreen>
#include <QWindow>
#include "MainWindow.h"
#include "Menu.h"
#include "ui/DialogsManager.h"
#include "ui/HMDToolsDialog.h"
#include "devices/OculusManager.h"
HMDToolsDialog::HMDToolsDialog(QWidget* parent) :

View file

@ -38,9 +38,7 @@ void NodeBounds::draw() {
// Compute ray to find selected nodes later on. We can't use the pre-computed ray in Application because it centers
// itself after the cursor disappears.
Application* application = Application::getInstance();
PickRay pickRay = application->getCamera()->computePickRay(application->getTrueMouseX(),
application->getTrueMouseY());
PickRay pickRay = qApp->computePickRay();
// Variables to keep track of the selected node and properties to draw the cube later if needed
Node* selectedNode = NULL;

View file

@ -170,7 +170,7 @@ void PreferencesDialog::loadPreferences() {
ui.maxOctreePPSSpin->setValue(qApp->getOctreeQuery().getMaxOctreePacketsPerSecond());
ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationOverlay().getOculusUIAngularSize());
ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationOverlay().getHmdUIAngularSize());
SixenseManager& sixense = SixenseManager::getInstance();
ui.sixenseReticleMoveSpeedSpin->setValue(sixense.getReticleMoveSpeed());
@ -216,8 +216,7 @@ void PreferencesDialog::savePreferences() {
myAvatar->setLeanScale(ui.leanScaleSpin->value());
myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value());
auto glCanvas = Application::getInstance()->getGLWidget();
Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height());
Application::getInstance()->resizeGL();
DependencyManager::get<AvatarManager>()->getMyAvatar()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value());
@ -231,7 +230,7 @@ void PreferencesDialog::savePreferences() {
qApp->getOctreeQuery().setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value());
qApp->getApplicationOverlay().setOculusUIAngularSize(ui.oculusUIAngularSizeSpin->value());
qApp->getApplicationOverlay().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value());
SixenseManager& sixense = SixenseManager::getInstance();
sixense.setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value());
@ -255,7 +254,7 @@ void PreferencesDialog::savePreferences() {
audio->setOutputStarveDetectionThreshold(ui.outputStarveDetectionThresholdSpinner->value());
audio->setOutputStarveDetectionPeriod(ui.outputStarveDetectionPeriodSpinner->value());
Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height());
Application::getInstance()->resizeGL();
// LOD items
auto lodManager = DependencyManager::get<LODManager>();

View file

@ -15,6 +15,7 @@
#include <PathUtils.h>
#include <SharedUtil.h>
#include <gpu/GLBackend.h>
#include "Application.h"
#include "RearMirrorTools.h"
@ -28,16 +29,16 @@ const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel";
Setting::Handle<int> RearMirrorTools::rearViewZoomLevel(QStringList() << SETTINGS_GROUP_NAME << ZOOM_LEVEL_SETTINGS,
ZoomLevel::HEAD);
RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds) :
_parent(parent),
RearMirrorTools::RearMirrorTools(QRect& bounds) :
_bounds(bounds),
_windowed(false),
_fullScreen(false)
{
_closeTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/close.svg"));
auto textureCache = DependencyManager::get<TextureCache>();
_closeTexture = textureCache->getImageTexture(PathUtils::resourcesPath() + "images/close.svg");
_zoomHeadTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/plus.svg"));
_zoomBodyTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/minus.svg"));
_zoomHeadTexture = textureCache->getImageTexture(PathUtils::resourcesPath() + "images/plus.svg");
_zoomBodyTexture = textureCache->getImageTexture(PathUtils::resourcesPath() + "images/minus.svg");
_shrinkIconRect = QRect(ICON_PADDING, ICON_PADDING, ICON_SIZE, ICON_SIZE);
_closeIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE);
@ -46,20 +47,19 @@ RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds) :
_headZoomIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE);
}
void RearMirrorTools::render(bool fullScreen) {
void RearMirrorTools::render(bool fullScreen, const QPoint & mousePosition) {
if (fullScreen) {
_fullScreen = true;
displayIcon(_parent->geometry(), _shrinkIconRect, _closeTextureId);
displayIcon(QRect(QPoint(), qApp->getDeviceSize()), _shrinkIconRect, _closeTexture);
} else {
// render rear view tools if mouse is in the bounds
QPoint mousePosition = _parent->mapFromGlobal(QCursor::pos());
_windowed = _bounds.contains(mousePosition.x(), mousePosition.y());
_windowed = _bounds.contains(mousePosition);
if (_windowed) {
displayIcon(_bounds, _closeIconRect, _closeTextureId);
displayIcon(_bounds, _closeIconRect, _closeTexture);
ZoomLevel zoomLevel = (ZoomLevel)rearViewZoomLevel.get();
displayIcon(_bounds, _headZoomIconRect, _zoomHeadTextureId, zoomLevel == HEAD);
displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTextureId, zoomLevel == BODY);
displayIcon(_bounds, _headZoomIconRect, _zoomHeadTexture, zoomLevel == HEAD);
displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTexture, zoomLevel == BODY);
}
}
}
@ -99,7 +99,7 @@ bool RearMirrorTools::mousePressEvent(int x, int y) {
return false;
}
void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint textureId, bool selected) {
void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, const gpu::TexturePointer& texture, bool selected) {
glMatrixMode(GL_PROJECTION);
glPushMatrix();
@ -116,13 +116,13 @@ void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint texture
} else {
quadColor = glm::vec4(1, 1, 1, 1);
}
glBindTexture(GL_TEXTURE_2D, textureId);
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(texture));
glm::vec2 topLeft(iconBounds.left(), iconBounds.top());
glm::vec2 bottomRight(iconBounds.right(), iconBounds.bottom());
glm::vec2 texCoordTopLeft(0.0f, 1.0f);
glm::vec2 texCoordBottomRight(1.0f, 0.0f);
static const glm::vec2 texCoordTopLeft(0.0f, 1.0f);
static const glm::vec2 texCoordBottomRight(1.0f, 0.0f);
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor);

View file

@ -12,10 +12,7 @@
#ifndef hifi_RearMirrorTools_h
#define hifi_RearMirrorTools_h
#include "InterfaceConfig.h"
#include <QGLWidget>
#include <gpu/Texture.h>
#include <SettingHandle.h>
enum ZoomLevel {
@ -26,8 +23,8 @@ enum ZoomLevel {
class RearMirrorTools : public QObject {
Q_OBJECT
public:
RearMirrorTools(QGLWidget* parent, QRect& bounds);
void render(bool fullScreen);
RearMirrorTools(QRect& bounds);
void render(bool fullScreen, const QPoint & mousePos);
bool mousePressEvent(int x, int y);
static Setting::Handle<int> rearViewZoomLevel;
@ -39,12 +36,10 @@ signals:
void restoreView();
private:
QGLWidget* _parent;
QRect _bounds;
GLuint _closeTextureId;
GLuint _resetTextureId;
GLuint _zoomBodyTextureId;
GLuint _zoomHeadTextureId;
gpu::TexturePointer _closeTexture;
gpu::TexturePointer _zoomBodyTexture;
gpu::TexturePointer _zoomHeadTexture;
QRect _closeIconRect;
QRect _resetIconRect;
@ -55,7 +50,7 @@ private:
bool _windowed;
bool _fullScreen;
void displayIcon(QRect bounds, QRect iconBounds, GLuint textureId, bool selected = false);
void displayIcon(QRect bounds, QRect iconBounds, const gpu::TexturePointer& texture, bool selected = false);
};
#endif // hifi_RearMirrorTools_h

View file

@ -75,8 +75,8 @@ SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) {
return data;
}
QString Snapshot::saveSnapshot() {
QFile* snapshotFile = savedFileForSnapshot(false);
QString Snapshot::saveSnapshot(QImage image) {
QFile* snapshotFile = savedFileForSnapshot(image, false);
// we don't need the snapshot file, so close it, grab its filename and delete it
snapshotFile->close();
@ -88,14 +88,12 @@ QString Snapshot::saveSnapshot() {
return snapshotPath;
}
QTemporaryFile* Snapshot::saveTempSnapshot() {
QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) {
// return whatever we get back from saved file for snapshot
return static_cast<QTemporaryFile*>(savedFileForSnapshot(true));;
return static_cast<QTemporaryFile*>(savedFileForSnapshot(image, true));;
}
QFile* Snapshot::savedFileForSnapshot(bool isTemporary) {
auto glCanvas = Application::getInstance()->getGLWidget();
QImage shot = glCanvas->grabFrameBuffer();
QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) {
Avatar* avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();

View file

@ -42,13 +42,13 @@ private:
class Snapshot {
public:
static QString saveSnapshot();
static QTemporaryFile* saveTempSnapshot();
static QString saveSnapshot(QImage image);
static QTemporaryFile* saveTempSnapshot(QImage image);
static SnapshotMetaData* parseSnapshotData(QString snapshotPath);
static Setting::Handle<QString> snapshotsLocation;
private:
static QFile* savedFileForSnapshot(bool isTemporary);
static QFile* savedFileForSnapshot(QImage & image, bool isTemporary);
};
#endif // hifi_Snapshot_h

View file

@ -57,8 +57,8 @@ Stats::Stats():
_octreeStatsWidth(STATS_OCTREE_MIN_WIDTH),
_lastHorizontalOffset(0)
{
auto glCanvas = Application::getInstance()->getGLWidget();
resetWidth(glCanvas->width(), 0);
auto canvasSize = Application::getInstance()->getCanvasSize();
resetWidth(canvasSize.x, 0);
}
void Stats::toggleExpanded() {
@ -68,7 +68,7 @@ void Stats::toggleExpanded() {
// called on mouse click release
// check for clicks over stats in order to expand or contract them
void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) {
auto glCanvas = Application::getInstance()->getGLWidget();
auto canvasSize = Application::getInstance()->getCanvasSize();
if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) {
// not worried about dragging on stats
@ -115,7 +115,7 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD
// top-right stats click
lines = _expanded ? 11 : 3;
statsHeight = lines * STATS_PELS_PER_LINE + 10;
statsWidth = glCanvas->width() - statsX;
statsWidth = canvasSize.x - statsX;
if (mouseX > statsX && mouseX < statsX + statsWidth && mouseY > statsY && mouseY < statsY + statsHeight) {
toggleExpanded();
return;
@ -123,8 +123,8 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD
}
void Stats::resetWidth(int width, int horizontalOffset) {
auto glCanvas = Application::getInstance()->getGLWidget();
int extraSpace = glCanvas->width() - horizontalOffset -2
auto canvasSize = Application::getInstance()->getCanvasSize();
int extraSpace = canvasSize.x - horizontalOffset - 2
- STATS_GENERAL_MIN_WIDTH
- (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0)
- STATS_GEO_MIN_WIDTH
@ -148,7 +148,7 @@ void Stats::resetWidth(int width, int horizontalOffset) {
_pingStatsWidth += (int) extraSpace / panels;
}
_geoStatsWidth += (int) extraSpace / panels;
_octreeStatsWidth += glCanvas->width() -
_octreeStatsWidth += canvasSize.x -
(_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3);
}
}
@ -197,7 +197,7 @@ void Stats::display(
int outKbitsPerSecond,
int voxelPacketsToProcess)
{
auto glCanvas = Application::getInstance()->getGLWidget();
auto canvasSize = Application::getInstance()->getCanvasSize();
unsigned int backgroundColor = 0x33333399;
int verticalOffset = 0, lines = 0;
@ -211,7 +211,7 @@ void Stats::display(
QSharedPointer<BandwidthRecorder> bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
if (_lastHorizontalOffset != horizontalOffset) {
resetWidth(glCanvas->width(), horizontalOffset);
resetWidth(canvasSize.x, horizontalOffset);
_lastHorizontalOffset = horizontalOffset;
}
@ -461,7 +461,7 @@ void Stats::display(
lines = _expanded ? 10 : 2;
drawBackground(backgroundColor, horizontalOffset, 0, glCanvas->width() - horizontalOffset,
drawBackground(backgroundColor, horizontalOffset, 0, canvasSize.x - horizontalOffset,
(lines + 1) * STATS_PELS_PER_LINE);
horizontalOffset += 5;

View file

@ -15,7 +15,12 @@
#include <QBuffer>
#include <QIODevice>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QEventLoop>
#include <ctype.h> // .obj files are not locale-specific. The C/ASCII charset applies.
#include <NetworkAccessManager.h>
#include "FBXReader.h"
#include "OBJReader.h"
#include "Shape.h"
@ -25,35 +30,14 @@
QHash<QString, float> COMMENT_SCALE_HINTS = {{"This file uses centimeters as units", 1.0f / 100.0f},
{"This file uses millimeters as units", 1.0f / 1000.0f}};
class OBJTokenizer {
public:
OBJTokenizer(QIODevice* device);
enum SpecialToken {
NO_TOKEN = -1,
NO_PUSHBACKED_TOKEN = -1,
DATUM_TOKEN = 0x100,
COMMENT_TOKEN = 0x101
};
int nextToken();
const QByteArray& getDatum() const { return _datum; }
bool isNextTokenFloat();
void skipLine() { _device->readLine(); }
void pushBackToken(int token) { _pushedBackToken = token; }
void ungetChar(char ch) { _device->ungetChar(ch); }
const QString getComment() const { return _comment; }
private:
QIODevice* _device;
QByteArray _datum;
int _pushedBackToken;
QString _comment;
};
const QString SMART_DEFAULT_MATERIAL_NAME = "High Fidelity smart default material name";
OBJTokenizer::OBJTokenizer(QIODevice* device) : _device(device), _pushedBackToken(-1) {
}
const QByteArray OBJTokenizer::getLineAsDatum() {
return _device->readLine().trimmed();
}
int OBJTokenizer::nextToken() {
if (_pushedBackToken != NO_PUSHBACKED_TOKEN) {
@ -116,14 +100,35 @@ bool OBJTokenizer::isNextTokenFloat() {
return ok;
}
void setMeshPartDefaults(FBXMeshPart &meshPart, QString materialID) {
glm::vec3 OBJTokenizer::getVec3() {
auto x = getFloat(); // N.B.: getFloat() has side-effect
auto y = getFloat(); // And order of arguments is different on Windows/Linux.
auto z = getFloat();
auto v = glm::vec3(x, y, z);
while (isNextTokenFloat()) {
// the spec(s) get(s) vague here. might be w, might be a color... chop it off.
nextToken();
}
return v;
}
glm::vec2 OBJTokenizer::getVec2() {
auto v = glm::vec2(getFloat(), 1.0f - getFloat()); // OBJ has an odd sense of u, v. Also N.B.: getFloat() has side-effect
while (isNextTokenFloat()) {
// there can be a w, but we don't handle that
nextToken();
}
return v;
}
void setMeshPartDefaults(FBXMeshPart& meshPart, QString materialID) {
meshPart.diffuseColor = glm::vec3(1, 1, 1);
meshPart.specularColor = glm::vec3(1, 1, 1);
meshPart.emissiveColor = glm::vec3(0, 0, 0);
meshPart.emissiveParams = glm::vec2(0, 1);
meshPart.shininess = 40;
meshPart.opacity = 1;
meshPart.materialID = materialID;
meshPart.opacity = 1.0;
meshPart._material = model::MaterialPointer(new model::Material());
@ -134,14 +139,146 @@ void setMeshPartDefaults(FBXMeshPart &meshPart, QString materialID) {
meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0));
}
bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
FBXGeometry &geometry, QVector<glm::vec3>& faceNormals, QVector<int>& faceNormalIndexes,
float& scaleGuess) {
FBXMesh &mesh = geometry.meshes[0];
// OBJFace
bool OBJFace::add(const QByteArray& vertexIndex, const QByteArray& textureIndex, const QByteArray& normalIndex, const QVector<glm::vec3>& vertices) {
bool ok;
int index = vertexIndex.toInt(&ok);
if (!ok) {
return false;
}
vertexIndices.append(index - 1);
if (!textureIndex.isEmpty()) {
index = textureIndex.toInt(&ok);
if (!ok) {
return false;
}
if (index < 0) { // Count backwards from the last one added.
index = vertices.count() + 1 + index;
}
textureUVIndices.append(index - 1);
}
if (!normalIndex.isEmpty()) {
index = normalIndex.toInt(&ok);
if (!ok) {
return false;
}
normalIndices.append(index - 1);
}
return true;
}
QVector<OBJFace> OBJFace::triangulate() {
QVector<OBJFace> newFaces;
const int nVerticesInATriangle = 3;
if (vertexIndices.count() == nVerticesInATriangle) {
newFaces.append(*this);
} else {
for (int i = 1; i < vertexIndices.count() - 1; i++) {
OBJFace newFace;
newFace.addFrom(this, 0);
newFace.addFrom(this, i);
newFace.addFrom(this, i + 1);
newFace.groupName = groupName;
newFace.materialName = materialName;
newFaces.append(newFace);
}
}
return newFaces;
}
void OBJFace::addFrom(const OBJFace* face, int index) { // add using data from f at index i
vertexIndices.append(face->vertexIndices[index]);
if (face->textureUVIndices.count() > 0) { // Any at all. Runtime error if not consistent.
textureUVIndices.append(face->textureUVIndices[index]);
}
if (face->normalIndices.count() > 0) {
normalIndices.append(face->normalIndices[index]);
}
}
bool OBJReader::isValidTexture(const QByteArray &filename) {
QUrl candidateUrl = url->resolved(QUrl(filename));
QNetworkReply *netReply = request(candidateUrl, true);
bool isValid = netReply->isFinished() && (netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200);
netReply->deleteLater();
return isValid;
}
void OBJReader::parseMaterialLibrary(QIODevice* device) {
OBJTokenizer tokenizer(device);
QString matName = SMART_DEFAULT_MATERIAL_NAME;
OBJMaterial& currentMaterial = materials[matName];
while (true) {
switch (tokenizer.nextToken()) {
case OBJTokenizer::COMMENT_TOKEN:
qCDebug(modelformat) << "OBJ Reader MTLLIB comment:" << tokenizer.getComment();
break;
case OBJTokenizer::DATUM_TOKEN:
break;
default:
materials[matName] = currentMaterial;
qCDebug(modelformat) << "OBJ Reader Last material shininess:" << currentMaterial.shininess << " opacity:" << currentMaterial.opacity << " diffuse color:" << currentMaterial.diffuseColor << " specular color:" << currentMaterial.specularColor << " diffuse texture:" << currentMaterial.diffuseTextureFilename << " specular texture:" << currentMaterial.specularTextureFilename;
return;
}
QByteArray token = tokenizer.getDatum();
if (token == "newmtl") {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
return;
}
materials[matName] = currentMaterial;
matName = tokenizer.getDatum();
currentMaterial = materials[matName];
currentMaterial.diffuseTextureFilename = "test";
qCDebug(modelformat) << "OBJ Reader Starting new material definition " << matName;
currentMaterial.diffuseTextureFilename = "";
} else if (token == "Ns") {
currentMaterial.shininess = tokenizer.getFloat();
} else if ((token == "d") || (token == "Tr")) {
currentMaterial.opacity = tokenizer.getFloat();
} else if (token == "Ka") {
qCDebug(modelformat) << "OBJ Reader Ignoring material Ka " << tokenizer.getVec3();
} else if (token == "Kd") {
currentMaterial.diffuseColor = tokenizer.getVec3();
} else if (token == "Ks") {
currentMaterial.specularColor = tokenizer.getVec3();
} else if ((token == "map_Kd") || (token == "map_Ks")) {
QByteArray filename = QUrl(tokenizer.getLineAsDatum()).fileName().toUtf8();
if (filename.endsWith(".tga")) {
qCDebug(modelformat) << "OBJ Reader WARNING: currently ignoring tga texture " << filename << " in " << url;
break;
}
if (isValidTexture(filename)) {
if (token == "map_Kd") {
currentMaterial.diffuseTextureFilename = filename;
} else {
currentMaterial.specularTextureFilename = filename;
}
} else {
qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " ignoring missing texture " << filename;
}
}
}
}
QNetworkReply* OBJReader::request(QUrl& url, bool isTest) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest netRequest(url);
QNetworkReply* netReply = isTest ? networkAccessManager.head(netRequest) : networkAccessManager.get(netRequest);
QEventLoop loop; // Create an event loop that will quit when we get the finished signal
QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec(); // Nothing is going to happen on this whole run thread until we get this
netReply->waitForReadyRead(-1); // so we might as well block this thread waiting for the response, rather than
return netReply; // trying to sync later on.
}
bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess) {
FaceGroup faces;
FBXMesh& mesh = geometry.meshes[0];
mesh.parts.append(FBXMeshPart());
FBXMeshPart &meshPart = mesh.parts.last();
FBXMeshPart& meshPart = mesh.parts.last();
bool sawG = false;
bool result = true;
int originalFaceCountForDebugging = 0;
QString currentGroup;
setMeshPartDefaults(meshPart, QString("dontknow") + QString::number(mesh.parts.count()));
@ -165,6 +302,7 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
break;
}
QByteArray token = tokenizer.getDatum();
//qCDebug(modelformat) << token;
if (token == "g") {
if (sawG) {
// we've encountered the beginning of the next group.
@ -176,54 +314,43 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
break;
}
QByteArray groupName = tokenizer.getDatum();
meshPart.materialID = groupName;
currentGroup = groupName;
//qCDebug(modelformat) << "new group:" << groupName;
} else if (token == "mtllib") {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
break;
}
QByteArray libraryName = tokenizer.getDatum();
if (librariesSeen.contains(libraryName)) {
break; // Some files use mtllib over and over again for the same libraryName
}
librariesSeen[libraryName] = true;
QUrl libraryUrl = url->resolved(QUrl(libraryName).fileName()); // Throw away any path part of libraryName, and merge against original url.
qCDebug(modelformat) << "OBJ Reader new library:" << libraryName << " at:" << libraryUrl;
QNetworkReply* netReply = request(libraryUrl, false);
if (netReply->isFinished() && (netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200)) {
parseMaterialLibrary(netReply);
} else {
qCDebug(modelformat) << "OBJ Reader " << libraryName << " did not answer. Got " << netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
}
netReply->deleteLater();
} else if (token == "usemtl") {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
break;
}
currentMaterialName = tokenizer.getDatum();
qCDebug(modelformat) << "OBJ Reader new current material:" << currentMaterialName;
} else if (token == "v") {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
break;
}
float x = std::stof(tokenizer.getDatum().data());
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
break;
}
float y = std::stof(tokenizer.getDatum().data());
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
break;
}
float z = std::stof(tokenizer.getDatum().data());
while (tokenizer.isNextTokenFloat()) {
// the spec(s) get(s) vague here. might be w, might be a color... chop it off.
tokenizer.nextToken();
}
mesh.vertices.append(glm::vec3(x, y, z));
vertices.append(tokenizer.getVec3());
} else if (token == "vn") {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
break;
}
float x = std::stof(tokenizer.getDatum().data());
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
break;
}
float y = std::stof(tokenizer.getDatum().data());
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
break;
}
float z = std::stof(tokenizer.getDatum().data());
while (tokenizer.isNextTokenFloat()) {
// the spec gets vague here. might be w
tokenizer.nextToken();
}
faceNormals.append(glm::vec3(x, y, z));
normals.append(tokenizer.getVec3());
} else if (token == "vt") {
textureUVs.append(tokenizer.getVec2());
} else if (token == "f") {
// a face can have 3 or more vertices
QVector<int> indices;
QVector<int> normalIndices;
OBJFace face;
while (true) {
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
if (indices.count() == 0) {
if (face.vertexIndices.count() == 0) {
// nonsense, bail out.
goto done;
}
@ -233,69 +360,22 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
// vertex-index
// vertex-index/texture-index
// vertex-index/texture-index/surface-normal-index
QByteArray token = tokenizer.getDatum();
QList<QByteArray> parts = token.split('/');
assert(parts.count() >= 1);
assert(parts.count() <= 3);
QByteArray vertIndexBA = parts[ 0 ];
bool ok;
int vertexIndex = vertIndexBA.toInt(&ok);
if (!ok) {
// it wasn't #/#/#, put it back and exit this loop.
if (!isdigit(token[0])) { // Tokenizer treats line endings as whitespace. Non-digit indicates done;
tokenizer.pushBackToken(OBJTokenizer::DATUM_TOKEN);
break;
}
// if (parts.count() > 1) {
// QByteArray textureIndexBA = parts[ 1 ];
// }
if (parts.count() > 2) {
QByteArray normalIndexBA = parts[ 2 ];
bool ok;
int normalIndex = normalIndexBA.toInt(&ok);
if (ok) {
normalIndices.append(normalIndex - 1);
}
}
// negative indexes count backward from the current end of the vertex list
vertexIndex = (vertexIndex >= 0 ? vertexIndex : mesh.vertices.count() + vertexIndex + 1);
// obj index is 1 based
assert(vertexIndex >= 1);
indices.append(vertexIndex - 1);
QList<QByteArray> parts = token.split('/');
assert(parts.count() >= 1);
assert(parts.count() <= 3);
const QByteArray noData {};
face.add(parts[0], (parts.count() > 1) ? parts[1] : noData, (parts.count() > 2) ? parts[2] : noData, vertices);
face.groupName = currentGroup;
face.materialName = currentMaterialName;
}
if (indices.count() == 3) {
meshPart.triangleIndices.append(indices[0]);
meshPart.triangleIndices.append(indices[1]);
meshPart.triangleIndices.append(indices[2]);
if (normalIndices.count() == 3) {
faceNormalIndexes.append(normalIndices[0]);
faceNormalIndexes.append(normalIndices[1]);
faceNormalIndexes.append(normalIndices[2]);
} else {
// hmm.
}
} else if (indices.count() == 4) {
meshPart.quadIndices << indices;
} else {
// some obj writers (maya) will write a face with lots of points.
for (int i = 1; i < indices.count() - 1; i++) {
// break the face into triangles
meshPart.triangleIndices.append(indices[0]);
meshPart.triangleIndices.append(indices[i]);
meshPart.triangleIndices.append(indices[i+1]);
}
if (indices.count() == normalIndices.count()) {
for (int i = 1; i < normalIndices.count() - 1; i++) {
faceNormalIndexes.append(normalIndices[0]);
faceNormalIndexes.append(normalIndices[i]);
faceNormalIndexes.append(normalIndices[i+1]);
}
}
originalFaceCountForDebugging++;
foreach(OBJFace face, face.triangulate()) {
faces.append(face);
}
} else {
// something we don't (yet) care about
@ -303,61 +383,40 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
tokenizer.skipLine();
}
}
done:
if (meshPart.triangleIndices.size() == 0 && meshPart.quadIndices.size() == 0) {
// empty mesh?
done:
if (faces.count() == 0) { // empty mesh
mesh.parts.pop_back();
}
faceGroups.append(faces); // We're done with this group. Add the faces.
//qCDebug(modelformat) << "end group:" << meshPart.materialID << " original faces:" << originalFaceCountForDebugging << " triangles:" << faces.count() << " keep going:" << result;
return result;
}
FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping) {
FBXGeometry OBJReader::readOBJ(const QByteArray& model, const QVariantHash& mapping) {
QBuffer buffer(const_cast<QByteArray*>(&model));
buffer.open(QIODevice::ReadOnly);
return readOBJ(&buffer, mapping);
return readOBJ(&buffer, mapping, nullptr);
}
FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) {
FBXGeometry OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, QUrl* url) {
FBXGeometry geometry;
OBJTokenizer tokenizer(device);
QVector<int> faceNormalIndexes;
QVector<glm::vec3> faceNormals;
float scaleGuess = 1.0f;
faceNormalIndexes.clear();
this->url = url;
geometry.meshExtents.reset();
geometry.meshes.append(FBXMesh());
try {
// call parseOBJGroup as long as it's returning true. Each successful call will
// add a new meshPart to the geometry's single mesh.
bool success = true;
while (success) {
success = parseOBJGroup(tokenizer, mapping, geometry, faceNormals, faceNormalIndexes, scaleGuess);
}
while (parseOBJGroup(tokenizer, mapping, geometry, scaleGuess)) {}
FBXMesh &mesh = geometry.meshes[0];
FBXMesh& mesh = geometry.meshes[0];
mesh.meshIndex = 0;
// if we got a hint about units, scale all the points
if (scaleGuess != 1.0f) {
for (int i = 0; i < mesh.vertices.size(); i++) {
mesh.vertices[i] *= scaleGuess;
}
}
mesh.meshExtents.reset();
foreach (const glm::vec3& vertex, mesh.vertices) {
mesh.meshExtents.addPoint(vertex);
geometry.meshExtents.addPoint(vertex);
}
geometry.joints.resize(1);
geometry.joints[0].isFree = false;
geometry.joints[0].parentIndex = -1;
@ -380,63 +439,96 @@ FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) {
0, 0, 1, 0,
0, 0, 0, 1);
mesh.clusters.append(cluster);
// The OBJ format has normals for faces. The FBXGeometry structure has normals for points.
// run through all the faces, look-up (or determine) a normal and set the normal for the points
// that make up each face.
QVector<glm::vec3> pointNormalsSums;
mesh.normals.fill(glm::vec3(0,0,0), mesh.vertices.count());
pointNormalsSums.fill(glm::vec3(0,0,0), mesh.vertices.count());
foreach (FBXMeshPart meshPart, mesh.parts) {
int triCount = meshPart.triangleIndices.count() / 3;
for (int i = 0; i < triCount; i++) {
int p0Index = meshPart.triangleIndices[i*3];
int p1Index = meshPart.triangleIndices[i*3+1];
int p2Index = meshPart.triangleIndices[i*3+2];
assert(p0Index < mesh.vertices.count());
assert(p1Index < mesh.vertices.count());
assert(p2Index < mesh.vertices.count());
glm::vec3 n0, n1, n2;
if (i < faceNormalIndexes.count()) {
int n0Index = faceNormalIndexes[i*3];
int n1Index = faceNormalIndexes[i*3+1];
int n2Index = faceNormalIndexes[i*3+2];
n0 = faceNormals[n0Index];
n1 = faceNormals[n1Index];
n2 = faceNormals[n2Index];
} else {
// We didn't read normals, add bogus normal data for this face
glm::vec3 p0 = mesh.vertices[p0Index];
glm::vec3 p1 = mesh.vertices[p1Index];
glm::vec3 p2 = mesh.vertices[p2Index];
n0 = glm::cross(p1 - p0, p2 - p0);
n1 = n0;
n2 = n0;
}
// we sum up the normal for each point and then divide by the count to get an average
pointNormalsSums[p0Index] += n0;
pointNormalsSums[p1Index] += n1;
pointNormalsSums[p2Index] += n2;
// Some .obj files use the convention that a group with uv coordinates that doesn't define a material, should use a texture with the same basename as the .obj file.
QString filename = url->fileName();
int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail
QString basename = filename.remove(extIndex + 1, sizeof("obj"));
OBJMaterial& preDefinedMaterial = materials[SMART_DEFAULT_MATERIAL_NAME];
preDefinedMaterial.diffuseColor = glm::vec3(1.0f);
QVector<QByteArray> extensions = {"jpg", "jpeg", "png", "tga"};
QByteArray base = basename.toUtf8(), textName = "";
for (int i = 0; i < extensions.count(); i++) {
QByteArray candidateString = base + extensions[i];
if (isValidTexture(candidateString)) {
textName = candidateString;
break;
}
int vertCount = mesh.vertices.count();
for (int i = 0; i < vertCount; i++) {
float length = glm::length(pointNormalsSums[i]);
if (length > FLT_EPSILON) {
mesh.normals[i] = glm::normalize(pointNormalsSums[i]);
}
}
// XXX do same normal calculation for quadCount
}
}
catch(const std::exception& e) {
qCDebug(modelformat) << "something went wrong in OBJ reader";
if (!textName.isEmpty()) {
preDefinedMaterial.diffuseTextureFilename = textName;
}
materials[SMART_DEFAULT_MATERIAL_NAME] = preDefinedMaterial;
for (int i = 0, meshPartCount = 0; i < mesh.parts.count(); i++, meshPartCount++) {
FBXMeshPart& meshPart = mesh.parts[i];
FaceGroup faceGroup = faceGroups[meshPartCount];
OBJFace leadFace = faceGroup[0]; // All the faces in the same group will have the same name and material.
QString groupMaterialName = leadFace.materialName;
if (groupMaterialName.isEmpty() && (leadFace.textureUVIndices.count() > 0)) {
qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " needs a texture that isn't specified. Using default mechanism.";
groupMaterialName = SMART_DEFAULT_MATERIAL_NAME;
} else if (!groupMaterialName.isEmpty() && !materials.contains(groupMaterialName)) {
qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " specifies a material " << groupMaterialName << " that is not defined. Using default mechanism.";
groupMaterialName = SMART_DEFAULT_MATERIAL_NAME;
}
if (!groupMaterialName.isEmpty()) {
OBJMaterial* material = &materials[groupMaterialName];
// The code behind this is in transition. Some things are set directly in the FXBMeshPart...
meshPart.materialID = groupMaterialName;
meshPart.diffuseTexture.filename = material->diffuseTextureFilename;
meshPart.specularTexture.filename = material->specularTextureFilename;
// ... and some things are set in the underlying material.
meshPart._material->setDiffuse(material->diffuseColor);
meshPart._material->setSpecular(material->specularColor);
meshPart._material->setShininess(material->shininess);
meshPart._material->setOpacity(material->opacity);
}
qCDebug(modelformat) << "OBJ Reader part:" << meshPartCount << "name:" << leadFace.groupName << "material:" << groupMaterialName << "diffuse:" << meshPart._material->getDiffuse() << "faces:" << faceGroup.count() << "triangle indices will start with:" << mesh.vertices.count();
foreach(OBJFace face, faceGroup) {
glm::vec3 v0 = vertices[face.vertexIndices[0]];
glm::vec3 v1 = vertices[face.vertexIndices[1]];
glm::vec3 v2 = vertices[face.vertexIndices[2]];
meshPart.triangleIndices.append(mesh.vertices.count()); // not face.vertexIndices into vertices
mesh.vertices << v0;
meshPart.triangleIndices.append(mesh.vertices.count());
mesh.vertices << v1;
meshPart.triangleIndices.append(mesh.vertices.count());
mesh.vertices << v2;
glm::vec3 n0, n1, n2;
if (face.normalIndices.count()) {
n0 = normals[face.normalIndices[0]];
n1 = normals[face.normalIndices[1]];
n2 = normals[face.normalIndices[2]];
} else { // generate normals from triangle plane if not provided
n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0);
}
mesh.normals << n0 << n1 << n2;
if (face.textureUVIndices.count()) {
mesh.texCoords
<< textureUVs[face.textureUVIndices[0]]
<< textureUVs[face.textureUVIndices[1]]
<< textureUVs[face.textureUVIndices[2]];
}
}
}
// if we got a hint about units, scale all the points
if (scaleGuess != 1.0f) {
for (int i = 0; i < mesh.vertices.size(); i++) {
mesh.vertices[i] *= scaleGuess;
}
}
mesh.meshExtents.reset();
foreach (const glm::vec3& vertex, mesh.vertices) {
mesh.meshExtents.addPoint(vertex);
geometry.meshExtents.addPoint(vertex);
}
fbxDebugDump(geometry);
} catch(const std::exception& e) {
qCDebug(modelformat) << "OBJ reader fail: " << e.what();
}
return geometry;
@ -453,11 +545,11 @@ void fbxDebugDump(const FBXGeometry& fbxgeo) {
foreach (FBXMesh mesh, fbxgeo.meshes) {
qCDebug(modelformat) << " vertices.count() =" << mesh.vertices.count();
qCDebug(modelformat) << " normals.count() =" << mesh.normals.count();
if (mesh.normals.count() == mesh.vertices.count()) {
/*if (mesh.normals.count() == mesh.vertices.count()) {
for (int i = 0; i < mesh.normals.count(); i++) {
qCDebug(modelformat) << " " << mesh.vertices[ i ] << mesh.normals[ i ];
}
}
}*/
qCDebug(modelformat) << " tangents.count() =" << mesh.tangents.count();
qCDebug(modelformat) << " colors.count() =" << mesh.colors.count();
qCDebug(modelformat) << " texCoords.count() =" << mesh.texCoords.count();
@ -470,13 +562,15 @@ void fbxDebugDump(const FBXGeometry& fbxgeo) {
foreach (FBXMeshPart meshPart, mesh.parts) {
qCDebug(modelformat) << " quadIndices.count() =" << meshPart.quadIndices.count();
qCDebug(modelformat) << " triangleIndices.count() =" << meshPart.triangleIndices.count();
qCDebug(modelformat) << " diffuseColor =" << meshPart.diffuseColor;
qCDebug(modelformat) << " specularColor =" << meshPart.specularColor;
qCDebug(modelformat) << " emissiveColor =" << meshPart.emissiveColor;
qCDebug(modelformat) << " diffuseColor =" << meshPart.diffuseColor << "mat =" << meshPart._material->getDiffuse();
qCDebug(modelformat) << " specularColor =" << meshPart.specularColor << "mat =" << meshPart._material->getSpecular();
qCDebug(modelformat) << " emissiveColor =" << meshPart.emissiveColor << "mat =" << meshPart._material->getEmissive();
qCDebug(modelformat) << " emissiveParams =" << meshPart.emissiveParams;
qCDebug(modelformat) << " shininess =" << meshPart.shininess;
qCDebug(modelformat) << " opacity =" << meshPart.opacity;
qCDebug(modelformat) << " shininess =" << meshPart.shininess << "mat =" << meshPart._material->getShininess();
qCDebug(modelformat) << " opacity =" << meshPart.opacity << "mat =" << meshPart._material->getOpacity();
qCDebug(modelformat) << " materialID =" << meshPart.materialID;
qCDebug(modelformat) << " diffuse texture =" << meshPart.diffuseTexture.filename;
qCDebug(modelformat) << " specular texture =" << meshPart.specularTexture.filename;
}
qCDebug(modelformat) << " clusters.count() =" << mesh.clusters.count();
foreach (FBXCluster cluster, mesh.clusters) {

View file

@ -1,8 +1,86 @@
#include <QtNetwork/QNetworkReply>
#include "FBXReader.h"
FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping);
FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping);
void fbxDebugDump(const FBXGeometry& fbxgeo);
void setMeshPartDefaults(FBXMeshPart &meshPart, QString materialID);
class OBJTokenizer {
public:
OBJTokenizer(QIODevice* device);
enum SpecialToken {
NO_TOKEN = -1,
NO_PUSHBACKED_TOKEN = -1,
DATUM_TOKEN = 0x100,
COMMENT_TOKEN = 0x101
};
int nextToken();
const QByteArray& getDatum() const { return _datum; }
bool isNextTokenFloat();
const QByteArray getLineAsDatum(); // some "filenames" have spaces in them
void skipLine() { _device->readLine(); }
void pushBackToken(int token) { _pushedBackToken = token; }
void ungetChar(char ch) { _device->ungetChar(ch); }
const QString getComment() const { return _comment; }
glm::vec3 getVec3();
glm::vec2 getVec2();
float getFloat() { return std::stof((nextToken() != OBJTokenizer::DATUM_TOKEN) ? nullptr : getDatum().data()); }
private:
QIODevice* _device;
QByteArray _datum;
int _pushedBackToken;
QString _comment;
};
class OBJFace { // A single face, with three or more planar vertices. But see triangulate().
public:
QVector<int> vertexIndices;
QVector<int> textureUVIndices;
QVector<int> normalIndices;
QString groupName; // We don't make use of hierarchical structure, but it can be preserved for debugging and future use.
QString materialName;
// Add one more set of vertex data. Answers true if successful
bool add(const QByteArray& vertexIndex, const QByteArray& textureIndex, const QByteArray& normalIndex, const QVector<glm::vec3>& vertices);
// Return a set of one or more OBJFaces from this one, in which each is just a triangle.
// Even though FBXMeshPart can handle quads, it would be messy to try to keep track of mixed-size faces, so we treat everything as triangles.
QVector<OBJFace> triangulate();
private:
void addFrom(const OBJFace* face, int index);
};
// Materials and references to material names can come in any order, and different mesh parts can refer to the same material.
// Therefore it would get pretty hacky to try to use FBXMeshPart to store these as we traverse the files.
class OBJMaterial {
public:
float shininess;
float opacity;
glm::vec3 diffuseColor;
glm::vec3 specularColor;
QByteArray diffuseTextureFilename;
QByteArray specularTextureFilename;
OBJMaterial() : opacity(1.0f) {}
};
class OBJReader: public QObject { // QObject so we can make network requests.
Q_OBJECT
public:
typedef QVector<OBJFace> FaceGroup;
QVector<glm::vec3> vertices; // all that we ever encounter while reading
QVector<glm::vec2> textureUVs;
QVector<glm::vec3> normals;
QVector<FaceGroup> faceGroups;
QString currentMaterialName;
QHash<QString, OBJMaterial> materials;
QUrl* url;
QNetworkReply* request(QUrl& url, bool isTest);
FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping);
FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping, QUrl* url);
private:
QHash<QByteArray, bool> librariesSeen;
bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess);
void parseMaterialLibrary(QIODevice* device);
bool isValidTexture(const QByteArray &filename); // true if the file exists. TODO?: check content-type header and that it is a supported format.
};
// What are these utilities doing here? One is used by fbx loading code in VHACD Utils, and the other a general debugging utility.
void setMeshPartDefaults(FBXMeshPart& meshPart, QString materialID);
void fbxDebugDump(const FBXGeometry& fbxgeo);

View file

@ -50,7 +50,7 @@ public:
virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera) = 0;
virtual float getSizeScale() const = 0;
virtual int getBoundaryLevelAdjust() const = 0;
virtual PickRay computePickRay(float x, float y) = 0;
virtual PickRay computePickRay(float x, float y) const = 0;
virtual const glm::vec3& getAvatarPosition() const = 0;
};

View file

@ -1797,8 +1797,8 @@ NetworkGeometry::NetworkGeometry(const QUrl& url, const QSharedPointer<NetworkGe
if (url.isEmpty()) {
// make the minimal amount of dummy geometry to satisfy Model
FBXJoint joint = { false, QVector<int>(), -1, 0.0f, 0.0f, glm::vec3(), glm::mat4(), glm::quat(), glm::quat(),
glm::quat(), glm::mat4(), glm::mat4(), glm::vec3(), glm::vec3(), glm::quat(), glm::quat(),
glm::mat4(), QString(""), glm::vec3(), glm::quat(), SHAPE_TYPE_NONE, false};
glm::quat(), glm::mat4(), glm::mat4(), glm::vec3(), glm::vec3(), glm::quat(), glm::quat(),
glm::mat4(), QString(""), glm::vec3(), glm::quat(), SHAPE_TYPE_NONE, false};
_geometry.joints.append(joint);
_geometry.leftEyeJointIndex = -1;
_geometry.rightEyeJointIndex = -1;
@ -2107,7 +2107,7 @@ void GeometryReader::run() {
}
fbxgeo = readFBX(_reply, _mapping, grabLightmaps, lightmapLevel);
} else if (_url.path().toLower().endsWith(".obj")) {
fbxgeo = readOBJ(_reply, _mapping);
fbxgeo = OBJReader().readOBJ(_reply, _mapping, &_url);
}
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo));
} else {

View file

@ -31,7 +31,6 @@ GlowEffect::GlowEffect()
_isOddFrame(false),
_isFirstFrame(true),
_intensity(0.0f),
_widget(NULL),
_enabled(false) {
}
@ -64,7 +63,7 @@ static ProgramObject* createProgram(const QString& name) {
return program;
}
void GlowEffect::init(QGLWidget* widget, bool enabled) {
void GlowEffect::init(bool enabled) {
if (_initialized) {
qCDebug(renderutils, "[ERROR] GlowEffeect is already initialized.");
return;
@ -92,19 +91,9 @@ void GlowEffect::init(QGLWidget* widget, bool enabled) {
_diffusionScaleLocation = _diffuseProgram->uniformLocation("diffusionScale");
_initialized = true;
_widget = widget;
_enabled = enabled;
}
int GlowEffect::getDeviceWidth() const {
return _widget->width() * (_widget->windowHandle() ? _widget->windowHandle()->devicePixelRatio() : 1.0f);
}
int GlowEffect::getDeviceHeight() const {
return _widget->height() * (_widget->windowHandle() ? _widget->windowHandle()->devicePixelRatio() : 1.0f);
}
void GlowEffect::prepare() {
auto primaryFBO = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
GLuint fbo = gpu::GLBackend::getFramebufferID(primaryFBO);
@ -173,7 +162,8 @@ gpu::FramebufferPointer GlowEffect::render(bool toTexture) {
} else {
maybeBind(destFBO);
if (!destFBO) {
glViewport(0, 0, getDeviceWidth(), getDeviceHeight());
//destFBO->getSize();
glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
}
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
@ -219,7 +209,7 @@ gpu::FramebufferPointer GlowEffect::render(bool toTexture) {
}
maybeBind(destFBO);
if (!destFBO) {
glViewport(0, 0, getDeviceWidth(), getDeviceHeight());
glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
}
_addSeparateProgram->bind();
renderFullscreenQuad();
@ -228,7 +218,6 @@ gpu::FramebufferPointer GlowEffect::render(bool toTexture) {
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
}
glPopMatrix();

View file

@ -34,7 +34,7 @@ public:
/// (either the secondary or the tertiary).
gpu::FramebufferPointer getFreeFramebuffer() const;
void init(QGLWidget* widget, bool enabled);
void init(bool enabled);
/// Prepares the glow effect for rendering the current frame. To be called before rendering the scene.
void prepare();
@ -61,9 +61,6 @@ private:
GlowEffect();
virtual ~GlowEffect();
int getDeviceWidth() const;
int getDeviceHeight() const;
bool _initialized;
ProgramObject* _addProgram;
@ -80,7 +77,6 @@ private:
float _intensity;
QStack<float> _intensityStack;
QGLWidget* _widget;
bool _enabled;
};

View file

@ -35,8 +35,7 @@ TextureCache::TextureCache() :
_permutationNormalTexture(0),
_whiteTexture(0),
_blueTexture(0),
_frameBufferSize(100, 100),
_associatedWidget(NULL)
_frameBufferSize(100, 100)
{
const qint64 TEXTURE_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE;
setUnusedResourceCacheSize(TEXTURE_DEFAULT_UNUSED_MAX_SIZE);
@ -293,22 +292,21 @@ GLuint TextureCache::getShadowDepthTextureID() {
return gpu::GLBackend::getTextureID(_shadowTexture);
}
bool TextureCache::eventFilter(QObject* watched, QEvent* event) {
if (event->type() == QEvent::Resize) {
QSize size = static_cast<QResizeEvent*>(event)->size();
if (_frameBufferSize != size) {
_primaryFramebuffer.reset();
_primaryColorTexture.reset();
_primaryDepthTexture.reset();
_primaryNormalTexture.reset();
_primarySpecularTexture.reset();
_secondaryFramebuffer.reset();
_tertiaryFramebuffer.reset();
}
/// Returns a texture version of an image file
gpu::TexturePointer TextureCache::getImageTexture(const QString & path) {
QImage image(path);
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB);
gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB);
if (image.hasAlphaChannel()) {
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA);
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::BGRA);
}
return false;
gpu::TexturePointer texture = gpu::TexturePointer(
gpu::Texture::create2D(formatGPU, image.width(), image.height(),
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
texture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
texture->autoGenerateMips(-1);
return texture;
}
QSharedPointer<Resource> TextureCache::createResource(const QUrl& url,
@ -318,14 +316,6 @@ QSharedPointer<Resource> TextureCache::createResource(const QUrl& url,
&Resource::allReferencesCleared);
}
void TextureCache::associateWithWidget(QGLWidget* widget) {
if (_associatedWidget) {
_associatedWidget->removeEventFilter(this);
}
_associatedWidget = widget;
_associatedWidget->installEventFilter(this);
}
Texture::Texture() {
}
@ -380,15 +370,15 @@ ImageReader::ImageReader(const QWeakPointer<Resource>& texture, QNetworkReply* r
}
std::once_flag onceListSuppoertedFormatsflag;
void listSupportedImageFormats() {
std::call_once(onceListSuppoertedFormatsflag, [](){
void listSupportedImageFormats() {
std::call_once(onceListSuppoertedFormatsflag, [](){
auto supportedFormats = QImageReader::supportedImageFormats();
QString formats;
foreach(const QByteArray& f, supportedFormats) {
formats += QString(f) + ",";
}
qCDebug(renderutils) << "List of supported Image formats:" << formats;
});
qCDebug(renderutils) << "List of supported Image formats:" << formats;
});
}
void ImageReader::run() {

View file

@ -35,9 +35,6 @@ class TextureCache : public ResourceCache, public Dependency {
SINGLETON_DEPENDENCY
public:
void associateWithWidget(QGLWidget* widget);
/// Sets the desired texture resolution for the framebuffer objects.
void setFrameBufferSize(QSize frameBufferSize);
const QSize& getFrameBufferSize() const { return _frameBufferSize; }
@ -53,6 +50,9 @@ public:
/// Returns the a pale blue texture (useful for a normal map).
const gpu::TexturePointer& getBlueTexture();
/// Returns a texture version of an image file
gpu::TexturePointer getImageTexture(const QString & path);
/// Loads a texture from the specified URL.
NetworkTexturePointer getTexture(const QUrl& url, TextureType type = DEFAULT_TEXTURE, bool dilatable = false,
const QByteArray& content = QByteArray());
@ -94,8 +94,6 @@ public:
/// Returns the ID of the shadow framebuffer object's depth texture.
GLuint getShadowDepthTextureID();
virtual bool eventFilter(QObject* watched, QEvent* event);
protected:
virtual QSharedPointer<Resource> createResource(const QUrl& url,
@ -127,7 +125,6 @@ private:
gpu::TexturePointer _shadowTexture;
QSize _frameBufferSize;
QGLWidget* _associatedWidget;
};
/// A simple object wrapper for an OpenGL texture.

View file

@ -338,6 +338,10 @@ QMatrix4x4 fromGlm(const glm::mat4 & m) {
return QMatrix4x4(&m[0][0]).transposed();
}
QSize fromGlm(const glm::ivec2 & v) {
return QSize(v.x, v.y);
}
QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size) {
QRectF result(pos.x, pos.y, size.x, size.y);
return result;

View file

@ -112,8 +112,13 @@ glm::vec2 toGlm(const QPointF & pt);
glm::vec3 toGlm(const xColor & color);
glm::vec4 toGlm(const QColor & color);
QSize fromGlm(const glm::ivec2 & v);
QMatrix4x4 fromGlm(const glm::mat4 & m);
QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size);
#define YAW(euler) euler.y
#define PITCH(euler) euler.x
#define ROLL(euler) euler.z
#endif // hifi_GLMHelpers_h

View file

@ -36,7 +36,7 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) {
QByteArray fbxContents = fbx.readAll();
if (filename.toLower().endsWith(".obj")) {
result = readOBJ(fbxContents, QVariantHash());
result = OBJReader().readOBJ(fbxContents, QVariantHash());
} else if (filename.toLower().endsWith(".fbx")) {
result = readFBX(fbxContents, QVariantHash());
} else {