Merge branch 'master' of https://github.com/highfidelity/hifi into fix_wireframe

This commit is contained in:
Atlante45 2015-05-11 14:20:16 +02:00
commit f941ca9601
49 changed files with 619 additions and 260 deletions

View file

@ -32,7 +32,7 @@ var BUTTON_SIZE = 32;
var PADDING = 3; var PADDING = 3;
var offButton = Overlays.addOverlay("image", { 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), y: screenSize.y- (BUTTON_SIZE + PADDING),
width: BUTTON_SIZE, width: BUTTON_SIZE,
height: BUTTON_SIZE, height: BUTTON_SIZE,
@ -40,6 +40,17 @@ var offButton = Overlays.addOverlay("image", {
color: { red: 255, green: 255, blue: 255}, color: { red: 255, green: 255, blue: 255},
alpha: 1 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", { var diceButton = Overlays.addOverlay("image", {
x: screenSize.x / 2 + PADDING, x: screenSize.x / 2 + PADDING,
y: screenSize.y - (BUTTON_SIZE + PADDING), y: screenSize.y - (BUTTON_SIZE + PADDING),
@ -108,6 +119,8 @@ function mousePressEvent(event) {
if (clickedOverlay == offButton) { if (clickedOverlay == offButton) {
deleteDice(); deleteDice();
Script.stop(); Script.stop();
} else if (clickedOverlay == deleteButton) {
deleteDice();
} else if (clickedOverlay == diceButton) { } else if (clickedOverlay == diceButton) {
var HOW_HARD = 2.0; var HOW_HARD = 2.0;
var position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); var position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
@ -120,6 +133,7 @@ function mousePressEvent(event) {
function scriptEnding() { function scriptEnding() {
Overlays.deleteOverlay(offButton); Overlays.deleteOverlay(offButton);
Overlays.deleteOverlay(diceButton); Overlays.deleteOverlay(diceButton);
Overlays.deleteOverlay(deleteButton);
} }
Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity);

View file

@ -179,7 +179,7 @@ function update(deltaTime) {
if (distanceToTarget > CLOSE_ENOUGH) { if (distanceToTarget > CLOSE_ENOUGH) {
// compute current velocity in the direction we want to move // compute current velocity in the direction we want to move
velocityTowardTarget = Vec3.dot(currentVelocity, Vec3.normalize(dPosition)); 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 // compute the speed we would like to be going toward the target position
desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE); desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE);
@ -193,12 +193,15 @@ function update(deltaTime) {
// Add Damping // Add Damping
newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE)); newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE));
// Update entity // Update entity
} else {
//add damping to angular velocity: newVelocity = entityProps.velocity;
} }
if (shouldRotate) { if (shouldRotate) {
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE)); angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
} else {
angularVelocity = entityProps.angularVelocity;
} }
Entities.editEntity(grabbedEntity, { Entities.editEntity(grabbedEntity, {
velocity: newVelocity, velocity: newVelocity,
angularVelocity: angularVelocity angularVelocity: angularVelocity

View file

@ -16,8 +16,7 @@
var ball, disc; var ball, disc;
var time = 0.0; var time = 0.0;
var range = 1.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())); var basePosition = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
@ -25,35 +24,44 @@ ball = Entities.addEntity(
{ type: "Box", { type: "Box",
position: basePosition, position: basePosition,
dimensions: { x: 0.1, y: 0.1, z: 0.1 }, 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( disc = Entities.addEntity(
{ type: "Sphere", { type: "Sphere",
position: basePosition, 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 } 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) { function update(deltaTime) {
time += deltaTime * speed; time += deltaTime;
if (!ball.isKnownID) { if (!ball.isKnownID) {
ball = Entities.identifyEntity(ball); 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, Entities.editEntity(ball,
{ {
color: { red: 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)/2.0 + 0.5), green: 255 - 255 * (Math.sin(time * omega)/2.0 + 0.5),
blue: 0 }, 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, y: basePosition.y,
z: basePosition.z + Math.cos(time) / 2.0 * range }, z: basePosition.z + Math.cos(time * omega) / 2.0 * range },
velocity: { x: Math.cos(time)/2.0 * range, velocity: { x: Math.cos(time * omega)/2.0 * range * omega,
y: 0.0, y: 0.0,
z: -Math.sin(time)/2.0 * range }, z: -Math.sin(time * omega)/2.0 * range * omega},
rotation: rotation rotation: rotation
}); });
if (Math.random() < 0.007) {
Entities.editEntity(disc, { color: randomColor() });
}
} }
function scriptEnding() { function scriptEnding() {

View file

@ -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) { function createEmitNumberPropertyUpdateFunction(propertyName) {
return function() { return function() {
EventBridge.emitWebEvent( EventBridge.emitWebEvent(
@ -286,6 +300,8 @@
var elZoneAtmosphereScatteringWavelengthsX = document.getElementById("property-zone-atmosphere-scattering-wavelengths-x"); var elZoneAtmosphereScatteringWavelengthsX = document.getElementById("property-zone-atmosphere-scattering-wavelengths-x");
var elZoneAtmosphereScatteringWavelengthsY = document.getElementById("property-zone-atmosphere-scattering-wavelengths-y"); var elZoneAtmosphereScatteringWavelengthsY = document.getElementById("property-zone-atmosphere-scattering-wavelengths-y");
var elZoneAtmosphereScatteringWavelengthsZ = document.getElementById("property-zone-atmosphere-scattering-wavelengths-z"); var elZoneAtmosphereScatteringWavelengthsZ = document.getElementById("property-zone-atmosphere-scattering-wavelengths-z");
var elZoneAtmosphereHasStars = document.getElementById("property-zone-atmosphere-has-stars");
if (window.EventBridge !== undefined) { if (window.EventBridge !== undefined) {
EventBridge.scriptEventReceived.connect(function(data) { EventBridge.scriptEventReceived.connect(function(data) {
@ -486,7 +502,7 @@
elZoneAtmosphereScatteringWavelengthsX.value = properties.atmosphere.scatteringWavelengths.x; elZoneAtmosphereScatteringWavelengthsX.value = properties.atmosphere.scatteringWavelengths.x;
elZoneAtmosphereScatteringWavelengthsY.value = properties.atmosphere.scatteringWavelengths.y; elZoneAtmosphereScatteringWavelengthsY.value = properties.atmosphere.scatteringWavelengths.y;
elZoneAtmosphereScatteringWavelengthsZ.value = properties.atmosphere.scatteringWavelengths.z; elZoneAtmosphereScatteringWavelengthsZ.value = properties.atmosphere.scatteringWavelengths.z;
elZoneAtmosphereHasStars.checked = properties.atmosphere.hasStars;
} }
@ -650,6 +666,8 @@
elZoneAtmosphereScatteringWavelengthsX.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction); elZoneAtmosphereScatteringWavelengthsX.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction);
elZoneAtmosphereScatteringWavelengthsY.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction); elZoneAtmosphereScatteringWavelengthsY.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction);
elZoneAtmosphereScatteringWavelengthsZ.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction); elZoneAtmosphereScatteringWavelengthsZ.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction);
elZoneAtmosphereHasStars.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('atmosphere','hasStars'));
elMoveSelectionToGrid.addEventListener("click", function() { elMoveSelectionToGrid.addEventListener("click", function() {
EventBridge.emitWebEvent(JSON.stringify({ EventBridge.emitWebEvent(JSON.stringify({
@ -1136,23 +1154,29 @@
<div class="zone-section property"> <div class="zone-section property">
<div class="label">Atmosphere Mie Scattering</div> <div class="label">Atmosphere Mie Scattering</div>
<div class="value"> <div class="value">
<input class="coord" type='number' id="property-zone-atmosphere-mie-scattering" min="0" max="0.5" step="0.001"></input> <input class="coord no-spin" type='number' id="property-zone-atmosphere-mie-scattering" min="0" max="0.5" step="any"></input>
</div> </div>
</div> </div>
<div class="zone-section property"> <div class="zone-section property">
<div class="label">Atmosphere Rayleigh Scattering</div> <div class="label">Atmosphere Rayleigh Scattering</div>
<div class="value"> <div class="value">
<input class="coord" type='number' id="property-zone-atmosphere-rayleigh-scattering" min="0" max="0.5" step="0.001"></input> <input class="coord no-spin" type='number' id="property-zone-atmosphere-rayleigh-scattering" min="0" max="0.5" step="any"></input>
</div> </div>
</div> </div>
<div class="zone-section property"> <div class="zone-section property">
<div class="label">Atmosphere Scattering Wavelenghts</div> <div class="label">Atmosphere Scattering Wavelenghts</div>
<div class="value"> <div class="value">
<div class="input-area">X <br><input class="coord" type='number' id="property-zone-atmosphere-scattering-wavelengths-x" min="0" max="1" step="0.001"></input></div> <div class="input-area">X <br><input class="coord no-spin" type='number' id="property-zone-atmosphere-scattering-wavelengths-x" min="0" max="1" step="any"></input></div>
<div class="input-area">Y <br><input class="coord" type='number' id="property-zone-atmosphere-scattering-wavelengths-y" min="0" max="1" step="0.001"></input></div> <div class="input-area">Y <br><input class="coord no-spin" type='number' id="property-zone-atmosphere-scattering-wavelengths-y" min="0" max="1" step="any"></input></div>
<div class="input-area">Z <br><input class="coord" type='number' id="property-zone-atmosphere-scattering-wavelengths-z" min="0" max="1" step="0.001"></input></div> <div class="input-area">Z <br><input class="coord no-spin" type='number' id="property-zone-atmosphere-scattering-wavelengths-z" min="0" max="1" step="any"></input></div>
</div> </div>
</div> </div>
<div class="zone-section property">
<span class="label">Atmosphere Has Stars</span>
<span class="value">
<input type='checkbox' id="property-zone-atmosphere-has-stars">
</span>
</div>
</div> </div>

View file

@ -121,6 +121,14 @@ input.coord {
display: block; 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 { table#entity-table {
border-collapse: collapse; border-collapse: collapse;
font-family: Sans-Serif; font-family: Sans-Serif;

View file

@ -203,7 +203,7 @@ SelectionManager = (function() {
try { try {
listeners[i](); listeners[i]();
} catch (e) { } catch (e) {
print("got exception"); print("EntitySelectionTool got exception: " + JSON.stringify(e));
} }
} }
}; };

View file

@ -692,6 +692,9 @@ Application::~Application() {
nodeThread->quit(); nodeThread->quit();
nodeThread->wait(); nodeThread->wait();
Leapmotion::destroy();
RealSense::destroy();
qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages 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) { if (devicePixelRatio != oldDevicePixelRatio) {
oldDevicePixelRatio = devicePixelRatio; oldDevicePixelRatio = devicePixelRatio;
qDebug() << "Device pixel ratio changed, triggering GL resize"; qDebug() << "Device pixel ratio changed, triggering GL resize";
resizeGL(_glWidget->width(), resizeGL();
_glWidget->height());
} }
}); });
} }
@ -827,15 +829,7 @@ void Application::paintGL() {
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::paintGL()"); PerformanceWarning warn(showWarnings, "Application::paintGL()");
resizeGL();
// 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<TextureCache>()->setFrameBufferSize(OculusManager::getRenderTargetSize());
} else {
QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale();
DependencyManager::get<TextureCache>()->setFrameBufferSize(fbSize);
}
glEnable(GL_LINE_SMOOTH); glEnable(GL_LINE_SMOOTH);
@ -912,7 +906,14 @@ void Application::paintGL() {
renderRearViewMirror(_mirrorViewRect); renderRearViewMirror(_mirrorViewRect);
} }
DependencyManager::get<GlowEffect>()->render(); auto finalFbo = DependencyManager::get<GlowEffect>()->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"); PerformanceTimer perfTimer("renderOverlay");
@ -957,33 +958,47 @@ void Application::showEditEntitiesHelp() {
InfoView::show(INFO_EDIT_ENTITIES_PATH); 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()) { if (OculusManager::isConnected()) {
OculusManager::configureCamera(camera, width, height); OculusManager::configureCamera(camera, size.x, size.y);
} else if (TV3DManager::isConnected()) { } else if (TV3DManager::isConnected()) {
TV3DManager::configureCamera(camera, width, height); TV3DManager::configureCamera(camera, size.x, size.y);
} else { } else {
camera.setAspectRatio((float)width / height); camera.setAspectRatio((float)size.x / size.y);
camera.setFieldOfView(_fieldOfView.get()); camera.setFieldOfView(_fieldOfView.get());
} }
} }
void Application::resizeGL(int width, int height) { void Application::resizeGL() {
DependencyManager::get<TextureCache>()->setFrameBufferSize(QSize(width, height)); // Set the desired FBO texture size. If it hasn't changed, this does nothing.
resetCamerasOnResizeGL(_myCamera, width, height); // 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<TextureCache>()->setFrameBufferSize(renderSize);
resetCamerasOnResizeGL(_myCamera, _renderResolution);
glViewport(0, 0, _renderResolution.x, _renderResolution.y); // shouldn't this account for the menu???
updateProjectionMatrix(); updateProjectionMatrix();
glLoadIdentity(); glLoadIdentity();
auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->resize(_glWidget->size()); offscreenUi->resize(_glWidget->size());
_glWidget->makeCurrent();
// update Stats width // update Stats width
// let's set horizontal offset to give stats some margin to mirror // let's set horizontal offset to give stats some margin to mirror
int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2;
Stats::getInstance()->resetWidth(width, horizontalOffset); Stats::getInstance()->resetWidth(_renderResolution.x, horizontalOffset);
} }
void Application::updateProjectionMatrix() { void Application::updateProjectionMatrix() {
@ -1821,7 +1836,7 @@ void Application::setFullscreen(bool fullscreen) {
} }
void Application::setEnable3DTVMode(bool enable3DTVMode) { void Application::setEnable3DTVMode(bool enable3DTVMode) {
resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); resizeGL();
} }
void Application::setEnableVRMode(bool enableVRMode) { void Application::setEnableVRMode(bool enableVRMode) {
@ -1846,7 +1861,7 @@ void Application::setEnableVRMode(bool enableVRMode) {
_myCamera.setHmdRotation(glm::quat()); _myCamera.setHmdRotation(glm::quat());
} }
resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); resizeGL();
updateCursorVisibility(); updateCursorVisibility();
} }
@ -1931,6 +1946,7 @@ void Application::setActiveFaceTracker() {
bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::UseCamera); bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::UseCamera);
Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE); Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE);
Menu::getInstance()->getActionForOption(MenuOption::VelocityFilter)->setVisible(isUsingDDE); Menu::getInstance()->getActionForOption(MenuOption::VelocityFilter)->setVisible(isUsingDDE);
Menu::getInstance()->getActionForOption(MenuOption::CalibrateCamera)->setVisible(isUsingDDE);
auto ddeTracker = DependencyManager::get<DdeFaceTracker>(); auto ddeTracker = DependencyManager::get<DdeFaceTracker>();
ddeTracker->setIsMuted(isMuted); ddeTracker->setIsMuted(isMuted);
ddeTracker->setEnabled(isUsingDDE && !isMuted); ddeTracker->setEnabled(isUsingDDE && !isMuted);
@ -2644,7 +2660,10 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
if (rootCode) { if (rootCode) {
VoxelPositionSize rootDetails; VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, 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); 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 // only send to the NodeTypes that are serverType
if (node->getActiveSocket() && node->getType() == serverType) { if (node->getActiveSocket() && node->getType() == serverType) {
// get the server bounds for this server // get the server bounds for this server
QUuid nodeUUID = node->getUUID(); QUuid nodeUUID = node->getUUID();
@ -2707,7 +2725,12 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
if (rootCode) { if (rootCode) {
VoxelPositionSize rootDetails; VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, 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); ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) { if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
@ -2753,7 +2776,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
} }
// set up the packet for sending... // set up the packet for sending...
unsigned char* endOfQueryPacket = queryPacket; unsigned char* endOfQueryPacket = queryPacket;
// insert packet type/version and node UUID // insert packet type/version and node UUID
endOfQueryPacket += populatePacketHeader(reinterpret_cast<char*>(endOfQueryPacket), packetType); endOfQueryPacket += populatePacketHeader(reinterpret_cast<char*>(endOfQueryPacket), packetType);
@ -3217,12 +3240,12 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
_stars.render(theCamera.getFieldOfView(), theCamera.getAspectRatio(), theCamera.getNearClip(), alpha); _stars.render(theCamera.getFieldOfView(), theCamera.getAspectRatio(), theCamera.getNearClip(), alpha);
} }
// draw the sky dome // draw the sky dome
if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
PerformanceTimer perfTimer("atmosphere"); PerformanceTimer perfTimer("atmosphere");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... atmosphere..."); "Application::displaySide() ... atmosphere...");
_environment.renderAtmospheres(theCamera); _environment.renderAtmospheres(theCamera);
} }
} }
@ -4625,7 +4648,3 @@ PickRay Application::computePickRay() const {
bool Application::hasFocus() const { bool Application::hasFocus() const {
return _glWidget->hasFocus(); return _glWidget->hasFocus();
} }
void Application::resizeGL() {
this->resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
}

View file

@ -163,7 +163,7 @@ public:
void initializeGL(); void initializeGL();
void initializeUi(); void initializeUi();
void paintGL(); void paintGL();
void resizeGL(int width, int height); void resizeGL();
void resizeEvent(QResizeEvent * size); void resizeEvent(QResizeEvent * size);
@ -194,7 +194,6 @@ public:
bool hasFocus() const; bool hasFocus() const;
PickRay computePickRay() const; PickRay computePickRay() const;
PickRay computeViewPickRay(float xRatio, float yRatio) const; PickRay computeViewPickRay(float xRatio, float yRatio) const;
void resizeGL();
bool isThrottleRendering() const; bool isThrottleRendering() const;
@ -463,7 +462,7 @@ private slots:
void setCursorVisible(bool visible); void setCursorVisible(bool visible);
private: private:
void resetCamerasOnResizeGL(Camera& camera, int width, int height); void resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size);
void updateProjectionMatrix(); void updateProjectionMatrix();
void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true); void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true);
@ -662,6 +661,7 @@ private:
QHash<QString, AcceptURLMethod> _acceptedExtensions; QHash<QString, AcceptURLMethod> _acceptedExtensions;
QList<QString> _domainConnectionRefusals; QList<QString> _domainConnectionRefusals;
glm::uvec2 _renderResolution;
}; };
#endif // hifi_Application_h #endif // hifi_Application_h

View file

@ -64,7 +64,7 @@ void GLCanvas::paintGL() {
} }
void GLCanvas::resizeGL(int width, int height) { void GLCanvas::resizeGL(int width, int height) {
Application::getInstance()->resizeGL(width, height); Application::getInstance()->resizeGL();
} }
void GLCanvas::activeChanged(Qt::ApplicationState state) { void GLCanvas::activeChanged(Qt::ApplicationState state) {

View file

@ -392,6 +392,9 @@ Menu::Menu() {
useAudioForMouth->setVisible(false); useAudioForMouth->setVisible(false);
QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true); QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true);
ddeFiltering->setVisible(false); ddeFiltering->setVisible(false);
QAction* ddeCalibrate = addActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::CalibrateCamera, 0,
DependencyManager::get<DdeFaceTracker>().data(), SLOT(calibrate()));
ddeCalibrate->setVisible(false);
#endif #endif
#if defined(HAVE_FACESHIFT) || defined(HAVE_DDE) #if defined(HAVE_FACESHIFT) || defined(HAVE_DDE)
faceTrackingMenu->addSeparator(); faceTrackingMenu->addSeparator();

View file

@ -154,6 +154,7 @@ namespace MenuOption {
const QString Bookmarks = "Bookmarks"; const QString Bookmarks = "Bookmarks";
const QString CascadedShadows = "Cascaded"; const QString CascadedShadows = "Cascaded";
const QString CachesSize = "RAM Caches Size"; const QString CachesSize = "RAM Caches Size";
const QString CalibrateCamera = "Calibrate Camera";
const QString Chat = "Chat..."; const QString Chat = "Chat...";
const QString Collisions = "Collisions"; const QString Collisions = "Collisions";
const QString Console = "Console..."; const QString Console = "Console...";
@ -181,7 +182,7 @@ namespace MenuOption {
const QString EditEntitiesHelp = "Edit Entities Help..."; const QString EditEntitiesHelp = "Edit Entities Help...";
const QString Enable3DTVMode = "Enable 3DTV Mode"; const QString Enable3DTVMode = "Enable 3DTV Mode";
const QString EnableCharacterController = "Enable avatar collisions"; 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 EnableVRMode = "Enable VR Mode";
const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation"; const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation";
const QString ExpandMyAvatarTiming = "Expand /myAvatar"; const QString ExpandMyAvatarTiming = "Expand /myAvatar";

View file

@ -20,6 +20,7 @@
#include <GLMHelpers.h> #include <GLMHelpers.h>
#include <NumericalConstants.h> #include <NumericalConstants.h>
#include "Application.h"
#include "DdeFaceTracker.h" #include "DdeFaceTracker.h"
#include "FaceshiftConstants.h" #include "FaceshiftConstants.h"
#include "InterfaceLogging.h" #include "InterfaceLogging.h"
@ -86,16 +87,16 @@ static const float DDE_COEFFICIENT_SCALES[] = {
3.0f, // BrowsU_L 3.0f, // BrowsU_L
3.0f, // BrowsU_R 3.0f, // BrowsU_R
1.0f, // JawFwd 1.0f, // JawFwd
1.5f, // JawLeft 2.0f, // JawLeft
1.8f, // JawOpen 1.8f, // JawOpen
1.0f, // JawChew 1.0f, // JawChew
1.5f, // JawRight 2.0f, // JawRight
1.5f, // MouthLeft 1.5f, // MouthLeft
1.5f, // MouthRight 1.5f, // MouthRight
1.5f, // MouthFrown_L 1.5f, // MouthFrown_L
1.5f, // MouthFrown_R 1.5f, // MouthFrown_R
1.5f, // MouthSmile_L 2.5f, // MouthSmile_L
1.5f, // MouthSmile_R 2.5f, // MouthSmile_R
1.0f, // MouthDimple_L 1.0f, // MouthDimple_L
1.0f, // MouthDimple_R 1.0f, // MouthDimple_R
1.0f, // LipsStretch_L 1.0f, // LipsStretch_L
@ -106,8 +107,8 @@ static const float DDE_COEFFICIENT_SCALES[] = {
1.0f, // LipsLowerDown 1.0f, // LipsLowerDown
1.0f, // LipsUpperOpen 1.0f, // LipsUpperOpen
1.0f, // LipsLowerOpen 1.0f, // LipsLowerOpen
2.5f, // LipsFunnel 1.5f, // LipsFunnel
2.0f, // LipsPucker 2.5f, // LipsPucker
1.5f, // ChinLowerRaise 1.5f, // ChinLowerRaise
1.5f, // ChinUpperRaise 1.5f, // ChinUpperRaise
1.0f, // Sneer 1.0f, // Sneer
@ -135,7 +136,9 @@ struct Packet {
char name[MAX_NAME_SIZE + 1]; 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 #ifdef WIN32
// warning C4351: new behavior: elements of array 'DdeFaceTracker::_lastEyeBlinks' will be default initialized // 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), _filteredBrowUp(0.0f),
_lastEyeBlinks(), _lastEyeBlinks(),
_filteredEyeBlinks(), _filteredEyeBlinks(),
_lastEyeCoefficients() _lastEyeCoefficients(),
_isCalibrating(false),
_calibrationValues(),
_calibrationCount(0),
_calibrationBillboard(NULL),
_calibrationBillboardID(0),
_calibrationMessage(QString())
{ {
_coefficients.resize(NUM_FACESHIFT_BLENDSHAPES); _coefficients.resize(NUM_FACESHIFT_BLENDSHAPES);
_blendshapeCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES); _blendshapeCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES);
_coefficientAverages.resize(NUM_FACESHIFT_BLENDSHAPES);
_calibrationValues.resize(NUM_FACESHIFT_BLENDSHAPES);
_eyeStates[0] = EYE_OPEN; _eyeStates[0] = EYE_OPEN;
_eyeStates[1] = EYE_OPEN; _eyeStates[1] = EYE_OPEN;
@ -195,6 +205,10 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
DdeFaceTracker::~DdeFaceTracker() { DdeFaceTracker::~DdeFaceTracker() {
setEnabled(false); setEnabled(false);
if (_isCalibrating) {
cancelCalibration();
}
} }
#ifdef WIN32 #ifdef WIN32
@ -212,6 +226,12 @@ void DdeFaceTracker::setEnabled(bool enabled) {
return; return;
} }
#ifdef HAVE_DDE #ifdef HAVE_DDE
if (_isCalibrating) {
cancelCalibration();
}
// isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket. // isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket.
_udpSocket.close(); _udpSocket.close();
if (enabled) { if (enabled) {
@ -382,10 +402,18 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
_coefficients[DDE_TO_FACESHIFT_MAPPING[i]] = packet.expressions[i]; _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 // Use BrowsU_C to control both brows' up and down
float browUp = _coefficients[_browUpCenterIndex]; float browUp = _coefficients[_browUpCenterIndex];
if (isFiltering) { 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 velocity = fabs(browUp - _lastBrowUp) / _averageMessageTime;
float velocityFilter = glm::clamp(velocity * BROW_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); float velocityFilter = glm::clamp(velocity * BROW_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f);
_filteredBrowUp = velocityFilter * browUp + (1.0f - velocityFilter) * _filteredBrowUp; _filteredBrowUp = velocityFilter * browUp + (1.0f - velocityFilter) * _filteredBrowUp;
@ -399,11 +427,11 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
_coefficients[_browDownRightIndex] = -browUp; _coefficients[_browDownRightIndex] = -browUp;
// Offset jaw open coefficient // 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; _coefficients[_jawOpenIndex] = _coefficients[_jawOpenIndex] - JAW_OPEN_THRESHOLD;
// Offset smile coefficients // Offset smile coefficients
static const float SMILE_THRESHOLD = 0.18f; static const float SMILE_THRESHOLD = 0.5f;
_coefficients[_mouthSmileLeftIndex] = _coefficients[_mouthSmileLeftIndex] - SMILE_THRESHOLD; _coefficients[_mouthSmileLeftIndex] = _coefficients[_mouthSmileLeftIndex] - SMILE_THRESHOLD;
_coefficients[_mouthSmileRightIndex] = _coefficients[_mouthSmileRightIndex] - SMILE_THRESHOLD; _coefficients[_mouthSmileRightIndex] = _coefficients[_mouthSmileRightIndex] - SMILE_THRESHOLD;
@ -430,7 +458,7 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
// Change to closing or opening states // Change to closing or opening states
const float EYE_CONTROL_HYSTERISIS = 0.25f; 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; 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) { if ((_eyeStates[i] == EYE_OPEN || _eyeStates[i] == EYE_OPENING) && eyeCoefficients[i] > EYE_CLOSING_THRESHOLD) {
_eyeStates[i] = EYE_CLOSING; _eyeStates[i] = EYE_CLOSING;
@ -510,4 +538,81 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
} else { } else {
qCWarning(interfaceapp) << "DDE Face Tracker: Decode error"; 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";
} }

View file

@ -20,6 +20,7 @@
#include <QUdpSocket> #include <QUdpSocket>
#include <DependencyManager.h> #include <DependencyManager.h>
#include <ui/overlays/TextOverlay.h>
#include "FaceTracker.h" #include "FaceTracker.h"
@ -51,6 +52,7 @@ public:
public slots: public slots:
void setEnabled(bool enabled); void setEnabled(bool enabled);
void calibrate();
private slots: private slots:
void processFinished(int exitCode, QProcess::ExitStatus exitStatus); void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
@ -121,6 +123,17 @@ private:
float _lastEyeBlinks[2]; float _lastEyeBlinks[2];
float _filteredEyeBlinks[2]; float _filteredEyeBlinks[2];
float _lastEyeCoefficients[2]; float _lastEyeCoefficients[2];
QVector<float> _coefficientAverages;
bool _isCalibrating;
int _calibrationCount;
QVector<float> _calibrationValues;
TextOverlay* _calibrationBillboard;
int _calibrationBillboardID;
QString _calibrationMessage;
void addCalibrationDatum();
void cancelCalibration();
void finishCalibration();
}; };
#endif // hifi_DdeFaceTracker_h #endif // hifi_DdeFaceTracker_h

View file

@ -66,6 +66,14 @@ DeviceTracker::ID DeviceTracker::registerDevice(const Name& name, DeviceTracker*
return deviceID; 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() { void DeviceTracker::updateAll() {
//TODO C++11 for (auto deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) { //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++) { for (Vector::iterator deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) {

View file

@ -79,6 +79,8 @@ public:
/// INVALID_DEVICE_NAME if the name is already taken /// INVALID_DEVICE_NAME if the name is already taken
static ID registerDevice(const Name& name, DeviceTracker* tracker); static ID registerDevice(const Name& name, DeviceTracker* tracker);
static void destroyDevice(const Name& name);
// DeviceTracker interface // DeviceTracker interface
virtual void update(); virtual void update();

View file

@ -50,6 +50,11 @@ void Leapmotion::init() {
} }
} }
// static
void Leapmotion::destroy() {
DeviceTracker::destroyDevice(NAME);
}
// static // static
Leapmotion* Leapmotion::getInstance() { Leapmotion* Leapmotion::getInstance() {
DeviceTracker* device = DeviceTracker::getDevice(NAME); DeviceTracker* device = DeviceTracker::getDevice(NAME);

View file

@ -26,6 +26,7 @@ public:
static const Name NAME; static const Name NAME;
static void init(); static void init();
static void destroy();
/// Leapmotion MotionTracker factory /// Leapmotion MotionTracker factory
static Leapmotion* getInstance(); static Leapmotion* getInstance();

View file

@ -627,7 +627,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
//Full texture viewport for glow effect //Full texture viewport for glow effect
glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h); glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h);
finalFbo = DependencyManager::get<GlowEffect>()->render(true); finalFbo = DependencyManager::get<GlowEffect>()->render();
} else { } else {
finalFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer(); finalFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);

View file

@ -54,6 +54,11 @@ void RealSense::init() {
} }
} }
// static
void RealSense::destroy() {
DeviceTracker::destroyDevice(NAME);
}
// static // static
RealSense* RealSense::getInstance() { RealSense* RealSense::getInstance() {
DeviceTracker* device = DeviceTracker::getDevice(NAME); DeviceTracker* device = DeviceTracker::getDevice(NAME);

View file

@ -32,6 +32,7 @@ public:
static const Name NAME; static const Name NAME;
static void init(); static void init();
static void destroy();
/// RealSense MotionTracker factory /// RealSense MotionTracker factory
static RealSense* getInstance(); static RealSense* getInstance();

View file

@ -14,7 +14,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <GlowEffect.h> #include <GlowEffect.h>
#include "gpu/GLBackend.h"
#include "Application.h" #include "Application.h"
#include "TV3DManager.h" #include "TV3DManager.h"
@ -163,10 +163,18 @@ void TV3DManager::display(Camera& whichCamera) {
glPopMatrix(); glPopMatrix();
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
auto finalFbo = DependencyManager::get<GlowEffect>()->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 // reset the viewport to how we started
glViewport(0, 0, deviceSize.width(), deviceSize.height()); glViewport(0, 0, deviceSize.width(), deviceSize.height());
DependencyManager::get<GlowEffect>()->render();
} }
void TV3DManager::overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, void TV3DManager::overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal,

View file

@ -190,8 +190,8 @@ void ApplicationOverlay::renderOverlay() {
Overlays& overlays = qApp->getOverlays(); Overlays& overlays = qApp->getOverlays();
_textureFov = glm::radians(_hmdUIAngularSize); _textureFov = glm::radians(_hmdUIAngularSize);
glm::vec2 deviceSize = qApp->getCanvasSize(); glm::vec2 size = qApp->getCanvasSize();
_textureAspectRatio = (float)deviceSize.x / (float)deviceSize.y; _textureAspectRatio = aspect(size);
//Handle fading and deactivation/activation of UI //Handle fading and deactivation/activation of UI
@ -204,12 +204,13 @@ void ApplicationOverlay::renderOverlay() {
_overlays.buildFramebufferObject(); _overlays.buildFramebufferObject();
_overlays.bind(); _overlays.bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, size.x, size.y);
glPushMatrix(); { glPushMatrix(); {
const float NEAR_CLIP = -10000; const float NEAR_CLIP = -10000;
const float FAR_CLIP = 10000; const float FAR_CLIP = 10000;
glLoadIdentity(); 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); glMatrixMode(GL_MODELVIEW);
@ -269,6 +270,7 @@ void ApplicationOverlay::displayOverlayTexture() {
if (_alpha < 1.0) { if (_alpha < 1.0) {
glEnable(GL_BLEND); glEnable(GL_BLEND);
} }
glViewport(0, 0, qApp->getDeviceSize().width(), qApp->getDeviceSize().height());
static const glm::vec2 topLeft(-1, 1); static const glm::vec2 topLeft(-1, 1);
static const glm::vec2 bottomRight(1, -1); static const glm::vec2 bottomRight(1, -1);
@ -1129,8 +1131,9 @@ void ApplicationOverlay::TexturedHemisphere::cleanupVBO() {
} }
void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() {
auto deviceSize = qApp->getDeviceSize(); auto canvasSize = qApp->getCanvasSize();
if (_framebufferObject != NULL && deviceSize == _framebufferObject->size()) { QSize fboSize = QSize(canvasSize.x, canvasSize.y);
if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) {
// Already build // Already build
return; return;
} }
@ -1139,7 +1142,7 @@ void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() {
delete _framebufferObject; delete _framebufferObject;
} }
_framebufferObject = new QOpenGLFramebufferObject(deviceSize, QOpenGLFramebufferObject::Depth); _framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth);
glBindTexture(GL_TEXTURE_2D, getTexture()); glBindTexture(GL_TEXTURE_2D, getTexture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

View file

@ -25,6 +25,7 @@
#include <PerfStat.h> #include <PerfStat.h>
#include <SceneScriptingInterface.h> #include <SceneScriptingInterface.h>
#include <ScriptEngine.h> #include <ScriptEngine.h>
#include <TextureCache.h>
#include "EntityTreeRenderer.h" #include "EntityTreeRenderer.h"
@ -449,15 +450,19 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
} else { } else {
_viewState->endOverrideEnvironmentData(); _viewState->endOverrideEnvironmentData();
auto stage = scene->getSkyStage();
if (_bestZone->getBackgroundMode() == BACKGROUND_MODE_SKYBOX) { if (_bestZone->getBackgroundMode() == BACKGROUND_MODE_SKYBOX) {
auto stage = scene->getSkyStage();
stage->getSkybox()->setColor(_bestZone->getSkyboxProperties().getColorVec3()); stage->getSkybox()->setColor(_bestZone->getSkyboxProperties().getColorVec3());
if (_bestZone->getSkyboxProperties().getURL().isEmpty()) { if (_bestZone->getSkyboxProperties().getURL().isEmpty()) {
stage->getSkybox()->clearCubemap(); stage->getSkybox()->clearCubemap();
} else { } 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<TextureCache>()->getTexture(_bestZone->getSkyboxProperties().getURL(), CUBE_TEXTURE);
stage->getSkybox()->setCubemap(cubeMap->getGPUTexture());
} }
stage->setBackgroundMode(model::SunSkyStage::SKY_BOX); 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; _hasPreviousZone = false;
} }
_viewState->endOverrideEnvironmentData(); _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 // we must call endScene while we still have the tree locked so that no one deletes a model

View file

@ -16,12 +16,19 @@
#include "EntityItemPropertiesMacros.h" #include "EntityItemPropertiesMacros.h"
AtmospherePropertyGroup::AtmospherePropertyGroup() { AtmospherePropertyGroup::AtmospherePropertyGroup() {
_center = glm::vec3(0.0f); const glm::vec3 DEFAULT_CENTER = glm::vec3(0.0f, -1000.0f, 0.0f);
_innerRadius = 0.0f; const float DEFAULT_INNER_RADIUS = 1000.0f;
_outerRadius = 0.0f; const float DEFAULT_OUTER_RADIUS = 1025.0f;
_mieScattering = 0.0f; const float DEFAULT_RAYLEIGH_SCATTERING = 0.0025f;
_rayleighScattering = 0.0f; const float DEFAULT_MIE_SCATTERING = 0.0010f;
_scatteringWavelengths = glm::vec3(0.0f); 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; _hasStars = true;
} }

View file

@ -386,8 +386,9 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi
done: done:
if (faces.count() == 0) { // empty mesh if (faces.count() == 0) { // empty mesh
mesh.parts.pop_back(); 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; //qCDebug(modelformat) << "end group:" << meshPart.materialID << " original faces:" << originalFaceCountForDebugging << " triangles:" << faces.count() << " keep going:" << result;
return result; return result;
} }

View file

@ -479,6 +479,7 @@ void GLBackend::getCurrentGLState(State::Data& state) {
void GLBackend::syncPipelineStateCache() { void GLBackend::syncPipelineStateCache() {
State::Data state; State::Data state;
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
getCurrentGLState(state); getCurrentGLState(state);
State::Signature signature = State::evalSignature(state); State::Signature signature = State::evalSignature(state);

View file

@ -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_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
if (needUpdate) { if (needUpdate) {
if (texture.isStoredMipAvailable(0)) { if (texture.isStoredMipAvailable(0)) {
Texture::PixelsPointer mip = texture.accessStoredMip(0); Texture::PixelsPointer mip = texture.accessStoredMip(0);

View file

@ -68,11 +68,11 @@ public:
uint8 _maxMip = MAX_MIP_LEVEL; uint8 _maxMip = MAX_MIP_LEVEL;
Desc() {} 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() {}
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(const Desc& desc) : _desc(desc) {}
~Sampler() {} ~Sampler() {}

View file

@ -92,15 +92,3 @@ void Material::setTextureView(MapChannel channel, const gpu::TextureView& view)
_textureMap[channel] = 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));
}

View file

@ -23,27 +23,6 @@
namespace model { 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 { class Material {
public: public:
typedef gpu::BufferView UniformBufferView; typedef gpu::BufferView UniformBufferView;
@ -62,6 +41,7 @@ public:
NUM_MAPS, NUM_MAPS,
}; };
typedef std::map<MapChannel, TextureView> TextureMap; typedef std::map<MapChannel, TextureView> TextureMap;
typedef std::bitset<NUM_MAPS> MapFlags;
enum FlagBit { enum FlagBit {
DIFFUSE_BIT = 0, DIFFUSE_BIT = 0,

View file

@ -21,6 +21,7 @@ using namespace model;
Skybox::Skybox() { Skybox::Skybox() {
/* // PLease create a default engineer skybox
_cubemap.reset( gpu::Texture::createCube(gpu::Element::COLOR_RGBA_32, 1)); _cubemap.reset( gpu::Texture::createCube(gpu::Element::COLOR_RGBA_32, 1));
unsigned char texels[] = { unsigned char texels[] = {
255, 0, 0, 255, 255, 0, 0, 255,
@ -30,7 +31,7 @@ Skybox::Skybox() {
0, 255, 0, 255, 0, 255, 0, 255,
255, 0, 255, 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) { 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) { 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::PipelinePointer thePipeline;
static gpu::BufferPointer theBuffer; static gpu::BufferPointer theBuffer;
static gpu::Stream::FormatPointer theFormat; static gpu::Stream::FormatPointer theFormat;

View file

@ -18,7 +18,8 @@ varying vec3 color;
void main(void) { void main(void) {
vec4 texel = textureCube(cubeMap, normalize(normal)); vec3 coord = normalize(normal);
gl_FragData[0] = texel; vec4 texel = textureCube(cubeMap, coord);
// gl_FragData[0] = vec4(normal, 1.0); // gl_FragData[0] = vec4(texel.xyz * color, texel.w);
gl_FragData[0] = vec4(texel.xyz, 1.0);
} }

View file

@ -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; const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f;
SunSkyStage::SunSkyStage() : SunSkyStage::SunSkyStage() :
_sunLight(new Light()) _sunLight(new Light()),
_skybox(new Skybox())
{ {
_sunLight->setType(Light::SUN); _sunLight->setType(Light::SUN);
@ -290,6 +291,19 @@ void SunSkyStage::updateGraphicsObject() const {
_sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); _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; static int firstTime = 0;
if (firstTime == 0) { if (firstTime == 0) {
firstTime++; firstTime++;

View file

@ -223,11 +223,11 @@ public:
const SkyboxPointer& getSkybox() const { valid(); return _skybox; } const SkyboxPointer& getSkybox() const { valid(); return _skybox; }
protected: protected:
BackgroundMode _backgroundMode = SKY_DOME; BackgroundMode _backgroundMode = SKY_BOX;
LightPointer _sunLight; LightPointer _sunLight;
AtmospherePointer _atmosphere; AtmospherePointer _atmosphere;
SkyboxPointer _skybox; mutable SkyboxPointer _skybox;
gpu::PipelinePointer _skyPipeline; gpu::PipelinePointer _skyPipeline;

View file

@ -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;
}

View file

@ -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 <qurl.h>
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

View file

@ -151,10 +151,10 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
_movingStepsWithoutSimulationOwner = 0; _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) { if (_movingStepsWithoutSimulationOwner > ownershipClaimDelay) {
qDebug() << "Warning -- claiming something I saw moving." << getName(); //qDebug() << "Warning -- claiming something I saw moving." << getName();
setShouldClaimSimulationOwnership(true); setShouldClaimSimulationOwnership(true);
} }
@ -178,7 +178,7 @@ void EntityMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) {
const int MAX_NUM_NON_MOVING_UPDATES = 5; const int MAX_NUM_NON_MOVING_UPDATES = 5;
bool EntityMotionState::doesNotNeedToSendUpdate() const { 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) { bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
@ -232,6 +232,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
_serverPosition += dt * _serverVelocity; _serverPosition += dt * _serverVelocity;
} }
// TODO: compensate for simulation offset here
btTransform worldTrans = _body->getWorldTransform(); btTransform worldTrans = _body->getWorldTransform();
glm::vec3 position = bulletToGLM(worldTrans.getOrigin()); glm::vec3 position = bulletToGLM(worldTrans.getOrigin());
@ -310,86 +311,60 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
return; // never update entities that are unknown 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(); EntityItemProperties properties = _entity->getProperties();
float gravityLength = glm::length(_entity->getGravity()); // explicitly set the properties that changed
float accVsGravity = glm::abs(glm::length(_measuredAcceleration) - gravityLength); properties.setPosition(_serverPosition);
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());
properties.setRotation(_serverRotation); 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); properties.setVelocity(_serverVelocity);
_serverGravity = _entity->getGravity();
properties.setGravity(_entity->getGravity());
_serverAcceleration = _entity->getAcceleration();
properties.setAcceleration(_serverAcceleration); properties.setAcceleration(_serverAcceleration);
properties.setAngularVelocity(_serverAngularVelocity); properties.setAngularVelocity(_serverAngularVelocity);
auto nodeList = DependencyManager::get<NodeList>(); // RELIABLE_SEND_HACK: count number of updates for entities at rest
QUuid myNodeID = nodeList->getSessionUUID(); // so we can stop sending them after some limit.
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.
if (_sentMoving) { if (_sentMoving) {
_numNonMovingUpdates = 0; _numNonMovingUpdates = 0;
} else { } else {
@ -397,8 +372,6 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
} }
if (_numNonMovingUpdates <= 1) { if (_numNonMovingUpdates <= 1) {
// we only update lastEdited when we're sending new physics data // 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(); quint64 lastSimulated = _entity->getLastSimulated();
_entity->setLastEdited(lastSimulated); _entity->setLastEdited(lastSimulated);
properties.setLastEdited(lastSimulated); properties.setLastEdited(lastSimulated);
@ -415,6 +388,25 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
properties.setLastEdited(_entity->getLastEdited()); properties.setLastEdited(_entity->getLastEdited());
} }
auto nodeList = DependencyManager::get<NodeList>();
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()) { if (EntityItem::getSendPhysicsUpdates()) {
EntityItemID id(_entity->getID()); EntityItemID id(_entity->getID());
EntityEditPacketSender* entityPacketSender = static_cast<EntityEditPacketSender*>(packetSender); EntityEditPacketSender* entityPacketSender = static_cast<EntityEditPacketSender*>(packetSender);

View file

@ -167,7 +167,8 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
_tempVector.push_back(motionState); _tempVector.push_back(motionState);
entityItr = _pendingAdds.erase(entityItr); entityItr = _pendingAdds.erase(entityItr);
} else { } 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; ++entityItr;
} }
} else { } else {

View file

@ -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. // NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
btRigidBody* body = object->getRigidBody(); btRigidBody* body = object->getRigidBody();
object->setRigidBody(nullptr); object->setRigidBody(nullptr);
body->setMotionState(nullptr);
delete body; delete body;
object->releaseShape(); object->releaseShape();
delete object; 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. // NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
object->setRigidBody(nullptr); object->setRigidBody(nullptr);
body->setMotionState(nullptr);
delete body; delete body;
object->releaseShape(); object->releaseShape();
delete object; delete object;

View file

@ -95,4 +95,7 @@ void FboCache::setSize(const QSize& newSize) {
}); });
} }
const QSize& FboCache::getSize() {
return _size;
}

View file

@ -37,6 +37,8 @@ public:
// internal locks and pointers but execute no OpenGL opreations. // internal locks and pointers but execute no OpenGL opreations.
void lockTexture(int texture); void lockTexture(int texture);
void releaseTexture(int texture); void releaseTexture(int texture);
const QSize& getSize();
protected: protected:
QMap<int, QSharedPointer<QOpenGLFramebufferObject>> _fboMap; QMap<int, QSharedPointer<QOpenGLFramebufferObject>> _fboMap;

View file

@ -129,7 +129,7 @@ static void maybeRelease(const gpu::FramebufferPointer& fbo) {
} }
} }
gpu::FramebufferPointer GlowEffect::render(bool toTexture) { gpu::FramebufferPointer GlowEffect::render() {
PerformanceTimer perfTimer("glowEffect"); PerformanceTimer perfTimer("glowEffect");
auto textureCache = DependencyManager::get<TextureCache>(); auto textureCache = DependencyManager::get<TextureCache>();
@ -151,26 +151,24 @@ gpu::FramebufferPointer GlowEffect::render(bool toTexture) {
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
gpu::FramebufferPointer destFBO = toTexture ? gpu::FramebufferPointer destFBO = textureCache->getSecondaryFramebuffer();
textureCache->getSecondaryFramebuffer() : nullptr;
if (!_enabled || _isEmpty) { if (!_enabled || _isEmpty) {
// copy the primary to the screen // copy the primary to the screen
if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO)); 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 { } else {
maybeBind(destFBO); glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO));
if (!destFBO) { glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
//destFBO->getSize();
glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
}
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
renderFullscreenQuad(); renderFullscreenQuad();
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
maybeRelease(destFBO); glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }
} else { } else {
// diffuse into the secondary/tertiary (alternating between frames) // diffuse into the secondary/tertiary (alternating between frames)
@ -199,22 +197,18 @@ gpu::FramebufferPointer GlowEffect::render(bool toTexture) {
_diffuseProgram->release(); _diffuseProgram->release();
} }
glBindFramebuffer(GL_FRAMEBUFFER, 0); destFBO = oldDiffusedFBO;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// add diffused texture to the primary // add diffused texture to the primary
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(newDiffusedFBO->getRenderBuffer(0))); glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(newDiffusedFBO->getRenderBuffer(0)));
if (toTexture) { glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO));
destFBO = oldDiffusedFBO; glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
}
maybeBind(destFBO);
if (!destFBO) {
glViewport(0, 0, framebufferSize.width(), framebufferSize.height());
}
_addSeparateProgram->bind(); _addSeparateProgram->bind();
renderFullscreenQuad(); renderFullscreenQuad();
_addSeparateProgram->release(); _addSeparateProgram->release();
maybeRelease(destFBO); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);

View file

@ -52,7 +52,7 @@ public:
/// Renders the glow effect. To be called after rendering the scene. /// 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 /// \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 /// \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: public slots:
void toggleGlowEffect(bool enabled); void toggleGlowEffect(bool enabled);

View file

@ -417,17 +417,23 @@ void ImageReader::run() {
return; return;
} }
// enforce a fixed maximum area (1024 * 2048)
const int MAXIMUM_AREA_SIZE = 2097152;
int imageArea = image.width() * image.height(); int imageArea = image.width() * image.height();
if (imageArea > MAXIMUM_AREA_SIZE) { auto ntex = dynamic_cast<NetworkTexture*>(&*texture);
float scaleRatio = sqrtf((float)MAXIMUM_AREA_SIZE) / sqrtf((float)imageArea); if (ntex && (ntex->getType() == CUBE_TEXTURE)) {
int resizeWidth = static_cast<int>(std::floor(scaleRatio * static_cast<float>(image.width()))); qCDebug(renderutils) << "Cube map size:" << _url << image.width() << image.height();
int resizeHeight = static_cast<int>(std::floor(scaleRatio * static_cast<float>(image.height()))); } else {
qCDebug(renderutils) << "Image greater than maximum size:" << _url << image.width() << image.height() <<
" scaled to:" << resizeWidth << resizeHeight; // enforce a fixed maximum area (1024 * 2048)
image = image.scaled(resizeWidth, resizeHeight, Qt::IgnoreAspectRatio); const int MAXIMUM_AREA_SIZE = 2097152;
imageArea = image.width() * image.height(); if (imageArea > MAXIMUM_AREA_SIZE) {
float scaleRatio = sqrtf((float)MAXIMUM_AREA_SIZE) / sqrtf((float)imageArea);
int resizeWidth = static_cast<int>(std::floor(scaleRatio * static_cast<float>(image.width())));
int resizeHeight = static_cast<int>(std::floor(scaleRatio * static_cast<float>(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; const int EIGHT_BIT_MAXIMUM = 255;
@ -507,6 +513,7 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo
imageLoaded(image); imageLoaded(image);
if ((_width > 0) && (_height > 0)) { if ((_width > 0) && (_height > 0)) {
bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE);
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); 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)); formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); 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()); if (_type == CUBE_TEXTURE) {
_gpuTexture->autoGenerateMips(-1); 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);
}
} }
} }

View file

@ -27,7 +27,7 @@ class NetworkTexture;
typedef QSharedPointer<NetworkTexture> NetworkTexturePointer; typedef QSharedPointer<NetworkTexture> 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. /// Stores cached textures, including render-to-texture targets.
class TextureCache : public ResourceCache, public Dependency { class TextureCache : public ResourceCache, public Dependency {
@ -164,7 +164,7 @@ public:
int getOriginalHeight() const { return _originalHeight; } int getOriginalHeight() const { return _originalHeight; }
int getWidth() const { return _width; } int getWidth() const { return _width; }
int getHeight() const { return _height; } int getHeight() const { return _height; }
TextureType getType() const { return _type; }
protected: protected:
virtual void downloadFinished(QNetworkReply* reply); virtual void downloadFinished(QNetworkReply* reply);

View file

@ -13,6 +13,9 @@
#include "SceneScriptingInterface.h" #include "SceneScriptingInterface.h"
#include "SceneScriptingInterface.h"
void SceneScriptingInterface::setStageOrientation(const glm::quat& orientation) { void SceneScriptingInterface::setStageOrientation(const glm::quat& orientation) {
_skyStage->setOriginOrientation(orientation); _skyStage->setOriginOrientation(orientation);
} }
@ -86,6 +89,29 @@ bool SceneScriptingInterface::isStageSunModelEnabled() const {
return _skyStage->isSunModelEnabled(); 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 { model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const {
return _skyStage; return _skyStage;
} }

View file

@ -57,7 +57,8 @@ public:
Q_INVOKABLE glm::vec3 getKeyLightDirection() const; Q_INVOKABLE glm::vec3 getKeyLightDirection() const;
Q_INVOKABLE void setBackgroundMode(const QString& mode);
Q_INVOKABLE QString getBackgroundMode() const;
model::SunSkyStagePointer getSkyStage() const; model::SunSkyStagePointer getSkyStage() const;

View file

@ -117,6 +117,11 @@ QMatrix4x4 fromGlm(const glm::mat4 & m);
QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size); QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size);
template <typename T>
float aspect(const T& t) {
return (float)t.x / (float)t.y;
}
#define YAW(euler) euler.y #define YAW(euler) euler.y
#define PITCH(euler) euler.x #define PITCH(euler) euler.x
#define ROLL(euler) euler.z #define ROLL(euler) euler.z

View file

@ -117,8 +117,13 @@ void OffscreenUi::addImportPath(const QString& path) {
void OffscreenUi::resize(const QSize& newSize) { void OffscreenUi::resize(const QSize& newSize) {
makeCurrent(); makeCurrent();
// Clear out any fbos with the old size
qreal pixelRatio = _renderControl->_renderWindow ? _renderControl->_renderWindow->devicePixelRatio() : 1.0; 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; qDebug() << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height() << " with pixel ratio " << pixelRatio;
_fboCache.setSize(newSize * pixelRatio); _fboCache.setSize(newSize * pixelRatio);