mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 19:50:38 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into hdr
This commit is contained in:
commit
a4945fe45c
19 changed files with 235 additions and 169 deletions
|
@ -1063,6 +1063,12 @@ void OctreeServer::readConfiguration() {
|
||||||
_wantBackup = !noBackup;
|
_wantBackup = !noBackup;
|
||||||
qDebug() << "wantBackup=" << _wantBackup;
|
qDebug() << "wantBackup=" << _wantBackup;
|
||||||
|
|
||||||
|
if (!readOptionString("backupDirectoryPath", settingsSectionObject, _backupDirectoryPath)) {
|
||||||
|
_backupDirectoryPath = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "backupDirectoryPath=" << _backupDirectoryPath;
|
||||||
|
|
||||||
readOptionBool(QString("persistFileDownload"), settingsSectionObject, _persistFileDownload);
|
readOptionBool(QString("persistFileDownload"), settingsSectionObject, _persistFileDownload);
|
||||||
qDebug() << "persistFileDownload=" << _persistFileDownload;
|
qDebug() << "persistFileDownload=" << _persistFileDownload;
|
||||||
|
|
||||||
|
@ -1160,25 +1166,25 @@ void OctreeServer::domainSettingsRequestComplete() {
|
||||||
// If persist filename does not exist, let's see if there is one beside the application binary
|
// If persist filename does not exist, let's see if there is one beside the application binary
|
||||||
// If there is, let's copy it over to our target persist directory
|
// If there is, let's copy it over to our target persist directory
|
||||||
QDir persistPath { _persistFilePath };
|
QDir persistPath { _persistFilePath };
|
||||||
QString absoluteFilePath = persistPath.absolutePath();
|
QString persistAbsoluteFilePath = persistPath.absolutePath();
|
||||||
|
|
||||||
if (persistPath.isRelative()) {
|
if (persistPath.isRelative()) {
|
||||||
// if the domain settings passed us a relative path, make an absolute path that is relative to the
|
// if the domain settings passed us a relative path, make an absolute path that is relative to the
|
||||||
// default data directory
|
// default data directory
|
||||||
absoluteFilePath = QDir(ServerPathUtils::getDataFilePath("entities/")).absoluteFilePath(_persistFilePath);
|
persistAbsoluteFilePath = QDir(ServerPathUtils::getDataFilePath("entities/")).absoluteFilePath(_persistFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const QString ENTITY_PERSIST_EXTENSION = ".json.gz";
|
static const QString ENTITY_PERSIST_EXTENSION = ".json.gz";
|
||||||
|
|
||||||
// force the persist file to end with .json.gz
|
// force the persist file to end with .json.gz
|
||||||
if (!absoluteFilePath.endsWith(ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive)) {
|
if (!persistAbsoluteFilePath.endsWith(ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive)) {
|
||||||
absoluteFilePath += ENTITY_PERSIST_EXTENSION;
|
persistAbsoluteFilePath += ENTITY_PERSIST_EXTENSION;
|
||||||
} else {
|
} else {
|
||||||
// make sure the casing of .json.gz is correct
|
// make sure the casing of .json.gz is correct
|
||||||
absoluteFilePath.replace(ENTITY_PERSIST_EXTENSION, ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive);
|
persistAbsoluteFilePath.replace(ENTITY_PERSIST_EXTENSION, ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!QFile::exists(absoluteFilePath)) {
|
if (!QFile::exists(persistAbsoluteFilePath)) {
|
||||||
qDebug() << "Persist file does not exist, checking for existence of persist file next to application";
|
qDebug() << "Persist file does not exist, checking for existence of persist file next to application";
|
||||||
|
|
||||||
static const QString OLD_DEFAULT_PERSIST_FILENAME = "resources/models.json.gz";
|
static const QString OLD_DEFAULT_PERSIST_FILENAME = "resources/models.json.gz";
|
||||||
|
@ -1204,7 +1210,7 @@ void OctreeServer::domainSettingsRequestComplete() {
|
||||||
pathToCopyFrom = oldDefaultPersistPath;
|
pathToCopyFrom = oldDefaultPersistPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir persistFileDirectory { QDir::cleanPath(absoluteFilePath + "/..") };
|
QDir persistFileDirectory { QDir::cleanPath(persistAbsoluteFilePath + "/..") };
|
||||||
|
|
||||||
if (!persistFileDirectory.exists()) {
|
if (!persistFileDirectory.exists()) {
|
||||||
qDebug() << "Creating data directory " << persistFileDirectory.absolutePath();
|
qDebug() << "Creating data directory " << persistFileDirectory.absolutePath();
|
||||||
|
@ -1212,16 +1218,46 @@ void OctreeServer::domainSettingsRequestComplete() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldCopy) {
|
if (shouldCopy) {
|
||||||
qDebug() << "Old persist file found, copying from " << pathToCopyFrom << " to " << absoluteFilePath;
|
qDebug() << "Old persist file found, copying from " << pathToCopyFrom << " to " << persistAbsoluteFilePath;
|
||||||
|
|
||||||
QFile::copy(pathToCopyFrom, absoluteFilePath);
|
QFile::copy(pathToCopyFrom, persistAbsoluteFilePath);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "No existing persist file found";
|
qDebug() << "No existing persist file found";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto persistFileDirectory = QFileInfo(persistAbsoluteFilePath).absolutePath();
|
||||||
|
if (_backupDirectoryPath.isEmpty()) {
|
||||||
|
// Use the persist file's directory to store backups
|
||||||
|
_backupDirectoryPath = persistFileDirectory;
|
||||||
|
} else {
|
||||||
|
// The backup directory has been set.
|
||||||
|
// If relative, make it relative to the entities directory in the application data directory
|
||||||
|
// If absolute, no resolution is necessary
|
||||||
|
QDir backupDirectory { _backupDirectoryPath };
|
||||||
|
QString absoluteBackupDirectory;
|
||||||
|
if (backupDirectory.isRelative()) {
|
||||||
|
absoluteBackupDirectory = QDir(ServerPathUtils::getDataFilePath("entities/")).absoluteFilePath(_backupDirectoryPath);
|
||||||
|
absoluteBackupDirectory = QDir(absoluteBackupDirectory).absolutePath();
|
||||||
|
} else {
|
||||||
|
absoluteBackupDirectory = backupDirectory.absolutePath();
|
||||||
|
}
|
||||||
|
backupDirectory = QDir(absoluteBackupDirectory);
|
||||||
|
if (!backupDirectory.exists()) {
|
||||||
|
if (backupDirectory.mkpath(".")) {
|
||||||
|
qDebug() << "Created backup directory";
|
||||||
|
} else {
|
||||||
|
qDebug() << "ERROR creating backup directory, using persist file directory";
|
||||||
|
_backupDirectoryPath = persistFileDirectory;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_backupDirectoryPath = absoluteBackupDirectory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDebug() << "Backups will be stored in: " << _backupDirectoryPath;
|
||||||
|
|
||||||
// now set up PersistThread
|
// now set up PersistThread
|
||||||
_persistThread = new OctreePersistThread(_tree, absoluteFilePath, _persistInterval,
|
_persistThread = new OctreePersistThread(_tree, persistAbsoluteFilePath, _backupDirectoryPath, _persistInterval,
|
||||||
_wantBackup, _settings, _debugTimestampNow, _persistAsFileType);
|
_wantBackup, _settings, _debugTimestampNow, _persistAsFileType);
|
||||||
_persistThread->initialize(true);
|
_persistThread->initialize(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,6 +172,7 @@ protected:
|
||||||
|
|
||||||
QString _persistFilePath;
|
QString _persistFilePath;
|
||||||
QString _persistAsFileType;
|
QString _persistAsFileType;
|
||||||
|
QString _backupDirectoryPath;
|
||||||
int _packetsPerClientPerInterval;
|
int _packetsPerClientPerInterval;
|
||||||
int _packetsTotalPerInterval;
|
int _packetsTotalPerInterval;
|
||||||
OctreePointer _tree; // this IS a reaveraging tree
|
OctreePointer _tree; // this IS a reaveraging tree
|
||||||
|
|
|
@ -1108,6 +1108,14 @@
|
||||||
"default": "models.json.gz",
|
"default": "models.json.gz",
|
||||||
"advanced": true
|
"advanced": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "backupDirectoryPath",
|
||||||
|
"label": "Entities Backup Directory Path",
|
||||||
|
"help": "The path to the directory to store backups in.<br/>If this path is relative it will be relative to the application data directory.",
|
||||||
|
"placeholder": "",
|
||||||
|
"default": "",
|
||||||
|
"advanced": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "persistInterval",
|
"name": "persistInterval",
|
||||||
"label": "Save Check Interval",
|
"label": "Save Check Interval",
|
||||||
|
|
|
@ -1237,6 +1237,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
_defaultSkybox->setCubemap(_defaultSkyboxTexture);
|
_defaultSkybox->setCubemap(_defaultSkyboxTexture);
|
||||||
_defaultSkybox->setColor({ 1.0, 1.0, 1.0 });
|
_defaultSkybox->setColor({ 1.0, 1.0, 1.0 });
|
||||||
|
|
||||||
|
EntityItem::setEntitiesShouldFadeFunction([this]() {
|
||||||
|
SharedNodePointer entityServerNode = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::EntityServer);
|
||||||
|
return entityServerNode && !isPhysicsEnabled();
|
||||||
|
});
|
||||||
|
|
||||||
// After all of the constructor is completed, then set firstRun to false.
|
// After all of the constructor is completed, then set firstRun to false.
|
||||||
Setting::Handle<bool> firstRun{ Settings::firstRun, true };
|
Setting::Handle<bool> firstRun{ Settings::firstRun, true };
|
||||||
firstRun.set(false);
|
firstRun.set(false);
|
||||||
|
@ -4253,6 +4258,21 @@ namespace render {
|
||||||
auto backgroundMode = skyStage->getBackgroundMode();
|
auto backgroundMode = skyStage->getBackgroundMode();
|
||||||
|
|
||||||
switch (backgroundMode) {
|
switch (backgroundMode) {
|
||||||
|
case model::SunSkyStage::SKY_DEFAULT: {
|
||||||
|
static const glm::vec3 DEFAULT_SKYBOX_COLOR{ 255.0f / 255.0f, 220.0f / 255.0f, 194.0f / 255.0f };
|
||||||
|
static const float DEFAULT_SKYBOX_INTENSITY{ 0.2f };
|
||||||
|
static const float DEFAULT_SKYBOX_AMBIENT_INTENSITY{ 2.0f };
|
||||||
|
static const glm::vec3 DEFAULT_SKYBOX_DIRECTION{ 0.0f, 0.0f, -1.0f };
|
||||||
|
|
||||||
|
auto scene = DependencyManager::get<SceneScriptingInterface>()->getStage();
|
||||||
|
auto sceneKeyLight = scene->getKeyLight();
|
||||||
|
scene->setSunModelEnable(false);
|
||||||
|
sceneKeyLight->setColor(DEFAULT_SKYBOX_COLOR);
|
||||||
|
sceneKeyLight->setIntensity(DEFAULT_SKYBOX_INTENSITY);
|
||||||
|
sceneKeyLight->setAmbientIntensity(DEFAULT_SKYBOX_AMBIENT_INTENSITY);
|
||||||
|
sceneKeyLight->setDirection(DEFAULT_SKYBOX_DIRECTION);
|
||||||
|
// fall through: render a skybox, if available
|
||||||
|
}
|
||||||
case model::SunSkyStage::SKY_BOX: {
|
case model::SunSkyStage::SKY_BOX: {
|
||||||
auto skybox = skyStage->getSkybox();
|
auto skybox = skyStage->getSkybox();
|
||||||
if (skybox) {
|
if (skybox) {
|
||||||
|
@ -4260,33 +4280,22 @@ namespace render {
|
||||||
skybox->render(batch, args->getViewFrustum());
|
skybox->render(batch, args->getViewFrustum());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// fall through: render defaults, if available
|
||||||
}
|
}
|
||||||
|
case model::SunSkyStage::SKY_DEFAULT_AMBIENT_TEXTURE: {
|
||||||
// Fall through: if no skybox is available, render the SKY_DOME
|
if (Menu::getInstance()->isOptionChecked(MenuOption::DefaultSkybox)) {
|
||||||
case model::SunSkyStage::SKY_DOME: {
|
auto scene = DependencyManager::get<SceneScriptingInterface>()->getStage();
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DefaultSkybox)) {
|
auto sceneKeyLight = scene->getKeyLight();
|
||||||
static const glm::vec3 DEFAULT_SKYBOX_COLOR { 255.0f / 255.0f, 220.0f / 255.0f, 194.0f / 255.0f };
|
auto defaultSkyboxAmbientTexture = qApp->getDefaultSkyboxAmbientTexture();
|
||||||
static const float DEFAULT_SKYBOX_INTENSITY { 0.2f };
|
// do not set the ambient sphere - it peaks too high, and causes flashing when turning
|
||||||
static const float DEFAULT_SKYBOX_AMBIENT_INTENSITY { 2.0f };
|
sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture);
|
||||||
static const glm::vec3 DEFAULT_SKYBOX_DIRECTION { 0.0f, 0.0f, -1.0f };
|
}
|
||||||
|
// fall through: render defaults, if available
|
||||||
auto scene = DependencyManager::get<SceneScriptingInterface>()->getStage();
|
|
||||||
auto sceneKeyLight = scene->getKeyLight();
|
|
||||||
scene->setSunModelEnable(false);
|
|
||||||
sceneKeyLight->setColor(DEFAULT_SKYBOX_COLOR);
|
|
||||||
sceneKeyLight->setIntensity(DEFAULT_SKYBOX_INTENSITY);
|
|
||||||
sceneKeyLight->setAmbientIntensity(DEFAULT_SKYBOX_AMBIENT_INTENSITY);
|
|
||||||
sceneKeyLight->setDirection(DEFAULT_SKYBOX_DIRECTION);
|
|
||||||
|
|
||||||
auto defaultSkyboxAmbientTexture = qApp->getDefaultSkyboxAmbientTexture();
|
|
||||||
sceneKeyLight->setAmbientSphere(defaultSkyboxAmbientTexture->getIrradiance());
|
|
||||||
sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture);
|
|
||||||
|
|
||||||
qApp->getDefaultSkybox()->render(batch, args->getViewFrustum());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
case model::SunSkyStage::SKY_DEFAULT_TEXTURE:
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::DefaultSkybox)) {
|
||||||
|
qApp->getDefaultSkybox()->render(batch, args->getViewFrustum());
|
||||||
|
}
|
||||||
case model::SunSkyStage::NO_BACKGROUND:
|
case model::SunSkyStage::NO_BACKGROUND:
|
||||||
default:
|
default:
|
||||||
// this line intentionally left blank
|
// this line intentionally left blank
|
||||||
|
@ -4503,7 +4512,7 @@ void Application::clearDomainOctreeDetails() {
|
||||||
|
|
||||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||||
|
|
||||||
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME);
|
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DEFAULT);
|
||||||
|
|
||||||
_recentlyClearedDomain = true;
|
_recentlyClearedDomain = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -516,13 +516,23 @@ glm::mat4 MyAvatar::getSensorToWorldMatrix() const {
|
||||||
return _sensorToWorldMatrixCache.get();
|
return _sensorToWorldMatrixCache.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As far as I know no HMD system supports a play area of a kilometer in radius.
|
||||||
|
static const float MAX_HMD_ORIGIN_DISTANCE = 1000.0f;
|
||||||
// Pass a recent sample of the HMD to the avatar.
|
// Pass a recent sample of the HMD to the avatar.
|
||||||
// This can also update the avatar's position to follow the HMD
|
// This can also update the avatar's position to follow the HMD
|
||||||
// as it moves through the world.
|
// as it moves through the world.
|
||||||
void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
||||||
// update the sensorMatrices based on the new hmd pose
|
// update the sensorMatrices based on the new hmd pose
|
||||||
_hmdSensorMatrix = hmdSensorMatrix;
|
_hmdSensorMatrix = hmdSensorMatrix;
|
||||||
_hmdSensorPosition = extractTranslation(hmdSensorMatrix);
|
auto newHmdSensorPosition = extractTranslation(hmdSensorMatrix);
|
||||||
|
|
||||||
|
if (newHmdSensorPosition != _hmdSensorPosition &&
|
||||||
|
glm::length(newHmdSensorPosition) > MAX_HMD_ORIGIN_DISTANCE) {
|
||||||
|
qWarning() << "Invalid HMD sensor position " << newHmdSensorPosition;
|
||||||
|
// Ignore unreasonable HMD sensor data
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_hmdSensorPosition = newHmdSensorPosition;
|
||||||
_hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix);
|
_hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix);
|
||||||
_hmdSensorFacing = getFacingDir2D(_hmdSensorOrientation);
|
_hmdSensorFacing = getFacingDir2D(_hmdSensorOrientation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,15 +346,13 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
|
||||||
auto sceneStage = scene->getStage();
|
auto sceneStage = scene->getStage();
|
||||||
auto skyStage = scene->getSkyStage();
|
auto skyStage = scene->getSkyStage();
|
||||||
auto sceneKeyLight = sceneStage->getKeyLight();
|
auto sceneKeyLight = sceneStage->getKeyLight();
|
||||||
auto sceneLocation = sceneStage->getLocation();
|
|
||||||
auto sceneTime = sceneStage->getTime();
|
|
||||||
|
|
||||||
// Skybox and procedural skybox data
|
// Skybox and procedural skybox data
|
||||||
auto skybox = std::dynamic_pointer_cast<ProceduralSkybox>(skyStage->getSkybox());
|
auto skybox = std::dynamic_pointer_cast<ProceduralSkybox>(skyStage->getSkybox());
|
||||||
static QString userData;
|
|
||||||
|
|
||||||
|
// If there is no zone, use the default background
|
||||||
if (!zone) {
|
if (!zone) {
|
||||||
userData = QString();
|
_zoneUserData = QString();
|
||||||
skybox->clear();
|
skybox->clear();
|
||||||
|
|
||||||
_pendingSkyboxTexture = false;
|
_pendingSkyboxTexture = false;
|
||||||
|
@ -363,50 +361,33 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
|
||||||
_pendingAmbientTexture = false;
|
_pendingAmbientTexture = false;
|
||||||
_ambientTexture.clear();
|
_ambientTexture.clear();
|
||||||
|
|
||||||
if (_hasPreviousZone) {
|
sceneKeyLight->resetAmbientSphere();
|
||||||
sceneKeyLight->resetAmbientSphere();
|
sceneKeyLight->setAmbientMap(nullptr);
|
||||||
sceneKeyLight->setAmbientMap(nullptr);
|
|
||||||
sceneKeyLight->setColor(_previousKeyLightColor);
|
|
||||||
sceneKeyLight->setIntensity(_previousKeyLightIntensity);
|
|
||||||
sceneKeyLight->setAmbientIntensity(_previousKeyLightAmbientIntensity);
|
|
||||||
sceneKeyLight->setDirection(_previousKeyLightDirection);
|
|
||||||
sceneStage->setSunModelEnable(_previousStageSunModelEnabled);
|
|
||||||
sceneStage->setLocation(_previousStageLongitude, _previousStageLatitude,
|
|
||||||
_previousStageAltitude);
|
|
||||||
sceneTime->setHour(_previousStageHour);
|
|
||||||
sceneTime->setDay(_previousStageDay);
|
|
||||||
|
|
||||||
_hasPreviousZone = false;
|
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DEFAULT);
|
||||||
}
|
return;
|
||||||
|
|
||||||
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application background through
|
|
||||||
return; // Early exit
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_hasPreviousZone) {
|
|
||||||
_previousKeyLightColor = sceneKeyLight->getColor();
|
|
||||||
_previousKeyLightIntensity = sceneKeyLight->getIntensity();
|
|
||||||
_previousKeyLightAmbientIntensity = sceneKeyLight->getAmbientIntensity();
|
|
||||||
_previousKeyLightDirection = sceneKeyLight->getDirection();
|
|
||||||
_previousStageSunModelEnabled = sceneStage->isSunModelEnabled();
|
|
||||||
_previousStageLongitude = sceneLocation->getLongitude();
|
|
||||||
_previousStageLatitude = sceneLocation->getLatitude();
|
|
||||||
_previousStageAltitude = sceneLocation->getAltitude();
|
|
||||||
_previousStageHour = sceneTime->getHour();
|
|
||||||
_previousStageDay = sceneTime->getDay();
|
|
||||||
_hasPreviousZone = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the keylight
|
||||||
sceneKeyLight->setColor(ColorUtils::toVec3(zone->getKeyLightProperties().getColor()));
|
sceneKeyLight->setColor(ColorUtils::toVec3(zone->getKeyLightProperties().getColor()));
|
||||||
sceneKeyLight->setIntensity(zone->getKeyLightProperties().getIntensity());
|
sceneKeyLight->setIntensity(zone->getKeyLightProperties().getIntensity());
|
||||||
sceneKeyLight->setAmbientIntensity(zone->getKeyLightProperties().getAmbientIntensity());
|
sceneKeyLight->setAmbientIntensity(zone->getKeyLightProperties().getAmbientIntensity());
|
||||||
sceneKeyLight->setDirection(zone->getKeyLightProperties().getDirection());
|
sceneKeyLight->setDirection(zone->getKeyLightProperties().getDirection());
|
||||||
sceneStage->setSunModelEnable(zone->getStageProperties().getSunModelEnabled());
|
|
||||||
sceneStage->setLocation(zone->getStageProperties().getLongitude(), zone->getStageProperties().getLatitude(),
|
|
||||||
zone->getStageProperties().getAltitude());
|
|
||||||
sceneTime->setHour(zone->getStageProperties().calculateHour());
|
|
||||||
sceneTime->setDay(zone->getStageProperties().calculateDay());
|
|
||||||
|
|
||||||
|
// Set the stage
|
||||||
|
bool isSunModelEnabled = zone->getStageProperties().getSunModelEnabled();
|
||||||
|
sceneStage->setSunModelEnable(isSunModelEnabled);
|
||||||
|
if (isSunModelEnabled) {
|
||||||
|
sceneStage->setLocation(zone->getStageProperties().getLongitude(),
|
||||||
|
zone->getStageProperties().getLatitude(),
|
||||||
|
zone->getStageProperties().getAltitude());
|
||||||
|
|
||||||
|
auto sceneTime = sceneStage->getTime();
|
||||||
|
sceneTime->setHour(zone->getStageProperties().calculateHour());
|
||||||
|
sceneTime->setDay(zone->getStageProperties().calculateDay());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the ambient texture
|
||||||
bool isAmbientTextureSet = false;
|
bool isAmbientTextureSet = false;
|
||||||
if (zone->getKeyLightProperties().getAmbientURL().isEmpty()) {
|
if (zone->getKeyLightProperties().getAmbientURL().isEmpty()) {
|
||||||
_pendingAmbientTexture = false;
|
_pendingAmbientTexture = false;
|
||||||
|
@ -429,12 +410,13 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the skybox texture
|
||||||
switch (zone->getBackgroundMode()) {
|
switch (zone->getBackgroundMode()) {
|
||||||
case BACKGROUND_MODE_SKYBOX: {
|
case BACKGROUND_MODE_SKYBOX: {
|
||||||
skybox->setColor(zone->getSkyboxProperties().getColorVec3());
|
skybox->setColor(zone->getSkyboxProperties().getColorVec3());
|
||||||
if (userData != zone->getUserData()) {
|
if (_zoneUserData != zone->getUserData()) {
|
||||||
userData = zone->getUserData();
|
_zoneUserData = zone->getUserData();
|
||||||
skybox->parse(userData);
|
skybox->parse(_zoneUserData);
|
||||||
}
|
}
|
||||||
if (zone->getSkyboxProperties().getURL().isEmpty()) {
|
if (zone->getSkyboxProperties().getURL().isEmpty()) {
|
||||||
skybox->setCubemap(nullptr);
|
skybox->setCubemap(nullptr);
|
||||||
|
@ -471,14 +453,18 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
|
||||||
case BACKGROUND_MODE_INHERIT:
|
case BACKGROUND_MODE_INHERIT:
|
||||||
default:
|
default:
|
||||||
// Clear the skybox to release its textures
|
// Clear the skybox to release its textures
|
||||||
userData = QString();
|
_zoneUserData = QString();
|
||||||
skybox->clear();
|
skybox->clear();
|
||||||
|
|
||||||
_skyboxTexture.clear();
|
_skyboxTexture.clear();
|
||||||
_pendingSkyboxTexture = false;
|
_pendingSkyboxTexture = false;
|
||||||
|
|
||||||
// Let the application background through
|
// Let the application background through
|
||||||
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME);
|
if (isAmbientTextureSet) {
|
||||||
|
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DEFAULT_TEXTURE);
|
||||||
|
} else {
|
||||||
|
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DEFAULT_AMBIENT_TEXTURE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,25 +185,15 @@ private:
|
||||||
|
|
||||||
QMultiMap<QUrl, EntityItemID> _waitingOnPreload;
|
QMultiMap<QUrl, EntityItemID> _waitingOnPreload;
|
||||||
|
|
||||||
bool _hasPreviousZone { false };
|
|
||||||
std::shared_ptr<ZoneEntityItem> _bestZone;
|
std::shared_ptr<ZoneEntityItem> _bestZone;
|
||||||
float _bestZoneVolume;
|
float _bestZoneVolume;
|
||||||
|
|
||||||
|
QString _zoneUserData;
|
||||||
|
|
||||||
quint64 _lastZoneCheck { 0 };
|
quint64 _lastZoneCheck { 0 };
|
||||||
const quint64 ZONE_CHECK_INTERVAL = USECS_PER_MSEC * 100; // ~10hz
|
const quint64 ZONE_CHECK_INTERVAL = USECS_PER_MSEC * 100; // ~10hz
|
||||||
const float ZONE_CHECK_DISTANCE = 0.001f;
|
const float ZONE_CHECK_DISTANCE = 0.001f;
|
||||||
|
|
||||||
glm::vec3 _previousKeyLightColor;
|
|
||||||
float _previousKeyLightIntensity;
|
|
||||||
float _previousKeyLightAmbientIntensity;
|
|
||||||
glm::vec3 _previousKeyLightDirection;
|
|
||||||
bool _previousStageSunModelEnabled;
|
|
||||||
float _previousStageLongitude;
|
|
||||||
float _previousStageLatitude;
|
|
||||||
float _previousStageAltitude;
|
|
||||||
float _previousStageHour;
|
|
||||||
int _previousStageDay;
|
|
||||||
|
|
||||||
QHash<EntityItemID, EntityItemPointer> _entitiesInScene;
|
QHash<EntityItemID, EntityItemPointer> _entitiesInScene;
|
||||||
// For Scene.shouldRenderEntities
|
// For Scene.shouldRenderEntities
|
||||||
QList<EntityItemID> _entityIDsLastInScene;
|
QList<EntityItemID> _entityIDsLastInScene;
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
int EntityItem::_maxActionsDataSize = 800;
|
int EntityItem::_maxActionsDataSize = 800;
|
||||||
quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND;
|
quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND;
|
||||||
|
std::function<bool()> EntityItem::_entitiesShouldFadeFunction = [](){ return true; };
|
||||||
|
|
||||||
EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
||||||
SpatiallyNestable(NestableType::Entity, entityItemID),
|
SpatiallyNestable(NestableType::Entity, entityItemID),
|
||||||
|
|
|
@ -432,6 +432,8 @@ public:
|
||||||
QUuid getOwningAvatarID() const { return _owningAvatarID; }
|
QUuid getOwningAvatarID() const { return _owningAvatarID; }
|
||||||
void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; }
|
void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; }
|
||||||
|
|
||||||
|
static void setEntitiesShouldFadeFunction(std::function<bool()> func) { _entitiesShouldFadeFunction = func; }
|
||||||
|
static std::function<bool()> getEntitiesShouldFadeFunction() { return _entitiesShouldFadeFunction; }
|
||||||
virtual bool isTransparent() { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
virtual bool isTransparent() { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -564,7 +566,8 @@ protected:
|
||||||
quint64 _lastUpdatedAccelerationTimestamp { 0 };
|
quint64 _lastUpdatedAccelerationTimestamp { 0 };
|
||||||
|
|
||||||
quint64 _fadeStartTime { usecTimestampNow() };
|
quint64 _fadeStartTime { usecTimestampNow() };
|
||||||
bool _isFading { true };
|
static std::function<bool()> _entitiesShouldFadeFunction;
|
||||||
|
bool _isFading { _entitiesShouldFadeFunction() };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_EntityItem_h
|
#endif // hifi_EntityItem_h
|
||||||
|
|
|
@ -293,10 +293,18 @@ public:
|
||||||
template <typename T> Iterator<T> end() { return Iterator<T>(&edit<T>(getNum<T>()), _stride); }
|
template <typename T> Iterator<T> end() { return Iterator<T>(&edit<T>(getNum<T>()), _stride); }
|
||||||
#else
|
#else
|
||||||
template <typename T> Iterator<const T> begin() const { return Iterator<const T>(&get<T>(), _stride); }
|
template <typename T> Iterator<const T> begin() const { return Iterator<const T>(&get<T>(), _stride); }
|
||||||
template <typename T> Iterator<const T> end() const { return Iterator<const T>(&get<T>(getNum<T>()), _stride); }
|
template <typename T> Iterator<const T> end() const {
|
||||||
|
// reimplement get<T> without bounds checking
|
||||||
|
Resource::Size elementOffset = getNum<T>() * _stride + _offset;
|
||||||
|
return Iterator<const T>((reinterpret_cast<const T*> (_buffer->getData() + elementOffset)), _stride);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
template <typename T> Iterator<const T> cbegin() const { return Iterator<const T>(&get<T>(), _stride); }
|
template <typename T> Iterator<const T> cbegin() const { return Iterator<const T>(&get<T>(), _stride); }
|
||||||
template <typename T> Iterator<const T> cend() const { return Iterator<const T>(&get<T>(getNum<T>()), _stride); }
|
template <typename T> Iterator<const T> cend() const {
|
||||||
|
// reimplement get<T> without bounds checking
|
||||||
|
Resource::Size elementOffset = getNum<T>() * _stride + _offset;
|
||||||
|
return Iterator<const T>((reinterpret_cast<const T*> (_buffer->getData() + elementOffset)), _stride);
|
||||||
|
}
|
||||||
|
|
||||||
// the number of elements of the specified type fitting in the view size
|
// the number of elements of the specified type fitting in the view size
|
||||||
template <typename T> Index getNum() const {
|
template <typename T> Index getNum() const {
|
||||||
|
|
|
@ -244,21 +244,6 @@ void SunSkyStage::updateGraphicsObject() const {
|
||||||
double originAlt = _earthSunModel.getAltitude();
|
double originAlt = _earthSunModel.getAltitude();
|
||||||
_sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f));
|
_sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background
|
|
||||||
switch (getBackgroundMode()) {
|
|
||||||
case NO_BACKGROUND: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SKY_DOME: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SKY_BOX: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NUM_BACKGROUND_MODES:
|
|
||||||
Q_UNREACHABLE();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SunSkyStage::setBackgroundMode(BackgroundMode mode) {
|
void SunSkyStage::setBackgroundMode(BackgroundMode mode) {
|
||||||
|
|
|
@ -160,8 +160,10 @@ public:
|
||||||
|
|
||||||
enum BackgroundMode {
|
enum BackgroundMode {
|
||||||
NO_BACKGROUND = 0,
|
NO_BACKGROUND = 0,
|
||||||
SKY_DOME,
|
SKY_DEFAULT,
|
||||||
SKY_BOX,
|
SKY_BOX,
|
||||||
|
SKY_DEFAULT_AMBIENT_TEXTURE,
|
||||||
|
SKY_DEFAULT_TEXTURE,
|
||||||
|
|
||||||
NUM_BACKGROUND_MODES,
|
NUM_BACKGROUND_MODES,
|
||||||
};
|
};
|
||||||
|
@ -173,7 +175,7 @@ public:
|
||||||
const SkyboxPointer& getSkybox() const { valid(); return _skybox; }
|
const SkyboxPointer& getSkybox() const { valid(); return _skybox; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BackgroundMode _backgroundMode = SKY_DOME;
|
BackgroundMode _backgroundMode = SKY_DEFAULT;
|
||||||
|
|
||||||
LightPointer _sunLight;
|
LightPointer _sunLight;
|
||||||
mutable SkyboxPointer _skybox;
|
mutable SkyboxPointer _skybox;
|
||||||
|
|
|
@ -34,11 +34,12 @@
|
||||||
|
|
||||||
const int OctreePersistThread::DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
|
const int OctreePersistThread::DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
|
||||||
|
|
||||||
OctreePersistThread::OctreePersistThread(OctreePointer tree, const QString& filename, int persistInterval,
|
OctreePersistThread::OctreePersistThread(OctreePointer tree, const QString& filename, const QString& backupDirectory, int persistInterval,
|
||||||
bool wantBackup, const QJsonObject& settings, bool debugTimestampNow,
|
bool wantBackup, const QJsonObject& settings, bool debugTimestampNow,
|
||||||
QString persistAsFileType) :
|
QString persistAsFileType) :
|
||||||
_tree(tree),
|
_tree(tree),
|
||||||
_filename(filename),
|
_filename(filename),
|
||||||
|
_backupDirectory(backupDirectory),
|
||||||
_persistInterval(persistInterval),
|
_persistInterval(persistInterval),
|
||||||
_initialLoadComplete(false),
|
_initialLoadComplete(false),
|
||||||
_loadTimeUSecs(0),
|
_loadTimeUSecs(0),
|
||||||
|
@ -316,7 +317,7 @@ bool OctreePersistThread::getMostRecentBackup(const QString& format,
|
||||||
|
|
||||||
// Based on our backup file name, determine the path and file name pattern for backup files
|
// Based on our backup file name, determine the path and file name pattern for backup files
|
||||||
QFileInfo persistFileInfo(_filename);
|
QFileInfo persistFileInfo(_filename);
|
||||||
QString path = persistFileInfo.path();
|
QString path = _backupDirectory;
|
||||||
QString fileNamePart = persistFileInfo.fileName();
|
QString fileNamePart = persistFileInfo.fileName();
|
||||||
|
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
|
@ -369,10 +370,12 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) {
|
||||||
if (rule.maxBackupVersions > 0) {
|
if (rule.maxBackupVersions > 0) {
|
||||||
qCDebug(octree) << "Rolling old backup versions for rule" << rule.name << "...";
|
qCDebug(octree) << "Rolling old backup versions for rule" << rule.name << "...";
|
||||||
|
|
||||||
|
QString backupFileName = _backupDirectory + "/" + QUrl(_filename).fileName();
|
||||||
|
|
||||||
// Delete maximum rolling file because rename() fails on Windows if target exists
|
// Delete maximum rolling file because rename() fails on Windows if target exists
|
||||||
QString backupMaxExtensionN = rule.extensionFormat;
|
QString backupMaxExtensionN = rule.extensionFormat;
|
||||||
backupMaxExtensionN.replace(QString("%N"), QString::number(rule.maxBackupVersions));
|
backupMaxExtensionN.replace(QString("%N"), QString::number(rule.maxBackupVersions));
|
||||||
QString backupMaxFilenameN = _filename + backupMaxExtensionN;
|
QString backupMaxFilenameN = backupFileName + backupMaxExtensionN;
|
||||||
QFile backupMaxFileN(backupMaxFilenameN);
|
QFile backupMaxFileN(backupMaxFilenameN);
|
||||||
if (backupMaxFileN.exists()) {
|
if (backupMaxFileN.exists()) {
|
||||||
int result = remove(qPrintable(backupMaxFilenameN));
|
int result = remove(qPrintable(backupMaxFilenameN));
|
||||||
|
@ -387,8 +390,8 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) {
|
||||||
backupExtensionN.replace(QString("%N"), QString::number(n));
|
backupExtensionN.replace(QString("%N"), QString::number(n));
|
||||||
backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1));
|
backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1));
|
||||||
|
|
||||||
QString backupFilenameN = findMostRecentFileExtension(_filename, PERSIST_EXTENSIONS) + backupExtensionN;
|
QString backupFilenameN = findMostRecentFileExtension(backupFileName, PERSIST_EXTENSIONS) + backupExtensionN;
|
||||||
QString backupFilenameNplusOne = _filename + backupExtensionNplusOne;
|
QString backupFilenameNplusOne = backupFileName + backupExtensionNplusOne;
|
||||||
|
|
||||||
QFile backupFileN(backupFilenameN);
|
QFile backupFileN(backupFilenameN);
|
||||||
|
|
||||||
|
@ -434,21 +437,20 @@ void OctreePersistThread::backup() {
|
||||||
|
|
||||||
struct tm* localTime = localtime(&_lastPersistTime);
|
struct tm* localTime = localtime(&_lastPersistTime);
|
||||||
|
|
||||||
QString backupFileName;
|
QString backupFileName = _backupDirectory + "/" + QUrl(_filename).fileName();
|
||||||
|
|
||||||
// check to see if they asked for version rolling format
|
// check to see if they asked for version rolling format
|
||||||
if (rule.extensionFormat.contains("%N")) {
|
if (rule.extensionFormat.contains("%N")) {
|
||||||
rollOldBackupVersions(rule); // rename all the old backup files accordingly
|
rollOldBackupVersions(rule); // rename all the old backup files accordingly
|
||||||
QString backupExtension = rule.extensionFormat;
|
QString backupExtension = rule.extensionFormat;
|
||||||
backupExtension.replace(QString("%N"), QString("1"));
|
backupExtension.replace(QString("%N"), QString("1"));
|
||||||
backupFileName = _filename + backupExtension;
|
backupFileName += backupExtension;
|
||||||
} else {
|
} else {
|
||||||
char backupExtension[256];
|
char backupExtension[256];
|
||||||
strftime(backupExtension, sizeof(backupExtension), qPrintable(rule.extensionFormat), localTime);
|
strftime(backupExtension, sizeof(backupExtension), qPrintable(rule.extensionFormat), localTime);
|
||||||
backupFileName = _filename + backupExtension;
|
backupFileName += backupExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (rule.maxBackupVersions > 0) {
|
if (rule.maxBackupVersions > 0) {
|
||||||
QFile persistFile(_filename);
|
QFile persistFile(_filename);
|
||||||
if (persistFile.exists()) {
|
if (persistFile.exists()) {
|
||||||
|
|
|
@ -33,9 +33,9 @@ public:
|
||||||
|
|
||||||
static const int DEFAULT_PERSIST_INTERVAL;
|
static const int DEFAULT_PERSIST_INTERVAL;
|
||||||
|
|
||||||
OctreePersistThread(OctreePointer tree, const QString& filename, int persistInterval = DEFAULT_PERSIST_INTERVAL,
|
OctreePersistThread(OctreePointer tree, const QString& filename, const QString& backupDirectory,
|
||||||
bool wantBackup = false, const QJsonObject& settings = QJsonObject(),
|
int persistInterval = DEFAULT_PERSIST_INTERVAL, bool wantBackup = false,
|
||||||
bool debugTimestampNow = false, QString persistAsFileType="svo");
|
const QJsonObject& settings = QJsonObject(), bool debugTimestampNow = false, QString persistAsFileType="svo");
|
||||||
|
|
||||||
bool isInitialLoadComplete() const { return _initialLoadComplete; }
|
bool isInitialLoadComplete() const { return _initialLoadComplete; }
|
||||||
quint64 getLoadElapsedTime() const { return _loadTimeUSecs; }
|
quint64 getLoadElapsedTime() const { return _loadTimeUSecs; }
|
||||||
|
@ -64,6 +64,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
OctreePointer _tree;
|
OctreePointer _tree;
|
||||||
QString _filename;
|
QString _filename;
|
||||||
|
QString _backupDirectory;
|
||||||
int _persistInterval;
|
int _persistInterval;
|
||||||
bool _initialLoadComplete;
|
bool _initialLoadComplete;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "DeferredLightingEffect.h"
|
#include "DeferredLightingEffect.h"
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
|
#include "EntityItem.h"
|
||||||
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
|
@ -517,10 +518,16 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline:
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelMeshPartPayload::startFade() {
|
void ModelMeshPartPayload::startFade() {
|
||||||
_fadeStartTime = usecTimestampNow();
|
bool shouldFade = EntityItem::getEntitiesShouldFadeFunction()();
|
||||||
_hasStartedFade = true;
|
if (shouldFade) {
|
||||||
_prevHasStartedFade = false;
|
_fadeStartTime = usecTimestampNow();
|
||||||
_hasFinishedFade = false;
|
_hasStartedFade = true;
|
||||||
|
_hasFinishedFade = false;
|
||||||
|
} else {
|
||||||
|
_isFading = true;
|
||||||
|
_hasStartedFade = true;
|
||||||
|
_hasFinishedFade = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelMeshPartPayload::render(RenderArgs* args) const {
|
void ModelMeshPartPayload::render(RenderArgs* args) const {
|
||||||
|
@ -533,10 +540,11 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
|
||||||
// When an individual mesh parts like this finishes its fade, we will mark the Model as
|
// When an individual mesh parts like this finishes its fade, we will mark the Model as
|
||||||
// having render items that need updating
|
// having render items that need updating
|
||||||
bool nextIsFading = _isFading ? isStillFading() : false;
|
bool nextIsFading = _isFading ? isStillFading() : false;
|
||||||
if (_isFading != nextIsFading || _prevHasStartedFade != _hasStartedFade) {
|
bool startFading = !_isFading && !_hasFinishedFade && _hasStartedFade;
|
||||||
_isFading = nextIsFading || _prevHasStartedFade != _hasStartedFade;
|
bool endFading = _isFading && !nextIsFading;
|
||||||
_hasFinishedFade = _prevHasStartedFade == _hasStartedFade && !_isFading;
|
if (startFading || endFading) {
|
||||||
_prevHasStartedFade = _hasStartedFade;
|
_isFading = startFading;
|
||||||
|
_hasFinishedFade = endFading;
|
||||||
_model->setRenderItemsNeedUpdate();
|
_model->setRenderItemsNeedUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,6 @@ public:
|
||||||
private:
|
private:
|
||||||
quint64 _fadeStartTime { 0 };
|
quint64 _fadeStartTime { 0 };
|
||||||
bool _hasStartedFade { false };
|
bool _hasStartedFade { false };
|
||||||
mutable bool _prevHasStartedFade{ false };
|
|
||||||
mutable bool _hasFinishedFade { false };
|
mutable bool _hasFinishedFade { false };
|
||||||
mutable bool _isFading { false };
|
mutable bool _isFading { false };
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,19 +108,20 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateSource() {
|
void updateSource() {
|
||||||
Lock lock(_plugin._presentMutex);
|
_plugin.withNonPresentThreadLock([&] {
|
||||||
while (!_queue.empty()) {
|
while (!_queue.empty()) {
|
||||||
auto& front = _queue.front();
|
auto& front = _queue.front();
|
||||||
auto result = glClientWaitSync(front.fence, 0, 0);
|
auto result = glClientWaitSync(front.fence, 0, 0);
|
||||||
if (GL_TIMEOUT_EXPIRED == result && GL_WAIT_FAILED == result) {
|
if (GL_TIMEOUT_EXPIRED == result && GL_WAIT_FAILED == result) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteSync(front.fence);
|
glDeleteSync(front.fence);
|
||||||
front.fence = 0;
|
front.fence = 0;
|
||||||
_current = front;
|
_current = front;
|
||||||
_queue.pop();
|
_queue.pop();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() override {
|
void run() override {
|
||||||
|
@ -170,15 +171,28 @@ public:
|
||||||
PoseData nextRender, nextSim;
|
PoseData nextRender, nextSim;
|
||||||
nextRender.frameIndex = _plugin.presentCount();
|
nextRender.frameIndex = _plugin.presentCount();
|
||||||
vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount);
|
vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount);
|
||||||
{
|
|
||||||
Lock lock(_plugin._presentMutex);
|
// Copy invalid poses in nextSim from nextRender
|
||||||
_presentCount++;
|
for (uint32_t i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i) {
|
||||||
_presented.notify_one();
|
if (!nextSim.vrPoses[i].bPoseIsValid) {
|
||||||
_nextRender = nextRender;
|
nextSim.vrPoses[i] = nextRender.vrPoses[i];
|
||||||
_nextRender.update(_plugin._sensorResetMat);
|
}
|
||||||
_nextSim = nextSim;
|
|
||||||
_nextSim.update(_plugin._sensorResetMat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mat4 sensorResetMat;
|
||||||
|
_plugin.withNonPresentThreadLock([&] {
|
||||||
|
sensorResetMat = _plugin._sensorResetMat;
|
||||||
|
});
|
||||||
|
|
||||||
|
nextRender.update(sensorResetMat);
|
||||||
|
nextSim.update(sensorResetMat);
|
||||||
|
|
||||||
|
_plugin.withNonPresentThreadLock([&] {
|
||||||
|
_nextRender = nextRender;
|
||||||
|
_nextSim = nextSim;
|
||||||
|
++_presentCount;
|
||||||
|
_presented.notify_one();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_canvas.doneCurrent();
|
_canvas.doneCurrent();
|
||||||
}
|
}
|
||||||
|
@ -366,19 +380,20 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
}
|
}
|
||||||
_currentRenderFrameInfo = FrameInfo();
|
_currentRenderFrameInfo = FrameInfo();
|
||||||
|
|
||||||
|
PoseData nextSimPoseData;
|
||||||
withNonPresentThreadLock([&] {
|
withNonPresentThreadLock([&] {
|
||||||
_currentRenderFrameInfo.renderPose = _nextSimPoseData.poses[vr::k_unTrackedDeviceIndex_Hmd];
|
nextSimPoseData = _nextSimPoseData;
|
||||||
});
|
});
|
||||||
|
|
||||||
// HACK: when interface is launched and steam vr is NOT running, openvr will return bad HMD poses for a few frames
|
// HACK: when interface is launched and steam vr is NOT running, openvr will return bad HMD poses for a few frames
|
||||||
// To workaround this, filter out any hmd poses that are obviously bad, i.e. beneath the floor.
|
// To workaround this, filter out any hmd poses that are obviously bad, i.e. beneath the floor.
|
||||||
if (isBadPose(&_nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking)) {
|
if (isBadPose(&nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking)) {
|
||||||
qDebug() << "WARNING: ignoring bad hmd pose from openvr";
|
qDebug() << "WARNING: ignoring bad hmd pose from openvr";
|
||||||
|
|
||||||
// use the last known good HMD pose
|
// use the last known good HMD pose
|
||||||
_nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking = _lastGoodHMDPose;
|
nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking = _lastGoodHMDPose;
|
||||||
} else {
|
} else {
|
||||||
_lastGoodHMDPose = _nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking;
|
_lastGoodHMDPose = nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking;
|
||||||
}
|
}
|
||||||
|
|
||||||
vr::TrackedDeviceIndex_t handIndices[2] { vr::k_unTrackedDeviceIndexInvalid, vr::k_unTrackedDeviceIndexInvalid };
|
vr::TrackedDeviceIndex_t handIndices[2] { vr::k_unTrackedDeviceIndexInvalid, vr::k_unTrackedDeviceIndexInvalid };
|
||||||
|
@ -387,7 +402,7 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
auto trackedCount = _system->GetSortedTrackedDeviceIndicesOfClass(vr::TrackedDeviceClass_Controller, controllerIndices, 2);
|
auto trackedCount = _system->GetSortedTrackedDeviceIndicesOfClass(vr::TrackedDeviceClass_Controller, controllerIndices, 2);
|
||||||
// Find the left and right hand controllers, if they exist
|
// Find the left and right hand controllers, if they exist
|
||||||
for (uint32_t i = 0; i < std::min<uint32_t>(trackedCount, 2); ++i) {
|
for (uint32_t i = 0; i < std::min<uint32_t>(trackedCount, 2); ++i) {
|
||||||
if (_nextSimPoseData.vrPoses[i].bPoseIsValid) {
|
if (nextSimPoseData.vrPoses[i].bPoseIsValid) {
|
||||||
auto role = _system->GetControllerRoleForTrackedDeviceIndex(controllerIndices[i]);
|
auto role = _system->GetControllerRoleForTrackedDeviceIndex(controllerIndices[i]);
|
||||||
if (vr::TrackedControllerRole_LeftHand == role) {
|
if (vr::TrackedControllerRole_LeftHand == role) {
|
||||||
handIndices[0] = controllerIndices[i];
|
handIndices[0] = controllerIndices[i];
|
||||||
|
@ -398,8 +413,7 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentRenderFrameInfo.renderPose = _nextSimPoseData.poses[vr::k_unTrackedDeviceIndex_Hmd];
|
_currentRenderFrameInfo.renderPose = nextSimPoseData.poses[vr::k_unTrackedDeviceIndex_Hmd];
|
||||||
|
|
||||||
bool keyboardVisible = isOpenVrKeyboardShown();
|
bool keyboardVisible = isOpenVrKeyboardShown();
|
||||||
|
|
||||||
std::array<mat4, 2> handPoses;
|
std::array<mat4, 2> handPoses;
|
||||||
|
@ -409,9 +423,9 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto deviceIndex = handIndices[i];
|
auto deviceIndex = handIndices[i];
|
||||||
const mat4& mat = _nextSimPoseData.poses[deviceIndex];
|
const mat4& mat = nextSimPoseData.poses[deviceIndex];
|
||||||
const vec3& linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex];
|
const vec3& linearVelocity = nextSimPoseData.linearVelocities[deviceIndex];
|
||||||
const vec3& angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex];
|
const vec3& angularVelocity = nextSimPoseData.angularVelocities[deviceIndex];
|
||||||
auto correctedPose = openVrControllerPoseToHandPose(i == 0, mat, linearVelocity, angularVelocity);
|
auto correctedPose = openVrControllerPoseToHandPose(i == 0, mat, linearVelocity, angularVelocity);
|
||||||
static const glm::quat HAND_TO_LASER_ROTATION = glm::rotation(Vectors::UNIT_Z, Vectors::UNIT_NEG_Y);
|
static const glm::quat HAND_TO_LASER_ROTATION = glm::rotation(Vectors::UNIT_Z, Vectors::UNIT_NEG_Y);
|
||||||
handPoses[i] = glm::translate(glm::mat4(), correctedPose.translation) * glm::mat4_cast(correctedPose.rotation * HAND_TO_LASER_ROTATION);
|
handPoses[i] = glm::translate(glm::mat4(), correctedPose.translation) * glm::mat4_cast(correctedPose.rotation * HAND_TO_LASER_ROTATION);
|
||||||
|
|
|
@ -66,8 +66,15 @@ struct PoseData {
|
||||||
vec3 linearVelocities[vr::k_unMaxTrackedDeviceCount];
|
vec3 linearVelocities[vr::k_unMaxTrackedDeviceCount];
|
||||||
vec3 angularVelocities[vr::k_unMaxTrackedDeviceCount];
|
vec3 angularVelocities[vr::k_unMaxTrackedDeviceCount];
|
||||||
|
|
||||||
|
PoseData() {
|
||||||
|
memset(vrPoses, 0, sizeof(vr::TrackedDevicePose_t) * vr::k_unMaxTrackedDeviceCount);
|
||||||
|
}
|
||||||
|
|
||||||
void update(const glm::mat4& resetMat) {
|
void update(const glm::mat4& resetMat) {
|
||||||
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
||||||
|
if (!vrPoses[i].bPoseIsValid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
poses[i] = resetMat * toGlm(vrPoses[i].mDeviceToAbsoluteTracking);
|
poses[i] = resetMat * toGlm(vrPoses[i].mDeviceToAbsoluteTracking);
|
||||||
linearVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vVelocity));
|
linearVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vVelocity));
|
||||||
angularVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vAngularVelocity));
|
angularVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vAngularVelocity));
|
||||||
|
|
|
@ -345,10 +345,6 @@ namespace render {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall through: if no skybox is available, render the SKY_DOME
|
|
||||||
case model::SunSkyStage::SKY_DOME:
|
|
||||||
case model::SunSkyStage::NO_BACKGROUND:
|
|
||||||
default:
|
default:
|
||||||
// this line intentionally left blank
|
// this line intentionally left blank
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue