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 5d2ae13cde..df2042350e 100644
--- a/examples/grab.js
+++ b/examples/grab.js
@@ -179,7 +179,7 @@ function update(deltaTime) {
if (distanceToTarget > CLOSE_ENOUGH) {
// compute current velocity in the direction we want to move
velocityTowardTarget = Vec3.dot(currentVelocity, Vec3.normalize(dPosition));
- velocityTowardTarget = Vec3.multiply(dPosition, velocityTowardTarget);
+ velocityTowardTarget = Vec3.multiply(Vec3.normalize(dPosition), velocityTowardTarget);
// compute the speed we would like to be going toward the target position
desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE);
@@ -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/harmonicOscillator.js b/examples/harmonicOscillator.js
index 0ffbce8beb..653c2db939 100644
--- a/examples/harmonicOscillator.js
+++ b/examples/harmonicOscillator.js
@@ -16,8 +16,7 @@
var ball, disc;
var time = 0.0;
var range = 1.0;
-var speed = 0.5;
-
+var omega = 2.0 * Math.PI / 32.0;
var basePosition = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
@@ -25,35 +24,44 @@ ball = Entities.addEntity(
{ type: "Box",
position: basePosition,
dimensions: { x: 0.1, y: 0.1, z: 0.1 },
- color: { red: 255, green: 0, blue: 255 }
+ color: { red: 255, green: 0, blue: 255 },
+ collisionsWillMove: false,
+ ignoreForCollisions: true
});
disc = Entities.addEntity(
{ type: "Sphere",
position: basePosition,
- dimensions: { x: range, y: range / 20.0, z: range },
+ dimensions: { x: range * 0.8, y: range / 20.0, z: range * 0.8},
color: { red: 128, green: 128, blue: 128 }
});
+function randomColor() {
+ return { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 };
+}
+
function update(deltaTime) {
- time += deltaTime * speed;
+ time += deltaTime;
if (!ball.isKnownID) {
ball = Entities.identifyEntity(ball);
}
- rotation = Quat.angleAxis(time/Math.PI * 180.0, { x: 0, y: 1, z: 0 });
+ rotation = Quat.angleAxis(time * omega /Math.PI * 180.0, { x: 0, y: 1, z: 0 });
Entities.editEntity(ball,
{
- color: { red: 255 * (Math.sin(time)/2.0 + 0.5),
- green: 255 - 255 * (Math.sin(time)/2.0 + 0.5),
+ color: { red: 255 * (Math.sin(time * omega)/2.0 + 0.5),
+ green: 255 - 255 * (Math.sin(time * omega)/2.0 + 0.5),
blue: 0 },
- position: { x: basePosition.x + Math.sin(time) / 2.0 * range,
+ position: { x: basePosition.x + Math.sin(time * omega) / 2.0 * range,
y: basePosition.y,
- z: basePosition.z + Math.cos(time) / 2.0 * range },
- velocity: { x: Math.cos(time)/2.0 * range,
+ z: basePosition.z + Math.cos(time * omega) / 2.0 * range },
+ velocity: { x: Math.cos(time * omega)/2.0 * range * omega,
y: 0.0,
- z: -Math.sin(time)/2.0 * range },
+ z: -Math.sin(time * omega)/2.0 * range * omega},
rotation: rotation
});
+ if (Math.random() < 0.007) {
+ Entities.editEntity(disc, { color: randomColor() });
+ }
}
function scriptEnding() {
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 70af987243..f3ea18aef3 100644
--- a/examples/libraries/entitySelectionTool.js
+++ b/examples/libraries/entitySelectionTool.js
@@ -203,7 +203,7 @@ SelectionManager = (function() {
try {
listeners[i]();
} catch (e) {
- print("got exception");
+ print("EntitySelectionTool got exception: " + JSON.stringify(e));
}
}
};
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 8d660848f2..cc62490b64 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -692,6 +692,9 @@ Application::~Application() {
nodeThread->quit();
nodeThread->wait();
+ Leapmotion::destroy();
+ RealSense::destroy();
+
qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages
}
@@ -809,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();
}
});
}
@@ -827,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);
@@ -912,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");
@@ -957,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() {
@@ -1821,7 +1836,7 @@ void Application::setFullscreen(bool fullscreen) {
}
void Application::setEnable3DTVMode(bool enable3DTVMode) {
- resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
+ resizeGL();
}
void Application::setEnableVRMode(bool enableVRMode) {
@@ -1846,7 +1861,7 @@ void Application::setEnableVRMode(bool enableVRMode) {
_myCamera.setHmdRotation(glm::quat());
}
- resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
+ resizeGL();
updateCursorVisibility();
}
@@ -1931,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);
@@ -2644,7 +2660,10 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
if (rootCode) {
VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, rootDetails);
- AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
+ AACube serverBounds(glm::vec3(rootDetails.x * TREE_SCALE,
+ rootDetails.y * TREE_SCALE,
+ rootDetails.z * TREE_SCALE),
+ rootDetails.s * TREE_SCALE);
ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
@@ -2685,7 +2704,6 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
// only send to the NodeTypes that are serverType
if (node->getActiveSocket() && node->getType() == serverType) {
-
// get the server bounds for this server
QUuid nodeUUID = node->getUUID();
@@ -2707,7 +2725,12 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
if (rootCode) {
VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, rootDetails);
- AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
+ AACube serverBounds(glm::vec3(rootDetails.x * TREE_SCALE,
+ rootDetails.y * TREE_SCALE,
+ rootDetails.z * TREE_SCALE),
+ rootDetails.s * TREE_SCALE);
+
+
ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
@@ -2753,7 +2776,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
}
// set up the packet for sending...
unsigned char* endOfQueryPacket = queryPacket;
-
+
// insert packet type/version and node UUID
endOfQueryPacket += populatePacketHeader(reinterpret_cast(endOfQueryPacket), packetType);
@@ -3217,12 +3240,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);
}
}
@@ -4625,7 +4648,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/DeviceTracker.cpp b/interface/src/devices/DeviceTracker.cpp
index 265a77b362..2a956a42de 100644
--- a/interface/src/devices/DeviceTracker.cpp
+++ b/interface/src/devices/DeviceTracker.cpp
@@ -66,6 +66,14 @@ DeviceTracker::ID DeviceTracker::registerDevice(const Name& name, DeviceTracker*
return deviceID;
}
+void DeviceTracker::destroyDevice(const Name& name) {
+ DeviceTracker::ID deviceID = getDeviceID(name);
+ if (deviceID != INVALID_DEVICE) {
+ delete Singleton::get()->_devicesVector[getDeviceID(name)];
+ Singleton::get()->_devicesVector[getDeviceID(name)] = nullptr;
+ }
+}
+
void DeviceTracker::updateAll() {
//TODO C++11 for (auto deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) {
for (Vector::iterator deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) {
diff --git a/interface/src/devices/DeviceTracker.h b/interface/src/devices/DeviceTracker.h
index 2e0f69b371..b28e22b06d 100644
--- a/interface/src/devices/DeviceTracker.h
+++ b/interface/src/devices/DeviceTracker.h
@@ -79,6 +79,8 @@ public:
/// INVALID_DEVICE_NAME if the name is already taken
static ID registerDevice(const Name& name, DeviceTracker* tracker);
+ static void destroyDevice(const Name& name);
+
// DeviceTracker interface
virtual void update();
diff --git a/interface/src/devices/Leapmotion.cpp b/interface/src/devices/Leapmotion.cpp
index 04cd51a484..cb99cf324d 100644
--- a/interface/src/devices/Leapmotion.cpp
+++ b/interface/src/devices/Leapmotion.cpp
@@ -50,6 +50,11 @@ void Leapmotion::init() {
}
}
+// static
+void Leapmotion::destroy() {
+ DeviceTracker::destroyDevice(NAME);
+}
+
// static
Leapmotion* Leapmotion::getInstance() {
DeviceTracker* device = DeviceTracker::getDevice(NAME);
diff --git a/interface/src/devices/Leapmotion.h b/interface/src/devices/Leapmotion.h
index a0c75da38f..266b9beb87 100644
--- a/interface/src/devices/Leapmotion.h
+++ b/interface/src/devices/Leapmotion.h
@@ -26,6 +26,7 @@ public:
static const Name NAME;
static void init();
+ static void destroy();
/// Leapmotion MotionTracker factory
static Leapmotion* getInstance();
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/RealSense.cpp b/interface/src/devices/RealSense.cpp
index 8e9cd85451..d9b1486f09 100644
--- a/interface/src/devices/RealSense.cpp
+++ b/interface/src/devices/RealSense.cpp
@@ -54,6 +54,11 @@ void RealSense::init() {
}
}
+// static
+void RealSense::destroy() {
+ DeviceTracker::destroyDevice(NAME);
+}
+
// static
RealSense* RealSense::getInstance() {
DeviceTracker* device = DeviceTracker::getDevice(NAME);
diff --git a/interface/src/devices/RealSense.h b/interface/src/devices/RealSense.h
index 20111365d0..c958ab1e53 100644
--- a/interface/src/devices/RealSense.h
+++ b/interface/src/devices/RealSense.h
@@ -32,6 +32,7 @@ public:
static const Name NAME;
static void init();
+ static void destroy();
/// RealSense MotionTracker factory
static RealSense* getInstance();
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 0fb9296b64..e4c476c6f7 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
#include "EntityTreeRenderer.h"
@@ -449,15 +450,19 @@ 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();
} else {
- stage->getSkybox()->clearCubemap(); // NOTE: this should be changed to do something to set the cubemap
+ // Update the Texture of the Skybox with the one pointed by this zone
+ auto cubeMap = DependencyManager::get()->getTexture(_bestZone->getSkyboxProperties().getURL(), CUBE_TEXTURE);
+ stage->getSkybox()->setCubemap(cubeMap->getGPUTexture());
}
stage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
+ } else {
+ stage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
}
}
@@ -475,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/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp
index c26dcacd4c..4a8a2fc53d 100644
--- a/libraries/fbx/src/OBJReader.cpp
+++ b/libraries/fbx/src/OBJReader.cpp
@@ -386,8 +386,9 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi
done:
if (faces.count() == 0) { // empty mesh
mesh.parts.pop_back();
+ } else {
+ faceGroups.append(faces); // We're done with this group. Add the faces.
}
- 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;
}
diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp
index 23cfef7764..ef272bb708 100644
--- a/libraries/gpu/src/gpu/GLBackendState.cpp
+++ b/libraries/gpu/src/gpu/GLBackendState.cpp
@@ -479,6 +479,7 @@ void GLBackend::getCurrentGLState(State::Data& state) {
void GLBackend::syncPipelineStateCache() {
State::Data state;
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
getCurrentGLState(state);
State::Signature signature = State::evalSignature(state);
diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp
index 4387821cfd..69f2b33d1b 100755
--- a/libraries/gpu/src/gpu/GLBackendTexture.cpp
+++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp
@@ -373,7 +373,6 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
-
if (needUpdate) {
if (texture.isStoredMipAvailable(0)) {
Texture::PixelsPointer mip = texture.accessStoredMip(0);
diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h
index 883b7c7098..19add9a47e 100755
--- a/libraries/gpu/src/gpu/Texture.h
+++ b/libraries/gpu/src/gpu/Texture.h
@@ -68,11 +68,11 @@ public:
uint8 _maxMip = MAX_MIP_LEVEL;
Desc() {}
- Desc(const Filter filter) : _filter(filter) {}
+ Desc(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _filter(filter), _wrapModeU(wrap), _wrapModeV(wrap), _wrapModeW(wrap) {}
};
Sampler() {}
- Sampler(const Filter filter) : _desc(filter) {}
+ Sampler(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _desc(filter, wrap) {}
Sampler(const Desc& desc) : _desc(desc) {}
~Sampler() {}
diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp
index d27bdd4372..55572a5122 100755
--- a/libraries/model/src/model/Material.cpp
+++ b/libraries/model/src/model/Material.cpp
@@ -92,15 +92,3 @@ void Material::setTextureView(MapChannel channel, const gpu::TextureView& view)
_textureMap[channel] = view;
}
-// TextureStorage
-TextureStorage::TextureStorage(const QUrl& url) : gpu::Texture::Storage(), _url(url) {
- init();
-}
-
-TextureStorage::~TextureStorage() {
-}
-
-void TextureStorage::init() {
- _gpuTexture = TexturePointer(Texture::createFromStorage(this));
-}
-
diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h
index 7e4417b55b..ea0ab808e9 100755
--- a/libraries/model/src/model/Material.h
+++ b/libraries/model/src/model/Material.h
@@ -23,27 +23,6 @@
namespace model {
-typedef glm::vec3 Color;
-
-// TextureStorage is a specialized version of the gpu::Texture::Storage
-// It adds the URL and the notion that it owns the gpu::Texture
-class TextureStorage : public gpu::Texture::Storage {
-public:
- TextureStorage(const QUrl& url);
- ~TextureStorage();
-
- const QUrl& getUrl() const { return _url; }
- const gpu::TexturePointer& getGPUTexture() const { return _gpuTexture; }
-
-protected:
- gpu::TexturePointer _gpuTexture;
- QUrl _url;
- void init();
-};
-typedef std::shared_ptr< TextureStorage > TextureStoragePointer;
-
-
-
class Material {
public:
typedef gpu::BufferView UniformBufferView;
@@ -62,6 +41,7 @@ public:
NUM_MAPS,
};
typedef std::map TextureMap;
+ typedef std::bitset MapFlags;
enum FlagBit {
DIFFUSE_BIT = 0,
diff --git a/libraries/model/src/model/Skybox.cpp b/libraries/model/src/model/Skybox.cpp
index d10b97a455..00a64c9606 100755
--- a/libraries/model/src/model/Skybox.cpp
+++ b/libraries/model/src/model/Skybox.cpp
@@ -21,6 +21,7 @@ using namespace model;
Skybox::Skybox() {
+/* // PLease create a default engineer skybox
_cubemap.reset( gpu::Texture::createCube(gpu::Element::COLOR_RGBA_32, 1));
unsigned char texels[] = {
255, 0, 0, 255,
@@ -30,7 +31,7 @@ Skybox::Skybox() {
0, 255, 0, 255,
255, 0, 255, 255,
};
- _cubemap->assignStoredMip(0, gpu::Element::COLOR_RGBA_32, sizeof(texels), texels);
+ _cubemap->assignStoredMip(0, gpu::Element::COLOR_RGBA_32, sizeof(texels), texels);*/
}
void Skybox::setColor(const Color& color) {
@@ -47,7 +48,7 @@ void Skybox::clearCubemap() {
void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) {
- if (skybox.getCubemap()) {
+ if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) {
static gpu::PipelinePointer thePipeline;
static gpu::BufferPointer theBuffer;
static gpu::Stream::FormatPointer theFormat;
diff --git a/libraries/model/src/model/Skybox.slf b/libraries/model/src/model/Skybox.slf
index 452b9daebe..03f7a5ef8a 100755
--- a/libraries/model/src/model/Skybox.slf
+++ b/libraries/model/src/model/Skybox.slf
@@ -18,7 +18,8 @@ varying vec3 color;
void main(void) {
- vec4 texel = textureCube(cubeMap, normalize(normal));
- gl_FragData[0] = texel;
- // gl_FragData[0] = vec4(normal, 1.0);
+ vec3 coord = normalize(normal);
+ vec4 texel = textureCube(cubeMap, coord);
+ // gl_FragData[0] = vec4(texel.xyz * color, texel.w);
+ gl_FragData[0] = vec4(texel.xyz, 1.0);
}
diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp
index c29ebfe83e..e5d23e9191 100644
--- a/libraries/model/src/model/Stage.cpp
+++ b/libraries/model/src/model/Stage.cpp
@@ -190,7 +190,8 @@ const float NUM_HOURS_PER_DAY = 24.0f;
const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f;
SunSkyStage::SunSkyStage() :
- _sunLight(new Light())
+ _sunLight(new Light()),
+ _skybox(new Skybox())
{
_sunLight->setType(Light::SUN);
@@ -290,6 +291,19 @@ void SunSkyStage::updateGraphicsObject() const {
_sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f));
}
+ // Background
+ switch (getBackgroundMode()) {
+ case NO_BACKGROUND: {
+ break;
+ }
+ case SKY_DOME: {
+ break;
+ }
+ case SKY_BOX: {
+ break;
+ }
+ };
+
static int firstTime = 0;
if (firstTime == 0) {
firstTime++;
diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h
index b6a19b49cd..a5f39cb825 100644
--- a/libraries/model/src/model/Stage.h
+++ b/libraries/model/src/model/Stage.h
@@ -223,11 +223,11 @@ public:
const SkyboxPointer& getSkybox() const { valid(); return _skybox; }
protected:
- BackgroundMode _backgroundMode = SKY_DOME;
+ BackgroundMode _backgroundMode = SKY_BOX;
LightPointer _sunLight;
AtmospherePointer _atmosphere;
- SkyboxPointer _skybox;
+ mutable SkyboxPointer _skybox;
gpu::PipelinePointer _skyPipeline;
diff --git a/libraries/model/src/model/TextureStorage.cpp b/libraries/model/src/model/TextureStorage.cpp
new file mode 100755
index 0000000000..499054c34b
--- /dev/null
+++ b/libraries/model/src/model/TextureStorage.cpp
@@ -0,0 +1,28 @@
+//
+// TextureStorage.cpp
+// libraries/model/src/model
+//
+// Created by Sam Gateau on 5/6/2015.
+// Copyright 2014 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+#include "TextureStorage.h"
+
+using namespace model;
+using namespace gpu;
+
+// TextureStorage
+TextureStorage::TextureStorage() : Texture::Storage(),
+ _gpuTexture(Texture::createFromStorage(this))
+{}
+
+TextureStorage::~TextureStorage() {
+}
+
+void TextureStorage::reset(const QUrl& url, const TextureUsage& usage) {
+ _url = url;
+ _usage = usage;
+}
+
diff --git a/libraries/model/src/model/TextureStorage.h b/libraries/model/src/model/TextureStorage.h
new file mode 100755
index 0000000000..2b19a6cc1d
--- /dev/null
+++ b/libraries/model/src/model/TextureStorage.h
@@ -0,0 +1,56 @@
+//
+// TextureStorage.h
+// libraries/model/src/model
+//
+// Created by Sam Gateau on 5/6/2015.
+// Copyright 2014 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+#ifndef hifi_model_TextureStorage_h
+#define hifi_model_TextureStorage_h
+
+#include "gpu/Texture.h"
+
+#include "Material.h"
+
+#include
+
+namespace model {
+
+typedef glm::vec3 Color;
+
+class TextureUsage {
+public:
+ gpu::Texture::Type _type{ gpu::Texture::TEX_2D };
+ Material::MapFlags _materialUsage{ Material::DIFFUSE_MAP };
+
+ int _environmentUsage = 0;
+};
+
+// TextureStorage is a specialized version of the gpu::Texture::Storage
+// It provides the mechanism to create a texture from a Url and the intended usage
+// that guides the internal format used
+class TextureStorage : public gpu::Texture::Storage {
+public:
+ TextureStorage();
+ ~TextureStorage();
+
+ const QUrl& getUrl() const { return _url; }
+ const gpu::Texture::Type getType() const { return _usage._type; }
+ const gpu::TexturePointer& getGPUTexture() const { return _gpuTexture; }
+
+ void reset(const QUrl& url, const TextureUsage& usage);
+
+protected:
+ gpu::TexturePointer _gpuTexture;
+ TextureUsage _usage;
+ QUrl _url;
+};
+typedef std::shared_ptr< TextureStorage > TextureStoragePointer;
+
+};
+
+#endif // hifi_model_TextureStorage_h
+
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 ed7b986800..50e81b4788 100644
--- a/libraries/physics/src/PhysicalEntitySimulation.cpp
+++ b/libraries/physics/src/PhysicalEntitySimulation.cpp
@@ -167,7 +167,8 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
_tempVector.push_back(motionState);
entityItr = _pendingAdds.erase(entityItr);
} else {
- 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();
++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/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp
index bd243cbe88..c88050f7fb 100644
--- a/libraries/render-utils/src/TextureCache.cpp
+++ b/libraries/render-utils/src/TextureCache.cpp
@@ -417,17 +417,23 @@ void ImageReader::run() {
return;
}
- // enforce a fixed maximum area (1024 * 2048)
- const int MAXIMUM_AREA_SIZE = 2097152;
int imageArea = image.width() * image.height();
- if (imageArea > MAXIMUM_AREA_SIZE) {
- float scaleRatio = sqrtf((float)MAXIMUM_AREA_SIZE) / sqrtf((float)imageArea);
- int resizeWidth = static_cast(std::floor(scaleRatio * static_cast(image.width())));
- int resizeHeight = static_cast(std::floor(scaleRatio * static_cast(image.height())));
- qCDebug(renderutils) << "Image greater than maximum size:" << _url << image.width() << image.height() <<
- " scaled to:" << resizeWidth << resizeHeight;
- image = image.scaled(resizeWidth, resizeHeight, Qt::IgnoreAspectRatio);
- imageArea = image.width() * image.height();
+ auto ntex = dynamic_cast(&*texture);
+ if (ntex && (ntex->getType() == CUBE_TEXTURE)) {
+ qCDebug(renderutils) << "Cube map size:" << _url << image.width() << image.height();
+ } else {
+
+ // enforce a fixed maximum area (1024 * 2048)
+ const int MAXIMUM_AREA_SIZE = 2097152;
+ if (imageArea > MAXIMUM_AREA_SIZE) {
+ float scaleRatio = sqrtf((float)MAXIMUM_AREA_SIZE) / sqrtf((float)imageArea);
+ int resizeWidth = static_cast(std::floor(scaleRatio * static_cast(image.width())));
+ int resizeHeight = static_cast(std::floor(scaleRatio * static_cast(image.height())));
+ qCDebug(renderutils) << "Image greater than maximum size:" << _url << image.width() << image.height() <<
+ " scaled to:" << resizeWidth << resizeHeight;
+ image = image.scaled(resizeWidth, resizeHeight, Qt::IgnoreAspectRatio);
+ imageArea = image.width() * image.height();
+ }
}
const int EIGHT_BIT_MAXIMUM = 255;
@@ -507,6 +513,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
imageLoaded(image);
if ((_width > 0) && (_height > 0)) {
+
bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
@@ -515,9 +522,18 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA));
}
- _gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
- _gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
- _gpuTexture->autoGenerateMips(-1);
+
+ if (_type == CUBE_TEXTURE) {
+ if (_height >= (6 * _width)) {
+ _gpuTexture = gpu::TexturePointer(gpu::Texture::createCube(formatGPU, image.width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP)));
+ _gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
+ _gpuTexture->autoGenerateMips(-1);
+ }
+ } else {
+ _gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
+ _gpuTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
+ _gpuTexture->autoGenerateMips(-1);
+ }
}
}
diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h
index e25a640ae7..3ff184c621 100644
--- a/libraries/render-utils/src/TextureCache.h
+++ b/libraries/render-utils/src/TextureCache.h
@@ -27,7 +27,7 @@ class NetworkTexture;
typedef QSharedPointer NetworkTexturePointer;
-enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, SPLAT_TEXTURE };
+enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, SPLAT_TEXTURE, CUBE_TEXTURE };
/// Stores cached textures, including render-to-texture targets.
class TextureCache : public ResourceCache, public Dependency {
@@ -164,7 +164,7 @@ public:
int getOriginalHeight() const { return _originalHeight; }
int getWidth() const { return _width; }
int getHeight() const { return _height; }
-
+ TextureType getType() const { return _type; }
protected:
virtual void downloadFinished(QNetworkReply* reply);
diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp
index 2461487414..ad76dbcc38 100644
--- a/libraries/script-engine/src/SceneScriptingInterface.cpp
+++ b/libraries/script-engine/src/SceneScriptingInterface.cpp
@@ -13,6 +13,9 @@
#include "SceneScriptingInterface.h"
+#include "SceneScriptingInterface.h"
+
+
void SceneScriptingInterface::setStageOrientation(const glm::quat& orientation) {
_skyStage->setOriginOrientation(orientation);
}
@@ -86,6 +89,29 @@ bool SceneScriptingInterface::isStageSunModelEnabled() const {
return _skyStage->isSunModelEnabled();
}
+void SceneScriptingInterface::setBackgroundMode(const QString& mode) {
+ if (mode == QString("inherit")) {
+ _skyStage->setBackgroundMode(model::SunSkyStage::NO_BACKGROUND);
+ } else if (mode == QString("atmosphere")) {
+ _skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME);
+ } else if (mode == QString("skybox")) {
+ _skyStage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
+ }
+}
+
+QString SceneScriptingInterface::getBackgroundMode() const {
+ switch (_skyStage->getBackgroundMode()) {
+ case model::SunSkyStage::NO_BACKGROUND:
+ return QString("inherit");
+ case model::SunSkyStage::SKY_DOME:
+ return QString("atmosphere");
+ case model::SunSkyStage::SKY_BOX:
+ return QString("skybox");
+ default:
+ return QString("inherit");
+ };
+}
+
model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const {
return _skyStage;
}
diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h
index c384153a0f..50aaae83ff 100644
--- a/libraries/script-engine/src/SceneScriptingInterface.h
+++ b/libraries/script-engine/src/SceneScriptingInterface.h
@@ -57,7 +57,8 @@ public:
Q_INVOKABLE glm::vec3 getKeyLightDirection() const;
-
+ Q_INVOKABLE void setBackgroundMode(const QString& mode);
+ Q_INVOKABLE QString getBackgroundMode() const;
model::SunSkyStagePointer getSkyStage() const;
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);