diff --git a/examples/dice.js b/examples/dice.js
index ee48d59617..f313e606b8 100644
--- a/examples/dice.js
+++ b/examples/dice.js
@@ -32,7 +32,7 @@ var BUTTON_SIZE = 32;
var PADDING = 3;
var offButton = Overlays.addOverlay("image", {
- x: screenSize.x / 2 - BUTTON_SIZE,
+ x: screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING,
y: screenSize.y- (BUTTON_SIZE + PADDING),
width: BUTTON_SIZE,
height: BUTTON_SIZE,
@@ -40,6 +40,17 @@ var offButton = Overlays.addOverlay("image", {
color: { red: 255, green: 255, blue: 255},
alpha: 1
});
+
+var deleteButton = Overlays.addOverlay("image", {
+ x: screenSize.x / 2 - BUTTON_SIZE,
+ y: screenSize.y- (BUTTON_SIZE + PADDING),
+ width: BUTTON_SIZE,
+ height: BUTTON_SIZE,
+ imageURL: HIFI_PUBLIC_BUCKET + "images/delete.png",
+ color: { red: 255, green: 255, blue: 255},
+ alpha: 1
+ });
+
var diceButton = Overlays.addOverlay("image", {
x: screenSize.x / 2 + PADDING,
y: screenSize.y - (BUTTON_SIZE + PADDING),
@@ -108,6 +119,8 @@ function mousePressEvent(event) {
if (clickedOverlay == offButton) {
deleteDice();
Script.stop();
+ } else if (clickedOverlay == deleteButton) {
+ deleteDice();
} else if (clickedOverlay == diceButton) {
var HOW_HARD = 2.0;
var position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
@@ -120,6 +133,7 @@ function mousePressEvent(event) {
function scriptEnding() {
Overlays.deleteOverlay(offButton);
Overlays.deleteOverlay(diceButton);
+ Overlays.deleteOverlay(deleteButton);
}
Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity);
diff --git a/examples/grab.js b/examples/grab.js
index 312d21dd43..df2042350e 100644
--- a/examples/grab.js
+++ b/examples/grab.js
@@ -193,12 +193,15 @@ function update(deltaTime) {
// Add Damping
newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE));
// Update entity
-
- //add damping to angular velocity:
+ } else {
+ newVelocity = entityProps.velocity;
}
if (shouldRotate) {
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
+ } else {
+ angularVelocity = entityProps.angularVelocity;
}
+
Entities.editEntity(grabbedEntity, {
velocity: newVelocity,
angularVelocity: angularVelocity
diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html
index e525818e51..26bcc63f15 100644
--- a/examples/html/entityProperties.html
+++ b/examples/html/entityProperties.html
@@ -26,6 +26,20 @@
);
};
}
+ function createEmitGroupCheckedPropertyUpdateFunction(group, propertyName) {
+ return function() {
+ var properties = {};
+ properties[group] = {};
+ properties[group][propertyName] = this.checked;
+ EventBridge.emitWebEvent(
+ JSON.stringify({
+ type: "update",
+ properties: properties
+ })
+ );
+ };
+ }
+
function createEmitNumberPropertyUpdateFunction(propertyName) {
return function() {
EventBridge.emitWebEvent(
@@ -286,6 +300,8 @@
var elZoneAtmosphereScatteringWavelengthsX = document.getElementById("property-zone-atmosphere-scattering-wavelengths-x");
var elZoneAtmosphereScatteringWavelengthsY = document.getElementById("property-zone-atmosphere-scattering-wavelengths-y");
var elZoneAtmosphereScatteringWavelengthsZ = document.getElementById("property-zone-atmosphere-scattering-wavelengths-z");
+ var elZoneAtmosphereHasStars = document.getElementById("property-zone-atmosphere-has-stars");
+
if (window.EventBridge !== undefined) {
EventBridge.scriptEventReceived.connect(function(data) {
@@ -486,7 +502,7 @@
elZoneAtmosphereScatteringWavelengthsX.value = properties.atmosphere.scatteringWavelengths.x;
elZoneAtmosphereScatteringWavelengthsY.value = properties.atmosphere.scatteringWavelengths.y;
elZoneAtmosphereScatteringWavelengthsZ.value = properties.atmosphere.scatteringWavelengths.z;
-
+ elZoneAtmosphereHasStars.checked = properties.atmosphere.hasStars;
}
@@ -650,6 +666,8 @@
elZoneAtmosphereScatteringWavelengthsX.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction);
elZoneAtmosphereScatteringWavelengthsY.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction);
elZoneAtmosphereScatteringWavelengthsZ.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction);
+ elZoneAtmosphereHasStars.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('atmosphere','hasStars'));
+
elMoveSelectionToGrid.addEventListener("click", function() {
EventBridge.emitWebEvent(JSON.stringify({
@@ -1136,23 +1154,29 @@
Atmosphere Scattering Wavelenghts
+
+ Atmosphere Has Stars
+
+
+
+
diff --git a/examples/html/style.css b/examples/html/style.css
index 8be9b92a51..c87201da4b 100644
--- a/examples/html/style.css
+++ b/examples/html/style.css
@@ -121,6 +121,14 @@ input.coord {
display: block;
}
+input.no-spin::-webkit-outer-spin-button,
+input.no-spin::-webkit-inner-spin-button {
+ display: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ margin: 0; /* <-- Apparently some margin are still there even though it's hidden */
+}
+
table#entity-table {
border-collapse: collapse;
font-family: Sans-Serif;
diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js
index 80ba4c0f56..f3ea18aef3 100644
--- a/examples/libraries/entitySelectionTool.js
+++ b/examples/libraries/entitySelectionTool.js
@@ -203,7 +203,7 @@ SelectionManager = (function() {
try {
listeners[i]();
} catch (e) {
- print("EntitySelectionTool got exception: " = JSON.stringify(e));
+ print("EntitySelectionTool got exception: " + JSON.stringify(e));
}
}
};
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 42d08bcd9e..7e1fef420e 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -812,8 +812,7 @@ void Application::initializeUi() {
if (devicePixelRatio != oldDevicePixelRatio) {
oldDevicePixelRatio = devicePixelRatio;
qDebug() << "Device pixel ratio changed, triggering GL resize";
- resizeGL(_glWidget->width(),
- _glWidget->height());
+ resizeGL();
}
});
}
@@ -830,15 +829,7 @@ void Application::paintGL() {
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::paintGL()");
-
- // Set the desired FBO texture size. If it hasn't changed, this does nothing.
- // Otherwise, it must rebuild the FBOs
- if (OculusManager::isConnected()) {
- DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize());
- } else {
- QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale();
- DependencyManager::get()->setFrameBufferSize(fbSize);
- }
+ resizeGL();
glEnable(GL_LINE_SMOOTH);
@@ -915,7 +906,14 @@ void Application::paintGL() {
renderRearViewMirror(_mirrorViewRect);
}
- DependencyManager::get()->render();
+ auto finalFbo = DependencyManager::get()->render();
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo));
+ glBlitFramebuffer(0, 0, _renderResolution.x, _renderResolution.y,
+ 0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(),
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
{
PerformanceTimer perfTimer("renderOverlay");
@@ -960,33 +958,47 @@ void Application::showEditEntitiesHelp() {
InfoView::show(INFO_EDIT_ENTITIES_PATH);
}
-void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) {
+void Application::resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size) {
if (OculusManager::isConnected()) {
- OculusManager::configureCamera(camera, width, height);
+ OculusManager::configureCamera(camera, size.x, size.y);
} else if (TV3DManager::isConnected()) {
- TV3DManager::configureCamera(camera, width, height);
+ TV3DManager::configureCamera(camera, size.x, size.y);
} else {
- camera.setAspectRatio((float)width / height);
+ camera.setAspectRatio((float)size.x / size.y);
camera.setFieldOfView(_fieldOfView.get());
}
}
-void Application::resizeGL(int width, int height) {
- DependencyManager::get()->setFrameBufferSize(QSize(width, height));
- resetCamerasOnResizeGL(_myCamera, width, height);
+void Application::resizeGL() {
+ // Set the desired FBO texture size. If it hasn't changed, this does nothing.
+ // Otherwise, it must rebuild the FBOs
+ QSize renderSize;
+ if (OculusManager::isConnected()) {
+ renderSize = OculusManager::getRenderTargetSize();
+ } else {
+ renderSize = _glWidget->getDeviceSize() * getRenderResolutionScale();
+ }
+ if (_renderResolution == toGlm(renderSize)) {
+ return;
+ }
- glViewport(0, 0, width, height); // shouldn't this account for the menu???
+ _renderResolution = toGlm(renderSize);
+ DependencyManager::get()->setFrameBufferSize(renderSize);
+ resetCamerasOnResizeGL(_myCamera, _renderResolution);
+
+ glViewport(0, 0, _renderResolution.x, _renderResolution.y); // shouldn't this account for the menu???
updateProjectionMatrix();
glLoadIdentity();
auto offscreenUi = DependencyManager::get();
offscreenUi->resize(_glWidget->size());
+ _glWidget->makeCurrent();
// update Stats width
// let's set horizontal offset to give stats some margin to mirror
int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2;
- Stats::getInstance()->resetWidth(width, horizontalOffset);
+ Stats::getInstance()->resetWidth(_renderResolution.x, horizontalOffset);
}
void Application::updateProjectionMatrix() {
@@ -1824,7 +1836,7 @@ void Application::setFullscreen(bool fullscreen) {
}
void Application::setEnable3DTVMode(bool enable3DTVMode) {
- resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
+ resizeGL();
}
void Application::setEnableVRMode(bool enableVRMode) {
@@ -1849,7 +1861,7 @@ void Application::setEnableVRMode(bool enableVRMode) {
_myCamera.setHmdRotation(glm::quat());
}
- resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
+ resizeGL();
updateCursorVisibility();
}
@@ -1934,6 +1946,7 @@ void Application::setActiveFaceTracker() {
bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::UseCamera);
Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE);
Menu::getInstance()->getActionForOption(MenuOption::VelocityFilter)->setVisible(isUsingDDE);
+ Menu::getInstance()->getActionForOption(MenuOption::CalibrateCamera)->setVisible(isUsingDDE);
auto ddeTracker = DependencyManager::get();
ddeTracker->setIsMuted(isMuted);
ddeTracker->setEnabled(isUsingDDE && !isMuted);
@@ -3228,12 +3241,12 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
_stars.render(theCamera.getFieldOfView(), theCamera.getAspectRatio(), theCamera.getNearClip(), alpha);
}
- // draw the sky dome
- if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
- PerformanceTimer perfTimer("atmosphere");
- PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
- "Application::displaySide() ... atmosphere...");
- _environment.renderAtmospheres(theCamera);
+ // draw the sky dome
+ if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
+ PerformanceTimer perfTimer("atmosphere");
+ PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
+ "Application::displaySide() ... atmosphere...");
+ _environment.renderAtmospheres(theCamera);
}
}
@@ -4637,7 +4650,3 @@ PickRay Application::computePickRay() const {
bool Application::hasFocus() const {
return _glWidget->hasFocus();
}
-
-void Application::resizeGL() {
- this->resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
-}
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 10df094c2e..5a3756e768 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -163,7 +163,7 @@ public:
void initializeGL();
void initializeUi();
void paintGL();
- void resizeGL(int width, int height);
+ void resizeGL();
void resizeEvent(QResizeEvent * size);
@@ -194,7 +194,6 @@ public:
bool hasFocus() const;
PickRay computePickRay() const;
PickRay computeViewPickRay(float xRatio, float yRatio) const;
- void resizeGL();
bool isThrottleRendering() const;
@@ -463,7 +462,7 @@ private slots:
void setCursorVisible(bool visible);
private:
- void resetCamerasOnResizeGL(Camera& camera, int width, int height);
+ void resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size);
void updateProjectionMatrix();
void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true);
@@ -662,6 +661,7 @@ private:
QHash _acceptedExtensions;
QList _domainConnectionRefusals;
+ glm::uvec2 _renderResolution;
};
#endif // hifi_Application_h
diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp
index 2cbec1b258..995e1908a9 100644
--- a/interface/src/GLCanvas.cpp
+++ b/interface/src/GLCanvas.cpp
@@ -64,7 +64,7 @@ void GLCanvas::paintGL() {
}
void GLCanvas::resizeGL(int width, int height) {
- Application::getInstance()->resizeGL(width, height);
+ Application::getInstance()->resizeGL();
}
void GLCanvas::activeChanged(Qt::ApplicationState state) {
diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp
index 425f9d13d9..61213e7334 100644
--- a/interface/src/Menu.cpp
+++ b/interface/src/Menu.cpp
@@ -392,6 +392,9 @@ Menu::Menu() {
useAudioForMouth->setVisible(false);
QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true);
ddeFiltering->setVisible(false);
+ QAction* ddeCalibrate = addActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::CalibrateCamera, 0,
+ DependencyManager::get().data(), SLOT(calibrate()));
+ ddeCalibrate->setVisible(false);
#endif
#if defined(HAVE_FACESHIFT) || defined(HAVE_DDE)
faceTrackingMenu->addSeparator();
diff --git a/interface/src/Menu.h b/interface/src/Menu.h
index b15607df8f..96c8fedf0d 100644
--- a/interface/src/Menu.h
+++ b/interface/src/Menu.h
@@ -154,6 +154,7 @@ namespace MenuOption {
const QString Bookmarks = "Bookmarks";
const QString CascadedShadows = "Cascaded";
const QString CachesSize = "RAM Caches Size";
+ const QString CalibrateCamera = "Calibrate Camera";
const QString Chat = "Chat...";
const QString Collisions = "Collisions";
const QString Console = "Console...";
@@ -181,7 +182,7 @@ namespace MenuOption {
const QString EditEntitiesHelp = "Edit Entities Help...";
const QString Enable3DTVMode = "Enable 3DTV Mode";
const QString EnableCharacterController = "Enable avatar collisions";
- const QString EnableGlowEffect = "Enable Glow Effect (Warning: Poor Oculus Performance)";
+ const QString EnableGlowEffect = "Enable Glow Effect";
const QString EnableVRMode = "Enable VR Mode";
const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation";
const QString ExpandMyAvatarTiming = "Expand /myAvatar";
diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp
index 59d2b42a51..6ed253c1ec 100644
--- a/interface/src/devices/DdeFaceTracker.cpp
+++ b/interface/src/devices/DdeFaceTracker.cpp
@@ -20,6 +20,7 @@
#include
#include
+#include "Application.h"
#include "DdeFaceTracker.h"
#include "FaceshiftConstants.h"
#include "InterfaceLogging.h"
@@ -86,16 +87,16 @@ static const float DDE_COEFFICIENT_SCALES[] = {
3.0f, // BrowsU_L
3.0f, // BrowsU_R
1.0f, // JawFwd
- 1.5f, // JawLeft
+ 2.0f, // JawLeft
1.8f, // JawOpen
1.0f, // JawChew
- 1.5f, // JawRight
+ 2.0f, // JawRight
1.5f, // MouthLeft
1.5f, // MouthRight
1.5f, // MouthFrown_L
1.5f, // MouthFrown_R
- 1.5f, // MouthSmile_L
- 1.5f, // MouthSmile_R
+ 2.5f, // MouthSmile_L
+ 2.5f, // MouthSmile_R
1.0f, // MouthDimple_L
1.0f, // MouthDimple_R
1.0f, // LipsStretch_L
@@ -106,8 +107,8 @@ static const float DDE_COEFFICIENT_SCALES[] = {
1.0f, // LipsLowerDown
1.0f, // LipsUpperOpen
1.0f, // LipsLowerOpen
- 2.5f, // LipsFunnel
- 2.0f, // LipsPucker
+ 1.5f, // LipsFunnel
+ 2.5f, // LipsPucker
1.5f, // ChinLowerRaise
1.5f, // ChinUpperRaise
1.0f, // Sneer
@@ -135,7 +136,9 @@ struct Packet {
char name[MAX_NAME_SIZE + 1];
};
-const float STARTING_DDE_MESSAGE_TIME = 0.033f;
+static const float STARTING_DDE_MESSAGE_TIME = 0.033f;
+
+static const int CALIBRATION_SAMPLES = 150;
#ifdef WIN32
// warning C4351: new behavior: elements of array 'DdeFaceTracker::_lastEyeBlinks' will be default initialized
@@ -178,11 +181,18 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
_filteredBrowUp(0.0f),
_lastEyeBlinks(),
_filteredEyeBlinks(),
- _lastEyeCoefficients()
+ _lastEyeCoefficients(),
+ _isCalibrating(false),
+ _calibrationValues(),
+ _calibrationCount(0),
+ _calibrationBillboard(NULL),
+ _calibrationBillboardID(0),
+ _calibrationMessage(QString())
{
_coefficients.resize(NUM_FACESHIFT_BLENDSHAPES);
-
_blendshapeCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES);
+ _coefficientAverages.resize(NUM_FACESHIFT_BLENDSHAPES);
+ _calibrationValues.resize(NUM_FACESHIFT_BLENDSHAPES);
_eyeStates[0] = EYE_OPEN;
_eyeStates[1] = EYE_OPEN;
@@ -195,6 +205,10 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
DdeFaceTracker::~DdeFaceTracker() {
setEnabled(false);
+
+ if (_isCalibrating) {
+ cancelCalibration();
+ }
}
#ifdef WIN32
@@ -212,6 +226,12 @@ void DdeFaceTracker::setEnabled(bool enabled) {
return;
}
#ifdef HAVE_DDE
+
+ if (_isCalibrating) {
+ cancelCalibration();
+ }
+
+
// isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket.
_udpSocket.close();
if (enabled) {
@@ -382,10 +402,18 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
_coefficients[DDE_TO_FACESHIFT_MAPPING[i]] = packet.expressions[i];
}
+ // Calibration
+ if (_isCalibrating) {
+ addCalibrationDatum();
+ }
+ for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) {
+ _coefficients[i] -= _coefficientAverages[i];
+ }
+
// Use BrowsU_C to control both brows' up and down
float browUp = _coefficients[_browUpCenterIndex];
if (isFiltering) {
- const float BROW_VELOCITY_FILTER_STRENGTH = 0.75f;
+ const float BROW_VELOCITY_FILTER_STRENGTH = 0.5f;
float velocity = fabs(browUp - _lastBrowUp) / _averageMessageTime;
float velocityFilter = glm::clamp(velocity * BROW_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f);
_filteredBrowUp = velocityFilter * browUp + (1.0f - velocityFilter) * _filteredBrowUp;
@@ -399,11 +427,11 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
_coefficients[_browDownRightIndex] = -browUp;
// Offset jaw open coefficient
- static const float JAW_OPEN_THRESHOLD = 0.16f;
+ static const float JAW_OPEN_THRESHOLD = 0.1f;
_coefficients[_jawOpenIndex] = _coefficients[_jawOpenIndex] - JAW_OPEN_THRESHOLD;
// Offset smile coefficients
- static const float SMILE_THRESHOLD = 0.18f;
+ static const float SMILE_THRESHOLD = 0.5f;
_coefficients[_mouthSmileLeftIndex] = _coefficients[_mouthSmileLeftIndex] - SMILE_THRESHOLD;
_coefficients[_mouthSmileRightIndex] = _coefficients[_mouthSmileRightIndex] - SMILE_THRESHOLD;
@@ -430,7 +458,7 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
// Change to closing or opening states
const float EYE_CONTROL_HYSTERISIS = 0.25f;
- const float EYE_CLOSING_THRESHOLD = 0.95f;
+ const float EYE_CLOSING_THRESHOLD = 0.8f;
const float EYE_OPENING_THRESHOLD = EYE_CONTROL_THRESHOLD - EYE_CONTROL_HYSTERISIS;
if ((_eyeStates[i] == EYE_OPEN || _eyeStates[i] == EYE_OPENING) && eyeCoefficients[i] > EYE_CLOSING_THRESHOLD) {
_eyeStates[i] = EYE_CLOSING;
@@ -510,4 +538,81 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
} else {
qCWarning(interfaceapp) << "DDE Face Tracker: Decode error";
}
+
+ if (_isCalibrating && _calibrationCount > CALIBRATION_SAMPLES) {
+ finishCalibration();
+ }
+}
+
+static const int CALIBRATION_BILLBOARD_WIDTH = 240;
+static const int CALIBRATION_BILLBOARD_HEIGHT = 180;
+static const int CALIBRATION_BILLBOARD_TOP_MARGIN = 60;
+static const int CALIBRATION_BILLBOARD_LEFT_MARGIN = 30;
+static const int CALIBRATION_BILLBOARD_FONT_SIZE = 16;
+static const float CALIBRATION_BILLBOARD_ALPHA = 0.5f;
+static QString CALIBRATION_INSTRUCTION_MESSAGE = "Hold still to calibrate";
+
+void DdeFaceTracker::calibrate() {
+ if (!_isCalibrating) {
+ qCDebug(interfaceapp) << "DDE Face Tracker: Calibration started";
+
+ _isCalibrating = true;
+ _calibrationCount = 0;
+ _calibrationMessage = CALIBRATION_INSTRUCTION_MESSAGE + "\n\n";
+
+ _calibrationBillboard = new TextOverlay();
+ _calibrationBillboard->setTopMargin(CALIBRATION_BILLBOARD_TOP_MARGIN);
+ _calibrationBillboard->setLeftMargin(CALIBRATION_BILLBOARD_LEFT_MARGIN);
+ _calibrationBillboard->setFontSize(CALIBRATION_BILLBOARD_FONT_SIZE);
+ _calibrationBillboard->setText(CALIBRATION_INSTRUCTION_MESSAGE);
+ _calibrationBillboard->setAlpha(CALIBRATION_BILLBOARD_ALPHA);
+ glm::vec2 viewport = qApp->getCanvasSize();
+ _calibrationBillboard->setX((viewport.x - CALIBRATION_BILLBOARD_WIDTH) / 2);
+ _calibrationBillboard->setY((viewport.y - CALIBRATION_BILLBOARD_HEIGHT) / 2);
+ _calibrationBillboard->setWidth(CALIBRATION_BILLBOARD_WIDTH);
+ _calibrationBillboard->setHeight(CALIBRATION_BILLBOARD_HEIGHT);
+ _calibrationBillboardID = qApp->getOverlays().addOverlay(_calibrationBillboard);
+
+ for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) {
+ _calibrationValues[i] = 0.0f;
+ }
+ }
+}
+
+void DdeFaceTracker::addCalibrationDatum() {
+ const int LARGE_TICK_INTERVAL = 30;
+ const int SMALL_TICK_INTERVAL = 6;
+ int samplesLeft = CALIBRATION_SAMPLES - _calibrationCount;
+ if (samplesLeft % LARGE_TICK_INTERVAL == 0) {
+ _calibrationMessage += QString::number(samplesLeft / LARGE_TICK_INTERVAL);
+ _calibrationBillboard->setText(_calibrationMessage);
+ } else if (samplesLeft % SMALL_TICK_INTERVAL == 0) {
+ _calibrationMessage += ".";
+ _calibrationBillboard->setText(_calibrationMessage);
+ }
+
+ for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) {
+ _calibrationValues[i] += _coefficients[i];
+ }
+
+ _calibrationCount += 1;
+}
+
+void DdeFaceTracker::cancelCalibration() {
+ qApp->getOverlays().deleteOverlay(_calibrationBillboardID);
+ _calibrationBillboard = NULL;
+ _isCalibrating = false;
+ qCDebug(interfaceapp) << "DDE Face Tracker: Calibration cancelled";
+}
+
+void DdeFaceTracker::finishCalibration() {
+ qApp->getOverlays().deleteOverlay(_calibrationBillboardID);
+ _calibrationBillboard = NULL;
+ _isCalibrating = false;
+
+ for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) {
+ _coefficientAverages[i] = _calibrationValues[i] / (float)CALIBRATION_SAMPLES;
+ }
+
+ qCDebug(interfaceapp) << "DDE Face Tracker: Calibration finished";
}
diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h
index 9edbd4df58..7019802603 100644
--- a/interface/src/devices/DdeFaceTracker.h
+++ b/interface/src/devices/DdeFaceTracker.h
@@ -20,6 +20,7 @@
#include
#include
+#include
#include "FaceTracker.h"
@@ -51,6 +52,7 @@ public:
public slots:
void setEnabled(bool enabled);
+ void calibrate();
private slots:
void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
@@ -121,6 +123,17 @@ private:
float _lastEyeBlinks[2];
float _filteredEyeBlinks[2];
float _lastEyeCoefficients[2];
+ QVector _coefficientAverages;
+
+ bool _isCalibrating;
+ int _calibrationCount;
+ QVector _calibrationValues;
+ TextOverlay* _calibrationBillboard;
+ int _calibrationBillboardID;
+ QString _calibrationMessage;
+ void addCalibrationDatum();
+ void cancelCalibration();
+ void finishCalibration();
};
#endif // hifi_DdeFaceTracker_h
diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp
index 065b7499d3..f4693d3c08 100644
--- a/interface/src/devices/OculusManager.cpp
+++ b/interface/src/devices/OculusManager.cpp
@@ -627,7 +627,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
//Full texture viewport for glow effect
glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h);
- finalFbo = DependencyManager::get()->render(true);
+ finalFbo = DependencyManager::get()->render();
} else {
finalFbo = DependencyManager::get()->getPrimaryFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp
index 9d5dd2faae..5d60bf7e19 100644
--- a/interface/src/devices/TV3DManager.cpp
+++ b/interface/src/devices/TV3DManager.cpp
@@ -14,7 +14,7 @@
#include
#include
-
+#include "gpu/GLBackend.h"
#include "Application.h"
#include "TV3DManager.h"
@@ -163,10 +163,18 @@ void TV3DManager::display(Camera& whichCamera) {
glPopMatrix();
glDisable(GL_SCISSOR_TEST);
+ auto finalFbo = DependencyManager::get()->render();
+ auto fboSize = finalFbo->getSize();
+ // Get the ACTUAL device size for the BLIT
+ deviceSize = qApp->getDeviceSize();
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo));
+ glBlitFramebuffer(0, 0, fboSize.x, fboSize.y,
+ 0, 0, deviceSize.width(), deviceSize.height(),
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
// reset the viewport to how we started
glViewport(0, 0, deviceSize.width(), deviceSize.height());
-
- DependencyManager::get()->render();
}
void TV3DManager::overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal,
diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp
index 5c878b484c..1bfdf88032 100644
--- a/interface/src/ui/ApplicationOverlay.cpp
+++ b/interface/src/ui/ApplicationOverlay.cpp
@@ -190,8 +190,8 @@ void ApplicationOverlay::renderOverlay() {
Overlays& overlays = qApp->getOverlays();
_textureFov = glm::radians(_hmdUIAngularSize);
- glm::vec2 deviceSize = qApp->getCanvasSize();
- _textureAspectRatio = (float)deviceSize.x / (float)deviceSize.y;
+ glm::vec2 size = qApp->getCanvasSize();
+ _textureAspectRatio = aspect(size);
//Handle fading and deactivation/activation of UI
@@ -204,12 +204,13 @@ void ApplicationOverlay::renderOverlay() {
_overlays.buildFramebufferObject();
_overlays.bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glViewport(0, 0, size.x, size.y);
glPushMatrix(); {
const float NEAR_CLIP = -10000;
const float FAR_CLIP = 10000;
glLoadIdentity();
- glOrtho(0, deviceSize.x, deviceSize.y, 0, NEAR_CLIP, FAR_CLIP);
+ glOrtho(0, size.x, size.y, 0, NEAR_CLIP, FAR_CLIP);
glMatrixMode(GL_MODELVIEW);
@@ -269,6 +270,7 @@ void ApplicationOverlay::displayOverlayTexture() {
if (_alpha < 1.0) {
glEnable(GL_BLEND);
}
+ glViewport(0, 0, qApp->getDeviceSize().width(), qApp->getDeviceSize().height());
static const glm::vec2 topLeft(-1, 1);
static const glm::vec2 bottomRight(1, -1);
@@ -1129,8 +1131,9 @@ void ApplicationOverlay::TexturedHemisphere::cleanupVBO() {
}
void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() {
- auto deviceSize = qApp->getDeviceSize();
- if (_framebufferObject != NULL && deviceSize == _framebufferObject->size()) {
+ auto canvasSize = qApp->getCanvasSize();
+ QSize fboSize = QSize(canvasSize.x, canvasSize.y);
+ if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) {
// Already build
return;
}
@@ -1139,7 +1142,7 @@ void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() {
delete _framebufferObject;
}
- _framebufferObject = new QOpenGLFramebufferObject(deviceSize, QOpenGLFramebufferObject::Depth);
+ _framebufferObject = new QOpenGLFramebufferObject(fboSize, 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);
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
index b268ba6031..e4c476c6f7 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
@@ -450,8 +450,8 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
} else {
_viewState->endOverrideEnvironmentData();
+ auto stage = scene->getSkyStage();
if (_bestZone->getBackgroundMode() == BACKGROUND_MODE_SKYBOX) {
- auto stage = scene->getSkyStage();
stage->getSkybox()->setColor(_bestZone->getSkyboxProperties().getColorVec3());
if (_bestZone->getSkyboxProperties().getURL().isEmpty()) {
stage->getSkybox()->clearCubemap();
@@ -461,6 +461,8 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
stage->getSkybox()->setCubemap(cubeMap->getGPUTexture());
}
stage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
+ } else {
+ stage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
}
}
@@ -478,7 +480,7 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
_hasPreviousZone = false;
}
_viewState->endOverrideEnvironmentData();
- scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME);
+ scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
}
// we must call endScene while we still have the tree locked so that no one deletes a model
diff --git a/libraries/entities/src/AtmospherePropertyGroup.cpp b/libraries/entities/src/AtmospherePropertyGroup.cpp
index c1210be24e..2e0a043749 100644
--- a/libraries/entities/src/AtmospherePropertyGroup.cpp
+++ b/libraries/entities/src/AtmospherePropertyGroup.cpp
@@ -16,12 +16,19 @@
#include "EntityItemPropertiesMacros.h"
AtmospherePropertyGroup::AtmospherePropertyGroup() {
- _center = glm::vec3(0.0f);
- _innerRadius = 0.0f;
- _outerRadius = 0.0f;
- _mieScattering = 0.0f;
- _rayleighScattering = 0.0f;
- _scatteringWavelengths = glm::vec3(0.0f);
+ const glm::vec3 DEFAULT_CENTER = glm::vec3(0.0f, -1000.0f, 0.0f);
+ const float DEFAULT_INNER_RADIUS = 1000.0f;
+ const float DEFAULT_OUTER_RADIUS = 1025.0f;
+ const float DEFAULT_RAYLEIGH_SCATTERING = 0.0025f;
+ const float DEFAULT_MIE_SCATTERING = 0.0010f;
+ const glm::vec3 DEFAULT_SCATTERING_WAVELENGTHS = glm::vec3(0.650f, 0.570f, 0.475f);
+
+ _center = DEFAULT_CENTER;
+ _innerRadius = DEFAULT_INNER_RADIUS;
+ _outerRadius = DEFAULT_OUTER_RADIUS;
+ _mieScattering = DEFAULT_MIE_SCATTERING;
+ _rayleighScattering = DEFAULT_RAYLEIGH_SCATTERING;
+ _scatteringWavelengths = DEFAULT_SCATTERING_WAVELENGTHS;
_hasStars = true;
}
diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp
index c897da3ef9..b5d14e4814 100644
--- a/libraries/physics/src/EntityMotionState.cpp
+++ b/libraries/physics/src/EntityMotionState.cpp
@@ -151,10 +151,10 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
_movingStepsWithoutSimulationOwner = 0;
}
- int ownershipClaimDelay = 50; // TODO -- how to pick this? based on meters from our characterController?
+ uint32_t ownershipClaimDelay = 50; // TODO -- how to pick this? based on meters from our characterController?
if (_movingStepsWithoutSimulationOwner > ownershipClaimDelay) {
- qDebug() << "Warning -- claiming something I saw moving." << getName();
+ //qDebug() << "Warning -- claiming something I saw moving." << getName();
setShouldClaimSimulationOwnership(true);
}
@@ -178,7 +178,7 @@ void EntityMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) {
const int MAX_NUM_NON_MOVING_UPDATES = 5;
bool EntityMotionState::doesNotNeedToSendUpdate() const {
- return !_body->isActive() && _numNonMovingUpdates > MAX_NUM_NON_MOVING_UPDATES;
+ return !_body || (_body->isActive() && _numNonMovingUpdates > MAX_NUM_NON_MOVING_UPDATES);
}
bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
@@ -232,6 +232,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
_serverPosition += dt * _serverVelocity;
}
+ // TODO: compensate for simulation offset here
btTransform worldTrans = _body->getWorldTransform();
glm::vec3 position = bulletToGLM(worldTrans.getOrigin());
@@ -310,86 +311,60 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
return; // never update entities that are unknown
}
+ bool active = _body->isActive();
+ if (!active) {
+ if (_sentMoving) {
+ // make sure all derivatives are zero
+ glm::vec3 zero(0.0f);
+ _entity->setVelocity(zero);
+ _entity->setAngularVelocity(zero);
+ _entity->setAcceleration(zero);
+ }
+
+ } else {
+ float gravityLength = glm::length(_entity->getGravity());
+ float accVsGravity = glm::abs(glm::length(_measuredAcceleration) - gravityLength);
+ if (accVsGravity < ACCELERATION_EQUIVALENT_EPSILON_RATIO * gravityLength) {
+ // acceleration measured during the most recent simulation step was close to gravity.
+ if (getAccelerationNearlyGravityCount() < STEPS_TO_DECIDE_BALLISTIC) {
+ // only increment this if we haven't reached the threshold yet. this is to avoid
+ // overflowing the counter.
+ incrementAccelerationNearlyGravityCount();
+ }
+ } else {
+ // acceleration wasn't similar to this entities gravity, so reset the went-ballistic counter
+ resetAccelerationNearlyGravityCount();
+ }
+
+ // if this entity has been accelerated at close to gravity for a certain number of simulation-steps, let
+ // the entity server's estimates include gravity.
+ if (getAccelerationNearlyGravityCount() >= STEPS_TO_DECIDE_BALLISTIC) {
+ _entity->setAcceleration(_entity->getGravity());
+ } else {
+ _entity->setAcceleration(glm::vec3(0.0f));
+ }
+ }
+
+ // remember properties for local server prediction
+ _serverPosition = _entity->getPosition();
+ _serverRotation = _entity->getRotation();
+ _serverVelocity = _entity->getVelocity();
+ _serverAcceleration = _entity->getAcceleration();
+ _serverAngularVelocity = _entity->getAngularVelocity();
+
+ _sentMoving = _serverVelocity != glm::vec3(0.0f) || _serverAngularVelocity != glm::vec3(0.0f);
+
EntityItemProperties properties = _entity->getProperties();
- float gravityLength = glm::length(_entity->getGravity());
- float accVsGravity = glm::abs(glm::length(_measuredAcceleration) - gravityLength);
- if (accVsGravity < ACCELERATION_EQUIVALENT_EPSILON_RATIO * gravityLength) {
- // acceleration measured during the most recent simulation step was close to gravity.
- if (getAccelerationNearlyGravityCount() < STEPS_TO_DECIDE_BALLISTIC) {
- // only increment this if we haven't reached the threshold yet. this is to avoid
- // overflowing the counter.
- incrementAccelerationNearlyGravityCount();
- }
- } else {
- // acceleration wasn't similar to this entities gravity, so reset the went-ballistic counter
- resetAccelerationNearlyGravityCount();
- }
-
- // if this entity has been accelerated at close to gravity for a certain number of simulation-steps, let
- // the entity server's estimates include gravity.
- if (getAccelerationNearlyGravityCount() >= STEPS_TO_DECIDE_BALLISTIC) {
- _entity->setAcceleration(_entity->getGravity());
- } else {
- _entity->setAcceleration(glm::vec3(0.0f));
- }
-
- btTransform worldTrans = _body->getWorldTransform();
- _serverPosition = bulletToGLM(worldTrans.getOrigin());
- properties.setPosition(_serverPosition + ObjectMotionState::getWorldOffset());
-
- _serverRotation = bulletToGLM(worldTrans.getRotation());
+ // explicitly set the properties that changed
+ properties.setPosition(_serverPosition);
properties.setRotation(_serverRotation);
-
- bool zeroSpeed = true;
- bool zeroSpin = true;
-
- if (_body->isActive()) {
- _serverVelocity = bulletToGLM(_body->getLinearVelocity());
- _serverAngularVelocity = bulletToGLM(_body->getAngularVelocity());
-
- // if the speeds are very small we zero them out
- const float MINIMUM_EXTRAPOLATION_SPEED_SQUARED = 1.0e-4f; // 1cm/sec
- zeroSpeed = (glm::length2(_serverVelocity) < MINIMUM_EXTRAPOLATION_SPEED_SQUARED);
- if (zeroSpeed) {
- _serverVelocity = glm::vec3(0.0f);
- }
- const float MINIMUM_EXTRAPOLATION_SPIN_SQUARED = 0.004f; // ~0.01 rotation/sec
- zeroSpin = glm::length2(_serverAngularVelocity) < MINIMUM_EXTRAPOLATION_SPIN_SQUARED;
- if (zeroSpin) {
- _serverAngularVelocity = glm::vec3(0.0f);
- }
-
- _sentMoving = ! (zeroSpeed && zeroSpin);
- } else {
- _serverVelocity = _serverAngularVelocity = glm::vec3(0.0f);
- _sentMoving = false;
- }
properties.setVelocity(_serverVelocity);
- _serverGravity = _entity->getGravity();
- properties.setGravity(_entity->getGravity());
- _serverAcceleration = _entity->getAcceleration();
properties.setAcceleration(_serverAcceleration);
properties.setAngularVelocity(_serverAngularVelocity);
- auto nodeList = DependencyManager::get();
- QUuid myNodeID = nodeList->getSessionUUID();
- QUuid simulatorID = _entity->getSimulatorID();
-
- if (getShouldClaimSimulationOwnership()) {
- properties.setSimulatorID(myNodeID);
- setShouldClaimSimulationOwnership(false);
- } else if (simulatorID == myNodeID && zeroSpeed && zeroSpin) {
- // we are the simulator and the entity has stopped. give up "simulator" status
- _entity->setSimulatorID(QUuid());
- properties.setSimulatorID(QUuid());
- } else if (simulatorID == myNodeID && !_body->isActive()) {
- // it's not active. don't keep simulation ownership.
- _entity->setSimulatorID(QUuid());
- properties.setSimulatorID(QUuid());
- }
-
- // RELIABLE_SEND_HACK: count number of updates for entities at rest so we can stop sending them after some limit.
+ // RELIABLE_SEND_HACK: count number of updates for entities at rest
+ // so we can stop sending them after some limit.
if (_sentMoving) {
_numNonMovingUpdates = 0;
} else {
@@ -397,8 +372,6 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
}
if (_numNonMovingUpdates <= 1) {
// we only update lastEdited when we're sending new physics data
- // (i.e. NOT when we just simulate the positions forward, nor when we resend non-moving data)
- // NOTE: Andrew & Brad to discuss. Let's make sure we're using lastEdited, lastSimulated, and lastUpdated correctly
quint64 lastSimulated = _entity->getLastSimulated();
_entity->setLastEdited(lastSimulated);
properties.setLastEdited(lastSimulated);
@@ -415,6 +388,25 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
properties.setLastEdited(_entity->getLastEdited());
}
+ auto nodeList = DependencyManager::get();
+ QUuid myNodeID = nodeList->getSessionUUID();
+ QUuid simulatorID = _entity->getSimulatorID();
+
+ if (getShouldClaimSimulationOwnership()) {
+ // we think we should own it, so we tell the server that we do,
+ // but we don't remember that we own it...
+ // instead we expect the sever to tell us later whose ownership it has accepted
+ properties.setSimulatorID(myNodeID);
+ setShouldClaimSimulationOwnership(false);
+ } else if (simulatorID == myNodeID
+ && !_sentMoving
+ && _numNonMovingUpdates == MAX_NUM_NON_MOVING_UPDATES) {
+ // we own it, the entity has stopped, and we're sending the last non-moving update
+ // --> give up ownership
+ _entity->setSimulatorID(QUuid());
+ properties.setSimulatorID(QUuid());
+ }
+
if (EntityItem::getSendPhysicsUpdates()) {
EntityItemID id(_entity->getID());
EntityEditPacketSender* entityPacketSender = static_cast(packetSender);
diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp
index 442065cac2..06099d19dc 100644
--- a/libraries/physics/src/PhysicalEntitySimulation.cpp
+++ b/libraries/physics/src/PhysicalEntitySimulation.cpp
@@ -167,7 +167,12 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
_tempVector.push_back(motionState);
entityItr = _pendingAdds.erase(entityItr);
} else {
+<<<<<<< HEAD
// qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName();
+=======
+ // TODO: Seth to look into why this case is hit.
+ //qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName();
+>>>>>>> 72e1ea688adad9914d9994b81a96225ac411ba83
++entityItr;
}
} else {
diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp
index ea74a87286..bfd0b6cb28 100644
--- a/libraries/physics/src/PhysicsEngine.cpp
+++ b/libraries/physics/src/PhysicsEngine.cpp
@@ -147,6 +147,7 @@ void PhysicsEngine::deleteObjects(VectorOfMotionStates& objects) {
// NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
btRigidBody* body = object->getRigidBody();
object->setRigidBody(nullptr);
+ body->setMotionState(nullptr);
delete body;
object->releaseShape();
delete object;
@@ -161,6 +162,7 @@ void PhysicsEngine::deleteObjects(SetOfMotionStates& objects) {
// NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
object->setRigidBody(nullptr);
+ body->setMotionState(nullptr);
delete body;
object->releaseShape();
delete object;
diff --git a/libraries/render-utils/src/FboCache.cpp b/libraries/render-utils/src/FboCache.cpp
index de2b483573..b6cca8116b 100644
--- a/libraries/render-utils/src/FboCache.cpp
+++ b/libraries/render-utils/src/FboCache.cpp
@@ -95,4 +95,7 @@ void FboCache::setSize(const QSize& newSize) {
});
}
+const QSize& FboCache::getSize() {
+ return _size;
+}
diff --git a/libraries/render-utils/src/FboCache.h b/libraries/render-utils/src/FboCache.h
index 30278470fd..78c3194eb5 100644
--- a/libraries/render-utils/src/FboCache.h
+++ b/libraries/render-utils/src/FboCache.h
@@ -37,6 +37,8 @@ public:
// internal locks and pointers but execute no OpenGL opreations.
void lockTexture(int texture);
void releaseTexture(int texture);
+
+ const QSize& getSize();
protected:
QMap> _fboMap;
diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp
index 3040088ce5..bb18729f12 100644
--- a/libraries/render-utils/src/GlowEffect.cpp
+++ b/libraries/render-utils/src/GlowEffect.cpp
@@ -129,7 +129,7 @@ static void maybeRelease(const gpu::FramebufferPointer& fbo) {
}
}
-gpu::FramebufferPointer GlowEffect::render(bool toTexture) {
+gpu::FramebufferPointer GlowEffect::render() {
PerformanceTimer perfTimer("glowEffect");
auto textureCache = DependencyManager::get();
@@ -151,26 +151,24 @@ gpu::FramebufferPointer GlowEffect::render(bool toTexture) {
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
- gpu::FramebufferPointer destFBO = toTexture ?
- textureCache->getSecondaryFramebuffer() : nullptr;
+ gpu::FramebufferPointer destFBO = textureCache->getSecondaryFramebuffer();
if (!_enabled || _isEmpty) {
// copy the primary to the screen
- if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO);
+ if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO));
- glBlitFramebuffer(0, 0, framebufferSize.width(), framebufferSize.height(), 0, 0, framebufferSize.width(), framebufferSize.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO);
+ glBlitFramebuffer(0, 0, framebufferSize.width(), framebufferSize.height(),
+ 0, 0, framebufferSize.width(), framebufferSize.height(),
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
} else {
- maybeBind(destFBO);
- if (!destFBO) {
- //destFBO->getSize();
- glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
- }
+ glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO));
+ glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
renderFullscreenQuad();
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
- maybeRelease(destFBO);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
} else {
// diffuse into the secondary/tertiary (alternating between frames)
@@ -199,22 +197,18 @@ gpu::FramebufferPointer GlowEffect::render(bool toTexture) {
_diffuseProgram->release();
}
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ destFBO = oldDiffusedFBO;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
// add diffused texture to the primary
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(newDiffusedFBO->getRenderBuffer(0)));
- if (toTexture) {
- destFBO = oldDiffusedFBO;
- }
- maybeBind(destFBO);
- if (!destFBO) {
- glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
- }
+ glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO));
+ glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
_addSeparateProgram->bind();
renderFullscreenQuad();
_addSeparateProgram->release();
- maybeRelease(destFBO);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
diff --git a/libraries/render-utils/src/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h
index 1cee7b2e9d..73c512ecf5 100644
--- a/libraries/render-utils/src/GlowEffect.h
+++ b/libraries/render-utils/src/GlowEffect.h
@@ -52,7 +52,7 @@ public:
/// Renders the glow effect. To be called after rendering the scene.
/// \param toTexture whether to render to a texture, rather than to the frame buffer
/// \return the framebuffer object to which we rendered, or NULL if to the frame buffer
- gpu::FramebufferPointer render(bool toTexture = false);
+ gpu::FramebufferPointer render();
public slots:
void toggleGlowEffect(bool enabled);
diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h
index a06f6f26cf..9b7cca70ee 100644
--- a/libraries/shared/src/GLMHelpers.h
+++ b/libraries/shared/src/GLMHelpers.h
@@ -117,6 +117,11 @@ QMatrix4x4 fromGlm(const glm::mat4 & m);
QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size);
+template
+float aspect(const T& t) {
+ return (float)t.x / (float)t.y;
+}
+
#define YAW(euler) euler.y
#define PITCH(euler) euler.x
#define ROLL(euler) euler.z
diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp
index 9b32aca96f..7d13a00324 100644
--- a/libraries/ui/src/OffscreenUi.cpp
+++ b/libraries/ui/src/OffscreenUi.cpp
@@ -117,8 +117,13 @@ void OffscreenUi::addImportPath(const QString& path) {
void OffscreenUi::resize(const QSize& newSize) {
makeCurrent();
- // Clear out any fbos with the old size
qreal pixelRatio = _renderControl->_renderWindow ? _renderControl->_renderWindow->devicePixelRatio() : 1.0;
+ QSize newOffscreenSize = newSize * pixelRatio;
+ if (newOffscreenSize == _fboCache.getSize()) {
+ return;
+ }
+
+ // Clear out any fbos with the old size
qDebug() << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height() << " with pixel ratio " << pixelRatio;
_fboCache.setSize(newSize * pixelRatio);