mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-24 01:54:09 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into fix_wireframe
This commit is contained in:
commit
f941ca9601
49 changed files with 619 additions and 260 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 @@
|
|||
<div class="zone-section property">
|
||||
<div class="label">Atmosphere Mie Scattering</div>
|
||||
<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 class="zone-section property">
|
||||
<div class="label">Atmosphere Rayleigh Scattering</div>
|
||||
<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 class="zone-section property">
|
||||
<div class="label">Atmosphere Scattering Wavelenghts</div>
|
||||
<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">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">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">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 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 no-spin" type='number' id="property-zone-atmosphere-scattering-wavelengths-z" min="0" max="1" step="any"></input></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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -203,7 +203,7 @@ SelectionManager = (function() {
|
|||
try {
|
||||
listeners[i]();
|
||||
} catch (e) {
|
||||
print("got exception");
|
||||
print("EntitySelectionTool got exception: " + JSON.stringify(e));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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<TextureCache>()->setFrameBufferSize(OculusManager::getRenderTargetSize());
|
||||
} else {
|
||||
QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale();
|
||||
DependencyManager::get<TextureCache>()->setFrameBufferSize(fbSize);
|
||||
}
|
||||
resizeGL();
|
||||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
|
@ -912,7 +906,14 @@ void Application::paintGL() {
|
|||
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");
|
||||
|
@ -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<TextureCache>()->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<TextureCache>()->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>();
|
||||
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<DdeFaceTracker>();
|
||||
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<char*>(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());
|
||||
}
|
||||
|
|
|
@ -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<QString, AcceptURLMethod> _acceptedExtensions;
|
||||
|
||||
QList<QString> _domainConnectionRefusals;
|
||||
glm::uvec2 _renderResolution;
|
||||
};
|
||||
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<DdeFaceTracker>().data(), SLOT(calibrate()));
|
||||
ddeCalibrate->setVisible(false);
|
||||
#endif
|
||||
#if defined(HAVE_FACESHIFT) || defined(HAVE_DDE)
|
||||
faceTrackingMenu->addSeparator();
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <GLMHelpers.h>
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
#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";
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <QUdpSocket>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <ui/overlays/TextOverlay.h>
|
||||
|
||||
#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<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
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -50,6 +50,11 @@ void Leapmotion::init() {
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void Leapmotion::destroy() {
|
||||
DeviceTracker::destroyDevice(NAME);
|
||||
}
|
||||
|
||||
// static
|
||||
Leapmotion* Leapmotion::getInstance() {
|
||||
DeviceTracker* device = DeviceTracker::getDevice(NAME);
|
||||
|
|
|
@ -26,6 +26,7 @@ public:
|
|||
static const Name NAME;
|
||||
|
||||
static void init();
|
||||
static void destroy();
|
||||
|
||||
/// Leapmotion MotionTracker factory
|
||||
static Leapmotion* getInstance();
|
||||
|
|
|
@ -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<GlowEffect>()->render(true);
|
||||
finalFbo = DependencyManager::get<GlowEffect>()->render();
|
||||
} else {
|
||||
finalFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
|
|
@ -54,6 +54,11 @@ void RealSense::init() {
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void RealSense::destroy() {
|
||||
DeviceTracker::destroyDevice(NAME);
|
||||
}
|
||||
|
||||
// static
|
||||
RealSense* RealSense::getInstance() {
|
||||
DeviceTracker* device = DeviceTracker::getDevice(NAME);
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
static const Name NAME;
|
||||
|
||||
static void init();
|
||||
static void destroy();
|
||||
|
||||
/// RealSense MotionTracker factory
|
||||
static RealSense* getInstance();
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <glm/glm.hpp>
|
||||
|
||||
#include <GlowEffect.h>
|
||||
|
||||
#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<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
|
||||
glViewport(0, 0, deviceSize.width(), deviceSize.height());
|
||||
|
||||
DependencyManager::get<GlowEffect>()->render();
|
||||
}
|
||||
|
||||
void TV3DManager::overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <PerfStat.h>
|
||||
#include <SceneScriptingInterface.h>
|
||||
#include <ScriptEngine.h>
|
||||
#include <TextureCache.h>
|
||||
|
||||
#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<TextureCache>()->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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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<MapChannel, TextureView> TextureMap;
|
||||
typedef std::bitset<NUM_MAPS> MapFlags;
|
||||
|
||||
enum FlagBit {
|
||||
DIFFUSE_BIT = 0,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
28
libraries/model/src/model/TextureStorage.cpp
Executable file
28
libraries/model/src/model/TextureStorage.cpp
Executable 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;
|
||||
}
|
||||
|
56
libraries/model/src/model/TextureStorage.h
Executable file
56
libraries/model/src/model/TextureStorage.h
Executable 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
|
||||
|
|
@ -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<NodeList>();
|
||||
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<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()) {
|
||||
EntityItemID id(_entity->getID());
|
||||
EntityEditPacketSender* entityPacketSender = static_cast<EntityEditPacketSender*>(packetSender);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -95,4 +95,7 @@ void FboCache::setSize(const QSize& newSize) {
|
|||
});
|
||||
}
|
||||
|
||||
const QSize& FboCache::getSize() {
|
||||
return _size;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<int, QSharedPointer<QOpenGLFramebufferObject>> _fboMap;
|
||||
|
|
|
@ -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<TextureCache>();
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<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();
|
||||
auto ntex = dynamic_cast<NetworkTexture*>(&*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<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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class NetworkTexture;
|
|||
|
||||
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.
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -117,6 +117,11 @@ QMatrix4x4 fromGlm(const glm::mat4 & m);
|
|||
|
||||
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 PITCH(euler) euler.x
|
||||
#define ROLL(euler) euler.z
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue