mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge remote-tracking branch 'upstream/master' into plugins
This commit is contained in:
commit
230d1701b4
11 changed files with 183 additions and 23 deletions
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -203,7 +203,7 @@ SelectionManager = (function() {
|
||||||
try {
|
try {
|
||||||
listeners[i]();
|
listeners[i]();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("EntitySelectionTool got exception: " = JSON.stringify(e));
|
print("EntitySelectionTool got exception: " + JSON.stringify(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1911,6 +1911,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);
|
||||||
|
|
|
@ -390,6 +390,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();
|
||||||
|
|
|
@ -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...";
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -450,8 +450,8 @@ 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();
|
||||||
|
@ -461,6 +461,8 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
|
||||||
stage->getSkybox()->setCubemap(cubeMap->getGPUTexture());
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue