mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 13:50:35 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into emojiAppAdd
This commit is contained in:
commit
9a5812d72c
52 changed files with 1483 additions and 362 deletions
20
BUILD_WIN.md
20
BUILD_WIN.md
|
@ -5,7 +5,7 @@ If you are upgrading from previous versions, do a clean uninstall of those versi
|
||||||
|
|
||||||
Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory.
|
Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory.
|
||||||
|
|
||||||
### Step 1. Visual Studio & Python
|
### Step 1. Visual Studio & Python 3.x
|
||||||
|
|
||||||
If you don’t have Community or Professional edition of Visual Studio, download [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/). If you have Visual Studio 2017, you are not required to download Visual Studio 2019.
|
If you don’t have Community or Professional edition of Visual Studio, download [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/). If you have Visual Studio 2017, you are not required to download Visual Studio 2019.
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ When selecting components, check "Desktop development with C++". On the right on
|
||||||
* MSVC v141 - VS 2017 C++ x64/x86 build tools
|
* MSVC v141 - VS 2017 C++ x64/x86 build tools
|
||||||
* MSVC v140 - VS 2015 C++ build tools (v14.00)
|
* MSVC v140 - VS 2015 C++ build tools (v14.00)
|
||||||
|
|
||||||
If you do not already have a Python development environment installed, also check "Python Development" in this screen.
|
If you do not already have a Python 3.x development environment installed, also check "Python Development" in this screen.
|
||||||
|
|
||||||
If you already have Visual Studio installed and need to add Python, open the "Add or remove programs" control panel and find the "Microsoft Visual Studio Installer". Select it and click "Modify". In the installer, select "Modify" again, then check "Python Development" and allow the installer to apply the changes.
|
If you already have Visual Studio installed and need to add Python, open the "Add or remove programs" control panel and find the "Microsoft Visual Studio Installer". Select it and click "Modify". In the installer, select "Modify" again, then check "Python Development" and allow the installer to apply the changes.
|
||||||
|
|
||||||
|
@ -31,9 +31,10 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo
|
||||||
|
|
||||||
### Step 2. Installing CMake
|
### Step 2. Installing CMake
|
||||||
|
|
||||||
Download and install the latest version of CMake 3.14.
|
Download and install the latest version of CMake 3.15.
|
||||||
|
* Note that earlier versions of CMake will work, but there is a specific bug related to the interaction of Visual Studio 2019 and CMake versions prior to 3.15 that will cause Visual Studio to rebuild far more than it needs to on every build
|
||||||
|
|
||||||
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.14 Version page](https://cmake.org/files/v3.14/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
|
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.15 Version page](https://cmake.org/files/v3.15/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
|
||||||
|
|
||||||
### Step 3. Create VCPKG environment variable
|
### Step 3. Create VCPKG environment variable
|
||||||
In the next step, you will use CMake to build High Fidelity. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them.
|
In the next step, you will use CMake to build High Fidelity. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them.
|
||||||
|
@ -42,9 +43,18 @@ To create this variable:
|
||||||
* Naviagte to 'Edit the System Environment Variables' Through the start menu.
|
* Naviagte to 'Edit the System Environment Variables' Through the start menu.
|
||||||
* Click on 'Environment Variables'
|
* Click on 'Environment Variables'
|
||||||
* Select 'New'
|
* Select 'New'
|
||||||
* Set "Variable name" to HIFI_VCPKG_BASE
|
* Set "Variable name" to `HIFI_VCPKG_BASE`
|
||||||
* Set "Variable value" to any directory that you have control over.
|
* Set "Variable value" to any directory that you have control over.
|
||||||
|
|
||||||
|
Additionally, if you have Visual Studio 2019 installed and _only_ Visual Studio 2019 (i.e. you do not have Visual Studio 2017 installed) you must add an additional environment variable `HIFI_VCPKG_BOOTSTRAP` that will fix a bug in our `vcpkg` pre-build step.
|
||||||
|
|
||||||
|
To create this variable:
|
||||||
|
* Naviagte to 'Edit the System Environment Variables' Through the start menu.
|
||||||
|
* Click on 'Environment Variables'
|
||||||
|
* Select 'New'
|
||||||
|
* Set "Variable name" to `HIFI_VCPKG_BOOTSTRAP`
|
||||||
|
* Set "Variable value" to `1`
|
||||||
|
|
||||||
### Step 4. Running CMake to Generate Build Files
|
### Step 4. Running CMake to Generate Build Files
|
||||||
|
|
||||||
Run Command Prompt from Start and run the following commands:
|
Run Command Prompt from Start and run the following commands:
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
void each(std::function<void(AvatarMixerSlave& slave)> functor);
|
void each(std::function<void(AvatarMixerSlave& slave)> functor);
|
||||||
|
|
||||||
#ifdef DEBUG_EVENT_QUEUE
|
#ifdef DEBUG_EVENT_QUEUE
|
||||||
void AvatarMixerSlavePool::queueStats(QJsonObject& stats);
|
void queueStats(QJsonObject& stats);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void setNumThreads(int numThreads);
|
void setNumThreads(int numThreads);
|
||||||
|
|
|
@ -71,16 +71,19 @@ endif()
|
||||||
|
|
||||||
if 'Windows' == system:
|
if 'Windows' == system:
|
||||||
self.exe = os.path.join(self.path, 'vcpkg.exe')
|
self.exe = os.path.join(self.path, 'vcpkg.exe')
|
||||||
|
self.bootstrapCmd = 'bootstrap-vcpkg.bat'
|
||||||
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-win32.tar.gz?versionId=YZYkDejDRk7L_hrK_WVFthWvisAhbDzZ'
|
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-win32.tar.gz?versionId=YZYkDejDRk7L_hrK_WVFthWvisAhbDzZ'
|
||||||
self.vcpkgHash = '3e0ff829a74956491d57666109b3e6b5ce4ed0735c24093884317102387b2cb1b2cd1ff38af9ed9173501f6e32ffa05cc6fe6d470b77a71ca1ffc3e0aa46ab9e'
|
self.vcpkgHash = '3e0ff829a74956491d57666109b3e6b5ce4ed0735c24093884317102387b2cb1b2cd1ff38af9ed9173501f6e32ffa05cc6fe6d470b77a71ca1ffc3e0aa46ab9e'
|
||||||
self.hostTriplet = 'x64-windows'
|
self.hostTriplet = 'x64-windows'
|
||||||
elif 'Darwin' == system:
|
elif 'Darwin' == system:
|
||||||
self.exe = os.path.join(self.path, 'vcpkg')
|
self.exe = os.path.join(self.path, 'vcpkg')
|
||||||
|
self.bootstrapCmd = 'bootstrap-vcpkg.sh'
|
||||||
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-osx.tar.gz?versionId=_fhqSxjfrtDJBvEsQ8L_ODcdUjlpX9cc'
|
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-osx.tar.gz?versionId=_fhqSxjfrtDJBvEsQ8L_ODcdUjlpX9cc'
|
||||||
self.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d'
|
self.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d'
|
||||||
self.hostTriplet = 'x64-osx'
|
self.hostTriplet = 'x64-osx'
|
||||||
else:
|
else:
|
||||||
self.exe = os.path.join(self.path, 'vcpkg')
|
self.exe = os.path.join(self.path, 'vcpkg')
|
||||||
|
self.bootstrapCmd = 'bootstrap-vcpkg.sh'
|
||||||
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-linux.tar.gz?versionId=97Nazh24etEVKWz33XwgLY0bvxEfZgMU'
|
self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-linux.tar.gz?versionId=97Nazh24etEVKWz33XwgLY0bvxEfZgMU'
|
||||||
self.vcpkgHash = '6a1ce47ef6621e699a4627e8821ad32528c82fce62a6939d35b205da2d299aaa405b5f392df4a9e5343dd6a296516e341105fbb2dd8b48864781d129d7fba10d'
|
self.vcpkgHash = '6a1ce47ef6621e699a4627e8821ad32528c82fce62a6939d35b205da2d299aaa405b5f392df4a9e5343dd6a296516e341105fbb2dd8b48864781d129d7fba10d'
|
||||||
self.hostTriplet = 'x64-linux'
|
self.hostTriplet = 'x64-linux'
|
||||||
|
@ -141,8 +144,14 @@ endif()
|
||||||
downloadVcpkg = True
|
downloadVcpkg = True
|
||||||
|
|
||||||
if downloadVcpkg:
|
if downloadVcpkg:
|
||||||
print("Fetching vcpkg from {} to {}".format(self.vcpkgUrl, self.path))
|
if "HIFI_VCPKG_BOOTSTRAP" in os.environ:
|
||||||
hifi_utils.downloadAndExtract(self.vcpkgUrl, self.path, self.vcpkgHash)
|
print("Cloning vcpkg from github to {}".format(self.path))
|
||||||
|
hifi_utils.executeSubprocess(['git', 'clone', 'git@github.com:microsoft/vcpkg.git', self.path])
|
||||||
|
print("Bootstrapping vcpkg")
|
||||||
|
hifi_utils.executeSubprocess([self.bootstrapCmd], folder=self.path)
|
||||||
|
else:
|
||||||
|
print("Fetching vcpkg from {} to {}".format(self.vcpkgUrl, self.path))
|
||||||
|
hifi_utils.downloadAndExtract(self.vcpkgUrl, self.path, self.vcpkgHash)
|
||||||
|
|
||||||
print("Replacing port files")
|
print("Replacing port files")
|
||||||
portsPath = os.path.join(self.path, 'ports')
|
portsPath = os.path.join(self.path, 'ports')
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
interface/resources/avatar/animations/sitting_emote_clap_all.fbx
Normal file
BIN
interface/resources/avatar/animations/sitting_emote_clap_all.fbx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
interface/resources/avatar/animations/sitting_talk04.fbx
Normal file
BIN
interface/resources/avatar/animations/sitting_talk04.fbx
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -27,11 +27,15 @@ Rectangle {
|
||||||
|
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
|
|
||||||
readonly property real treeScale: 32768; // ~20 miles.. This is the number of meters of the 0.0 to 1.0 voxel universe
|
// This controls the LOD. Larger number will make smaller objects visible at greater distance.
|
||||||
readonly property real halfTreeScale: treeScale / 2;
|
readonly property real defaultMaxVisibilityDistance: 400.0
|
||||||
|
readonly property real unitElementMaxExtent: Math.sqrt(3.0) * 0.5
|
||||||
// This controls the LOD. Larger number will make smaller voxels visible at greater distance.
|
|
||||||
readonly property real defaultOctreeSizeScale: treeScale * 400.0
|
function visibilityDistanceToLODAngleDeg(visibilityDistance) {
|
||||||
|
var lodHalfAngle = Math.atan(unitElementMaxExtent / visibilityDistance);
|
||||||
|
var lodAngle = lodHalfAngle * 2.0;
|
||||||
|
return lodAngle * 180.0 / Math.PI;
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.margins: 10
|
anchors.margins: 10
|
||||||
|
@ -71,7 +75,7 @@ Rectangle {
|
||||||
id: adjustCheckbox
|
id: adjustCheckbox
|
||||||
boxSize: 20
|
boxSize: 20
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
onCheckedChanged: LODManager.setAutomaticLODAdjust(!checked);
|
onCheckedChanged: LODManager.setAutomaticLODAdjust(!adjustCheckbox.checked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,10 +93,10 @@ Rectangle {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
minimumValue: 5
|
minimumValue: 5
|
||||||
maximumValue: 2000
|
maximumValue: 2000
|
||||||
value: LODManager.getOctreeSizeScale() / treeScale
|
value: defaultMaxVisibilityDistance
|
||||||
tickmarksEnabled: false
|
tickmarksEnabled: false
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
LODManager.setOctreeSizeScale(value * treeScale);
|
LODManager.lodAngleDeg = visibilityDistanceToLODAngleDeg(slider.value);
|
||||||
whatYouCanSeeLabel.text = LODManager.getLODFeedbackText()
|
whatYouCanSeeLabel.text = LODManager.getLODFeedbackText()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +110,7 @@ Rectangle {
|
||||||
colorScheme: root.colorScheme
|
colorScheme: root.colorScheme
|
||||||
height: 30
|
height: 30
|
||||||
onClicked: {
|
onClicked: {
|
||||||
slider.value = defaultOctreeSizeScale/treeScale
|
slider.value = defaultMaxVisibilityDistance
|
||||||
adjustCheckbox.checked = false
|
adjustCheckbox.checked = false
|
||||||
LODManager.setAutomaticLODAdjust(adjustCheckbox.checked);
|
LODManager.setAutomaticLODAdjust(adjustCheckbox.checked);
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,7 +292,7 @@ static const uint32_t MAX_CONCURRENT_RESOURCE_DOWNLOADS = 4;
|
||||||
// For processing on QThreadPool, we target a number of threads after reserving some
|
// For processing on QThreadPool, we target a number of threads after reserving some
|
||||||
// based on how many are being consumed by the application and the display plugin. However,
|
// based on how many are being consumed by the application and the display plugin. However,
|
||||||
// we will never drop below the 'min' value
|
// we will never drop below the 'min' value
|
||||||
static const int MIN_PROCESSING_THREAD_POOL_SIZE = 1;
|
static const int MIN_PROCESSING_THREAD_POOL_SIZE = 2;
|
||||||
|
|
||||||
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
||||||
static const QString JPG_EXTENSION = ".jpg";
|
static const QString JPG_EXTENSION = ".jpg";
|
||||||
|
@ -4418,8 +4418,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
} else if (isMeta) {
|
} else if (isMeta) {
|
||||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||||
dialogsManager->toggleAddressBar();
|
dialogsManager->toggleAddressBar();
|
||||||
} else if (isShifted) {
|
|
||||||
Menu::getInstance()->triggerOption(MenuOption::LodTools);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -6817,8 +6815,8 @@ void Application::updateRenderArgs(float deltaTime) {
|
||||||
_viewFrustum.setProjection(adjustedProjection);
|
_viewFrustum.setProjection(adjustedProjection);
|
||||||
_viewFrustum.calculate();
|
_viewFrustum.calculate();
|
||||||
}
|
}
|
||||||
appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(),
|
appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getVisibilityDistance(),
|
||||||
lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE,
|
lodManager->getBoundaryLevelAdjust(), lodManager->getLODHalfAngleTan(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||||
RenderArgs::MONO, RenderArgs::DEFERRED, RenderArgs::RENDER_DEBUG_NONE);
|
RenderArgs::MONO, RenderArgs::DEFERRED, RenderArgs::RENDER_DEBUG_NONE);
|
||||||
appRenderArgs._renderArgs._scene = getMain3DScene();
|
appRenderArgs._renderArgs._scene = getMain3DScene();
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "LODManager.h"
|
#include "LODManager.h"
|
||||||
|
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
#include <OctreeUtils.h>
|
|
||||||
#include <Util.h>
|
#include <Util.h>
|
||||||
#include <shared/GlobalAppProperties.h>
|
#include <shared/GlobalAppProperties.h>
|
||||||
|
|
||||||
|
@ -93,8 +92,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Previous values for output
|
// Previous value for output
|
||||||
float oldOctreeSizeScale = getOctreeSizeScale();
|
|
||||||
float oldLODAngle = getLODAngleDeg();
|
float oldLODAngle = getLODAngleDeg();
|
||||||
|
|
||||||
// Target fps is slightly overshooted by 5hz
|
// Target fps is slightly overshooted by 5hz
|
||||||
|
@ -165,7 +163,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
||||||
// And now add the output of the controller to the LODAngle where we will guarantee it is in the proper range
|
// And now add the output of the controller to the LODAngle where we will guarantee it is in the proper range
|
||||||
setLODAngleDeg(oldLODAngle + output);
|
setLODAngleDeg(oldLODAngle + output);
|
||||||
|
|
||||||
if (oldOctreeSizeScale != _octreeSizeScale) {
|
if (oldLODAngle != getLODAngleDeg()) {
|
||||||
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog();
|
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog();
|
||||||
if (lodToolsDialog) {
|
if (lodToolsDialog) {
|
||||||
lodToolsDialog->reloadSliders();
|
lodToolsDialog->reloadSliders();
|
||||||
|
@ -173,21 +171,32 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float LODManager::getLODAngleHalfTan() const {
|
float LODManager::getLODHalfAngleTan() const {
|
||||||
return getPerspectiveAccuracyAngleTan(_octreeSizeScale, _boundaryLevelAdjust);
|
return tan(_lodHalfAngle);
|
||||||
}
|
}
|
||||||
float LODManager::getLODAngle() const {
|
float LODManager::getLODAngle() const {
|
||||||
return 2.0f * atanf(getLODAngleHalfTan());
|
return 2.0f * _lodHalfAngle;
|
||||||
}
|
}
|
||||||
float LODManager::getLODAngleDeg() const {
|
float LODManager::getLODAngleDeg() const {
|
||||||
return glm::degrees(getLODAngle());
|
return glm::degrees(getLODAngle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float LODManager::getVisibilityDistance() const {
|
||||||
|
float systemDistance = getVisibilityDistanceFromHalfAngle(_lodHalfAngle);
|
||||||
|
// Maintain behavior with deprecated _boundaryLevelAdjust property
|
||||||
|
return systemDistance * powf(2.0f, _boundaryLevelAdjust);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LODManager::setVisibilityDistance(float distance) {
|
||||||
|
// Maintain behavior with deprecated _boundaryLevelAdjust property
|
||||||
|
float userDistance = distance / powf(2.0f, _boundaryLevelAdjust);
|
||||||
|
_lodHalfAngle = getHalfAngleFromVisibilityDistance(userDistance);
|
||||||
|
}
|
||||||
|
|
||||||
void LODManager::setLODAngleDeg(float lodAngle) {
|
void LODManager::setLODAngleDeg(float lodAngle) {
|
||||||
auto newSolidAngle = std::max(0.5f, std::min(lodAngle, 90.f));
|
auto newLODAngleDeg = std::max(0.001f, std::min(lodAngle, 90.f));
|
||||||
auto halTan = glm::tan(glm::radians(newSolidAngle * 0.5f));
|
auto newLODHalfAngle = glm::radians(newLODAngleDeg * 0.5f);
|
||||||
auto octreeSizeScale = TREE_SCALE * OCTREE_TO_MESH_RATIO / halTan;
|
_lodHalfAngle = newLODHalfAngle;
|
||||||
setOctreeSizeScale(octreeSizeScale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LODManager::setSmoothScale(float t) {
|
void LODManager::setSmoothScale(float t) {
|
||||||
|
@ -267,7 +276,11 @@ bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) {
|
||||||
};
|
};
|
||||||
|
|
||||||
void LODManager::setOctreeSizeScale(float sizeScale) {
|
void LODManager::setOctreeSizeScale(float sizeScale) {
|
||||||
_octreeSizeScale = sizeScale;
|
setVisibilityDistance(sizeScale / TREE_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
float LODManager::getOctreeSizeScale() const {
|
||||||
|
return getVisibilityDistance() * TREE_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
|
void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
|
||||||
|
@ -293,12 +306,14 @@ QString LODManager::getLODFeedbackText() {
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
// distance feedback
|
// distance feedback
|
||||||
float octreeSizeScale = getOctreeSizeScale();
|
float visibilityDistance = getVisibilityDistance();
|
||||||
float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
|
float relativeToDefault = visibilityDistance / DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
||||||
int relativeToTwentyTwenty = 20 / relativeToDefault;
|
int relativeToTwentyTwenty = 20 / relativeToDefault;
|
||||||
|
|
||||||
QString result;
|
QString result;
|
||||||
if (relativeToDefault > 1.01f) {
|
if (relativeToTwentyTwenty < 1) {
|
||||||
|
result = QString("%2 times further than average vision%3").arg(relativeToDefault, 0, 'f', 3).arg(granularityFeedback);
|
||||||
|
} else if (relativeToDefault > 1.01f) {
|
||||||
result = QString("20:%1 or %2 times further than average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault, 0, 'f', 2).arg(granularityFeedback);
|
result = QString("20:%1 or %2 times further than average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault, 0, 'f', 2).arg(granularityFeedback);
|
||||||
} else if (relativeToDefault > 0.99f) {
|
} else if (relativeToDefault > 0.99f) {
|
||||||
result = QString("20:20 or the default distance for average vision%1").arg(granularityFeedback);
|
result = QString("20:20 or the default distance for average vision%1").arg(granularityFeedback);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
#include <OctreeConstants.h>
|
#include <OctreeConstants.h>
|
||||||
|
#include <OctreeUtils.h>
|
||||||
#include <PIDController.h>
|
#include <PIDController.h>
|
||||||
#include <SimpleMovingAverage.h>
|
#include <SimpleMovingAverage.h>
|
||||||
#include <render/Args.h>
|
#include <render/Args.h>
|
||||||
|
@ -138,24 +139,28 @@ public:
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function LODManager.setOctreeSizeScale
|
* @function LODManager.setOctreeSizeScale
|
||||||
* @param {number} sizeScale
|
* @param {number} sizeScale
|
||||||
|
* @deprecated This function is deprecated and will be removed. Use the {@link LODManager.lodAngleDeg} property instead.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void setOctreeSizeScale(float sizeScale);
|
Q_INVOKABLE void setOctreeSizeScale(float sizeScale);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function LODManager.getOctreeSizeScale
|
* @function LODManager.getOctreeSizeScale
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
|
* @deprecated This function is deprecated and will be removed. Use the {@link LODManager.lodAngleDeg} property instead.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE float getOctreeSizeScale() const { return _octreeSizeScale; }
|
Q_INVOKABLE float getOctreeSizeScale() const;
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function LODManager.setBoundaryLevelAdjust
|
* @function LODManager.setBoundaryLevelAdjust
|
||||||
* @param {number} boundaryLevelAdjust
|
* @param {number} boundaryLevelAdjust
|
||||||
|
* @deprecated This function is deprecated and will be removed.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function LODManager.getBoundaryLevelAdjust
|
* @function LODManager.getBoundaryLevelAdjust
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
|
* @deprecated This function is deprecated and will be removed.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||||
|
|
||||||
|
@ -196,8 +201,10 @@ public:
|
||||||
|
|
||||||
float getLODAngleDeg() const;
|
float getLODAngleDeg() const;
|
||||||
void setLODAngleDeg(float lodAngle);
|
void setLODAngleDeg(float lodAngle);
|
||||||
float getLODAngleHalfTan() const;
|
float getLODHalfAngleTan() const;
|
||||||
float getLODAngle() const;
|
float getLODAngle() const;
|
||||||
|
float getVisibilityDistance() const;
|
||||||
|
void setVisibilityDistance(float distance);
|
||||||
|
|
||||||
float getPidKp() const;
|
float getPidKp() const;
|
||||||
float getPidKi() const;
|
float getPidKi() const;
|
||||||
|
@ -254,7 +261,7 @@ private:
|
||||||
float _desktopTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_DESKTOP_FPS };
|
float _desktopTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_DESKTOP_FPS };
|
||||||
float _hmdTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS };
|
float _hmdTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS };
|
||||||
|
|
||||||
float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE;
|
float _lodHalfAngle = getHalfAngleFromVisibilityDistance(DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT);
|
||||||
int _boundaryLevelAdjust = 0;
|
int _boundaryLevelAdjust = 0;
|
||||||
|
|
||||||
glm::vec4 _pidCoefs{ 1.0f, 0.0f, 0.0f, 1.0f }; // Kp, Ki, Kd, Kv
|
glm::vec4 _pidCoefs{ 1.0f, 0.0f, 0.0f, 1.0f }; // Kp, Ki, Kd, Kv
|
||||||
|
|
|
@ -258,6 +258,7 @@ void GraphicsEngine::render_performFrame() {
|
||||||
batch.setFramebuffer(finalFramebuffer);
|
batch.setFramebuffer(finalFramebuffer);
|
||||||
batch.enableSkybox(true);
|
batch.enableSkybox(true);
|
||||||
batch.enableStereo(isStereo);
|
batch.enableStereo(isStereo);
|
||||||
|
batch.clearDepthStencilFramebuffer(1.0, 0);
|
||||||
batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() });
|
batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() });
|
||||||
_splashScreen->render(batch, viewFrustum, renderArgs._renderMethod == RenderArgs::RenderMethod::FORWARD);
|
_splashScreen->render(batch, viewFrustum, renderArgs._renderMethod == RenderArgs::RenderMethod::FORWARD);
|
||||||
});
|
});
|
||||||
|
|
|
@ -64,7 +64,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
||||||
_lodSize->setTickPosition(QSlider::TicksBelow);
|
_lodSize->setTickPosition(QSlider::TicksBelow);
|
||||||
_lodSize->setFixedWidth(SLIDER_WIDTH);
|
_lodSize->setFixedWidth(SLIDER_WIDTH);
|
||||||
_lodSize->setPageStep(PAGE_STEP_LOD_SIZE);
|
_lodSize->setPageStep(PAGE_STEP_LOD_SIZE);
|
||||||
int sliderValue = lodManager->getOctreeSizeScale() / TREE_SCALE;
|
int sliderValue = lodManager->getVisibilityDistance();
|
||||||
_lodSize->setValue(sliderValue);
|
_lodSize->setValue(sliderValue);
|
||||||
form->addRow("Level of Detail:", _lodSize);
|
form->addRow("Level of Detail:", _lodSize);
|
||||||
connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int)));
|
connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int)));
|
||||||
|
@ -81,7 +81,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
||||||
|
|
||||||
void LodToolsDialog::reloadSliders() {
|
void LodToolsDialog::reloadSliders() {
|
||||||
auto lodManager = DependencyManager::get<LODManager>();
|
auto lodManager = DependencyManager::get<LODManager>();
|
||||||
_lodSize->setValue(lodManager->getOctreeSizeScale() / TREE_SCALE);
|
_lodSize->setValue(lodManager->getVisibilityDistance());
|
||||||
_feedback->setText(lodManager->getLODFeedbackText());
|
_feedback->setText(lodManager->getLODFeedbackText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,15 +93,14 @@ void LodToolsDialog::updateAutomaticLODAdjust() {
|
||||||
|
|
||||||
void LodToolsDialog::sizeScaleValueChanged(int value) {
|
void LodToolsDialog::sizeScaleValueChanged(int value) {
|
||||||
auto lodManager = DependencyManager::get<LODManager>();
|
auto lodManager = DependencyManager::get<LODManager>();
|
||||||
float realValue = value * TREE_SCALE;
|
lodManager->setVisibilityDistance(value);
|
||||||
lodManager->setOctreeSizeScale(realValue);
|
|
||||||
|
|
||||||
_feedback->setText(lodManager->getLODFeedbackText());
|
_feedback->setText(lodManager->getLODFeedbackText());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LodToolsDialog::resetClicked(bool checked) {
|
void LodToolsDialog::resetClicked(bool checked) {
|
||||||
|
|
||||||
int sliderValue = DEFAULT_OCTREE_SIZE_SCALE / TREE_SCALE;
|
int sliderValue = DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
||||||
_lodSize->setValue(sliderValue);
|
_lodSize->setValue(sliderValue);
|
||||||
_manualLODAdjust->setChecked(false);
|
_manualLODAdjust->setChecked(false);
|
||||||
|
|
||||||
|
@ -124,8 +123,8 @@ void LodToolsDialog::closeEvent(QCloseEvent* event) {
|
||||||
lodManager->setAutomaticLODAdjust(true);
|
lodManager->setAutomaticLODAdjust(true);
|
||||||
|
|
||||||
// if the user adjusted the LOD above "normal" then always revert back to default
|
// if the user adjusted the LOD above "normal" then always revert back to default
|
||||||
if (lodManager->getOctreeSizeScale() > DEFAULT_OCTREE_SIZE_SCALE) {
|
if (lodManager->getVisibilityDistance() > DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) {
|
||||||
lodManager->setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE);
|
lodManager->setVisibilityDistance(DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,8 @@ set(src_files
|
||||||
src/LaunchInterface.h
|
src/LaunchInterface.h
|
||||||
src/CustomUI.h
|
src/CustomUI.h
|
||||||
src/CustomUI.m
|
src/CustomUI.m
|
||||||
|
src/NSTask+NSTaskExecveAdditions.h
|
||||||
|
src/NSTask+NSTaskExecveAdditions.m
|
||||||
src/main.mm
|
src/main.mm
|
||||||
nib/Window.xib
|
nib/Window.xib
|
||||||
nib/SplashScreen.xib
|
nib/SplashScreen.xib
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#import "ProcessScreen.h"
|
#import "ProcessScreen.h"
|
||||||
#import "ErrorViewController.h"
|
#import "ErrorViewController.h"
|
||||||
#import "Settings.h"
|
#import "Settings.h"
|
||||||
|
#import "NSTask+NSTaskExecveAdditions.h"
|
||||||
|
|
||||||
@interface Launcher ()
|
@interface Launcher ()
|
||||||
|
|
||||||
|
@ -456,8 +457,6 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
||||||
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
|
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
|
||||||
NSURL *url = [NSURL fileURLWithPath:[workspace fullPathForApplication:[[self getAppPath] stringByAppendingString:@"interface.app/Contents/MacOS/interface"]]];
|
NSURL *url = [NSURL fileURLWithPath:[workspace fullPathForApplication:[[self getAppPath] stringByAppendingString:@"interface.app/Contents/MacOS/interface"]]];
|
||||||
|
|
||||||
NSError *error = nil;
|
|
||||||
|
|
||||||
NSString* contentPath = [[self getDownloadPathForContentAndScripts] stringByAppendingString:@"content"];
|
NSString* contentPath = [[self getDownloadPathForContentAndScripts] stringByAppendingString:@"content"];
|
||||||
NSString* displayName = [ self displayName];
|
NSString* displayName = [ self displayName];
|
||||||
NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUIBootstrapper.js"];
|
NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUIBootstrapper.js"];
|
||||||
|
@ -484,13 +483,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
||||||
@"--no-updater",
|
@"--no-updater",
|
||||||
@"--no-launcher", nil];
|
@"--no-launcher", nil];
|
||||||
}
|
}
|
||||||
[workspace launchApplicationAtURL:url options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:&error];
|
|
||||||
|
|
||||||
[NSTimer scheduledTimerWithTimeInterval: 3.0
|
NSTask *task = [[NSTask alloc] init];
|
||||||
target: self
|
task.launchPath = [url path];
|
||||||
selector: @selector(exitLauncher:)
|
task.arguments = arguments;
|
||||||
userInfo:nil
|
[task replaceThisProcess];
|
||||||
repeats: NO];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ProcessState) currentProccessState
|
- (ProcessState) currentProccessState
|
||||||
|
@ -500,15 +497,20 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
||||||
|
|
||||||
- (void) callLaunchInterface:(NSTimer*) timer
|
- (void) callLaunchInterface:(NSTimer*) timer
|
||||||
{
|
{
|
||||||
|
NSWindow* mainWindow = [[[NSApplication sharedApplication] windows] objectAtIndex:0];
|
||||||
|
|
||||||
ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil];
|
ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil];
|
||||||
[[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen];
|
[mainWindow setContentViewController: processScreen];
|
||||||
[self launchInterface];
|
@try
|
||||||
}
|
{
|
||||||
|
[self launchInterface];
|
||||||
|
}
|
||||||
- (void) exitLauncher:(NSTimer*) timer
|
@catch (NSException *exception)
|
||||||
{
|
{
|
||||||
[NSApp terminate:self];
|
NSLog(@"Caught exception: Name: %@, Reason: %@", exception.name, exception.reason);
|
||||||
|
ErrorViewController* errorViewController = [[ErrorViewController alloc] initWithNibName:@"ErrorScreen" bundle:nil];
|
||||||
|
[mainWindow setContentViewController: errorViewController];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
9
launchers/darwin/src/NSTask+NSTaskExecveAdditions.h
Normal file
9
launchers/darwin/src/NSTask+NSTaskExecveAdditions.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface NSTask (NSTaskExecveAdditions)
|
||||||
|
- (void) replaceThisProcess;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
73
launchers/darwin/src/NSTask+NSTaskExecveAdditions.m
Normal file
73
launchers/darwin/src/NSTask+NSTaskExecveAdditions.m
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#import "NSTask+NSTaskExecveAdditions.h"
|
||||||
|
|
||||||
|
#import <libgen.h>
|
||||||
|
|
||||||
|
char **
|
||||||
|
toCArray(NSArray<NSString *> *array)
|
||||||
|
{
|
||||||
|
// Add one to count to accommodate the NULL that terminates the array.
|
||||||
|
char **cArray = (char **) calloc([array count] + 1, sizeof(char *));
|
||||||
|
if (cArray == NULL) {
|
||||||
|
NSException *exception = [NSException
|
||||||
|
exceptionWithName:@"MemoryException"
|
||||||
|
reason:@"malloc failed"
|
||||||
|
userInfo:nil];
|
||||||
|
@throw exception;
|
||||||
|
}
|
||||||
|
char *str;
|
||||||
|
for (int i = 0; i < [array count]; i++) {
|
||||||
|
str = (char *) [array[i] UTF8String];
|
||||||
|
if (str == NULL) {
|
||||||
|
NSException *exception = [NSException
|
||||||
|
exceptionWithName:@"NULLStringException"
|
||||||
|
reason:@"UTF8String was NULL"
|
||||||
|
userInfo:nil];
|
||||||
|
@throw exception;
|
||||||
|
}
|
||||||
|
if (asprintf(&cArray[i], "%s", str) == -1) {
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
free(cArray[j]);
|
||||||
|
}
|
||||||
|
free(cArray);
|
||||||
|
NSException *exception = [NSException
|
||||||
|
exceptionWithName:@"MemoryException"
|
||||||
|
reason:@"malloc failed"
|
||||||
|
userInfo:nil];
|
||||||
|
@throw exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation NSTask (NSTaskExecveAdditions)
|
||||||
|
|
||||||
|
- (void) replaceThisProcess {
|
||||||
|
char **args = toCArray([@[[self launchPath]] arrayByAddingObjectsFromArray:[self arguments]]);
|
||||||
|
|
||||||
|
NSMutableArray *env = [[NSMutableArray alloc] init];
|
||||||
|
NSDictionary* environvment = [[NSProcessInfo processInfo] environment];
|
||||||
|
for (NSString* key in environvment) {
|
||||||
|
NSString* environmentVariable = [[key stringByAppendingString:@"="] stringByAppendingString:environvment[key]];
|
||||||
|
[env addObject:environmentVariable];
|
||||||
|
}
|
||||||
|
|
||||||
|
char** envp = toCArray(env);
|
||||||
|
// `execve` replaces the current process with `path`.
|
||||||
|
// It will only return if it fails to replace the current process.
|
||||||
|
chdir(dirname(args[0]));
|
||||||
|
execve(args[0], (char * const *)args, envp);
|
||||||
|
|
||||||
|
// If we're here `execve` failed. :(
|
||||||
|
for (int i = 0; i < [[self arguments] count]; i++) {
|
||||||
|
free((void *) args[i]);
|
||||||
|
}
|
||||||
|
free((void *) args);
|
||||||
|
|
||||||
|
NSException *exception = [NSException
|
||||||
|
exceptionWithName:@"ExecveException"
|
||||||
|
reason:[NSString stringWithFormat:@"couldn't execve: %s", strerror(errno)]
|
||||||
|
userInfo:nil];
|
||||||
|
@throw exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -213,6 +213,12 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float AnimInverseKinematics::getInterpolationAlpha(float timer) {
|
||||||
|
float alpha = (JOINT_CHAIN_INTERP_TIME - timer) / JOINT_CHAIN_INTERP_TIME;
|
||||||
|
alpha = 1.0f - powf(2.0f, -10.0f * alpha);
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<IKTarget>& targets, float dt, JointChainInfoVec& jointChainInfoVec) {
|
void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<IKTarget>& targets, float dt, JointChainInfoVec& jointChainInfoVec) {
|
||||||
// compute absolute poses that correspond to relative target poses
|
// compute absolute poses that correspond to relative target poses
|
||||||
AnimPoseVec absolutePoses;
|
AnimPoseVec absolutePoses;
|
||||||
|
@ -227,6 +233,8 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
||||||
accumulator.clearAndClean();
|
accumulator.clearAndClean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<int, int> targetToChainMap;
|
||||||
|
|
||||||
float maxError = 0.0f;
|
float maxError = 0.0f;
|
||||||
int numLoops = 0;
|
int numLoops = 0;
|
||||||
const int MAX_IK_LOOPS = 16;
|
const int MAX_IK_LOOPS = 16;
|
||||||
|
@ -248,17 +256,13 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// on last iteration, interpolate jointChains, if necessary
|
// on last iteration, interpolate jointChains, if necessary
|
||||||
if (numLoops == MAX_IK_LOOPS) {
|
if (numLoops == MAX_IK_LOOPS) {
|
||||||
for (size_t i = 0; i < _prevJointChainInfoVec.size(); i++) {
|
for (size_t i = 0; i < _prevJointChainInfoVec.size(); i++) {
|
||||||
|
targetToChainMap.insert(std::pair<int, int>(_prevJointChainInfoVec[i].target.getIndex(), (int)i));
|
||||||
if (_prevJointChainInfoVec[i].timer > 0.0f) {
|
if (_prevJointChainInfoVec[i].timer > 0.0f) {
|
||||||
|
float alpha = getInterpolationAlpha(_prevJointChainInfoVec[i].timer);
|
||||||
float alpha = (JOINT_CHAIN_INTERP_TIME - _prevJointChainInfoVec[i].timer) / JOINT_CHAIN_INTERP_TIME;
|
|
||||||
|
|
||||||
// ease in expo
|
|
||||||
alpha = 1.0f - powf(2.0f, -10.0f * alpha);
|
|
||||||
|
|
||||||
size_t chainSize = std::min(_prevJointChainInfoVec[i].jointInfoVec.size(), jointChainInfoVec[i].jointInfoVec.size());
|
size_t chainSize = std::min(_prevJointChainInfoVec[i].jointInfoVec.size(), jointChainInfoVec[i].jointInfoVec.size());
|
||||||
|
|
||||||
if (jointChainInfoVec[i].target.getType() != IKTarget::Type::Unknown) {
|
if (jointChainInfoVec[i].target.getType() != IKTarget::Type::Unknown) {
|
||||||
|
@ -336,22 +340,47 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
||||||
for (auto& target: targets) {
|
for (auto& target: targets) {
|
||||||
int tipIndex = target.getIndex();
|
int tipIndex = target.getIndex();
|
||||||
int parentIndex = (tipIndex >= 0) ? _skeleton->getParentIndex(tipIndex) : -1;
|
int parentIndex = (tipIndex >= 0) ? _skeleton->getParentIndex(tipIndex) : -1;
|
||||||
|
int chainIndex = targetToChainMap[tipIndex];
|
||||||
|
bool needsInterpolation = _prevJointChainInfoVec[chainIndex].timer > 0.0f;
|
||||||
|
float alpha = needsInterpolation ? getInterpolationAlpha(_prevJointChainInfoVec[chainIndex].timer) : 0.0f;
|
||||||
// update rotationOnly targets that don't lie on the ik chain of other ik targets.
|
// update rotationOnly targets that don't lie on the ik chain of other ik targets.
|
||||||
if (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() && target.getType() == IKTarget::Type::RotationOnly) {
|
if (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() &&
|
||||||
const glm::quat& targetRotation = target.getRotation();
|
(target.getType() == IKTarget::Type::RotationOnly || target.getType() == IKTarget::Type::Unknown)) {
|
||||||
// compute tip's new parent-relative rotation
|
if (target.getType() == IKTarget::Type::RotationOnly) {
|
||||||
// Q = Qp * q --> q' = Qp^ * Q
|
const glm::quat& targetRotation = target.getRotation();
|
||||||
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot()) * targetRotation;
|
// compute tip's new parent-relative rotation
|
||||||
RotationConstraint* constraint = getConstraint(tipIndex);
|
// Q = Qp * q --> q' = Qp^ * Q
|
||||||
if (constraint) {
|
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot()) * targetRotation;
|
||||||
constraint->apply(newRelativeRotation);
|
RotationConstraint* constraint = getConstraint(tipIndex);
|
||||||
// TODO: ATM the final rotation target just fails but we need to provide
|
if (constraint) {
|
||||||
// feedback to the IK system so that it can adjust the bones up the skeleton
|
constraint->apply(newRelativeRotation);
|
||||||
// to help this rotation target get met.
|
// TODO: ATM the final rotation target just fails but we need to provide
|
||||||
|
// feedback to the IK system so that it can adjust the bones up the skeleton
|
||||||
|
// to help this rotation target get met.
|
||||||
|
}
|
||||||
|
if (needsInterpolation) {
|
||||||
|
_relativePoses[tipIndex].rot() = safeMix(_relativePoses[tipIndex].rot(), newRelativeRotation, alpha);
|
||||||
|
} else {
|
||||||
|
_relativePoses[tipIndex].rot() = newRelativeRotation;
|
||||||
|
}
|
||||||
|
// Add last known rotations to interpolate from
|
||||||
|
if (_rotationOnlyIKRotations.find(tipIndex) == _rotationOnlyIKRotations.end()) {
|
||||||
|
_rotationOnlyIKRotations.insert(std::pair<int, glm::quat>(tipIndex, _relativePoses[tipIndex].rot()));
|
||||||
|
} else {
|
||||||
|
_rotationOnlyIKRotations[tipIndex] = _relativePoses[tipIndex].rot();
|
||||||
|
}
|
||||||
|
absolutePoses[tipIndex].rot() = targetRotation;
|
||||||
|
} else {
|
||||||
|
bool rotationSnapshotExist = _rotationOnlyIKRotations.find(tipIndex) != _rotationOnlyIKRotations.end();
|
||||||
|
if (needsInterpolation) {
|
||||||
|
if (rotationSnapshotExist) {
|
||||||
|
glm::quat lastKnownRotation = _rotationOnlyIKRotations[tipIndex];
|
||||||
|
_relativePoses[tipIndex].rot() = safeMix(_relativePoses[tipIndex].rot(), lastKnownRotation, (1 - alpha));
|
||||||
|
}
|
||||||
|
} else if (rotationSnapshotExist) {
|
||||||
|
_rotationOnlyIKRotations.erase(tipIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_relativePoses[tipIndex].rot() = newRelativeRotation;
|
|
||||||
absolutePoses[tipIndex].rot() = targetRotation;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,6 +957,10 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
||||||
(jointChainInfoVec[i].target.getType() != _prevJointChainInfoVec[i].target.getType() ||
|
(jointChainInfoVec[i].target.getType() != _prevJointChainInfoVec[i].target.getType() ||
|
||||||
jointChainInfoVec[i].target.getPoleVectorEnabled() != _prevJointChainInfoVec[i].target.getPoleVectorEnabled())) {
|
jointChainInfoVec[i].target.getPoleVectorEnabled() != _prevJointChainInfoVec[i].target.getPoleVectorEnabled())) {
|
||||||
_prevJointChainInfoVec[i].timer = JOINT_CHAIN_INTERP_TIME;
|
_prevJointChainInfoVec[i].timer = JOINT_CHAIN_INTERP_TIME;
|
||||||
|
// Clear the rotations when the target is known
|
||||||
|
if (jointChainInfoVec[i].target.getType() != IKTarget::Type::Unknown) {
|
||||||
|
_rotationOnlyIKRotations.erase(jointChainInfoVec[i].target.getIndex());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,7 @@ protected:
|
||||||
void clearConstraints();
|
void clearConstraints();
|
||||||
void initConstraints();
|
void initConstraints();
|
||||||
void initLimitCenterPoses();
|
void initLimitCenterPoses();
|
||||||
|
float getInterpolationAlpha(float timer);
|
||||||
|
|
||||||
// no copies
|
// no copies
|
||||||
AnimInverseKinematics(const AnimInverseKinematics&) = delete;
|
AnimInverseKinematics(const AnimInverseKinematics&) = delete;
|
||||||
|
@ -181,6 +182,7 @@ protected:
|
||||||
AnimPoseVec _defaultRelativePoses; // poses of the relaxed state
|
AnimPoseVec _defaultRelativePoses; // poses of the relaxed state
|
||||||
AnimPoseVec _relativePoses; // current relative poses
|
AnimPoseVec _relativePoses; // current relative poses
|
||||||
AnimPoseVec _limitCenterPoses; // relative
|
AnimPoseVec _limitCenterPoses; // relative
|
||||||
|
std::map<int, glm::quat> _rotationOnlyIKRotations;
|
||||||
|
|
||||||
std::map<int, AnimPose> _secondaryTargetsInRigFrame;
|
std::map<int, AnimPose> _secondaryTargetsInRigFrame;
|
||||||
|
|
||||||
|
|
|
@ -57,14 +57,12 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
||||||
lowerBound = upperBound;
|
lowerBound = upperBound;
|
||||||
}
|
}
|
||||||
if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1) {
|
if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1) {
|
||||||
_duringInterp = false;
|
switchRandomState(animVars, context, desiredState, false);
|
||||||
switchRandomState(animVars, context, desiredState, _duringInterp);
|
|
||||||
} else {
|
} else {
|
||||||
// firing a random switch, be sure that we aren't completing a previously triggered transition
|
// firing a random switch, be sure that we aren't completing a previously triggered transition
|
||||||
if (currentStateHasPriority) {
|
if (currentStateHasPriority) {
|
||||||
if (desiredState->getID() != _currentState->getID()) {
|
if (desiredState->getID() != _currentState->getID()) {
|
||||||
_duringInterp = true;
|
switchRandomState(animVars, context, desiredState, true);
|
||||||
switchRandomState(animVars, context, desiredState, _duringInterp);
|
|
||||||
} else {
|
} else {
|
||||||
_duringInterp = false;
|
_duringInterp = false;
|
||||||
}
|
}
|
||||||
|
@ -79,8 +77,7 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
||||||
// evaluate currentState transitions
|
// evaluate currentState transitions
|
||||||
auto transitionState = evaluateTransitions(animVars);
|
auto transitionState = evaluateTransitions(animVars);
|
||||||
if (transitionState != _currentState) {
|
if (transitionState != _currentState) {
|
||||||
_duringInterp = true;
|
switchRandomState(animVars, context, transitionState, true);
|
||||||
switchRandomState(animVars, context, transitionState, _duringInterp);
|
|
||||||
_triggerTime = randFloatInRange(_triggerTimeMin, _triggerTimeMax);
|
_triggerTime = randFloatInRange(_triggerTimeMin, _triggerTimeMax);
|
||||||
_randomSwitchTime = randFloatInRange(_randomSwitchTimeMin, _randomSwitchTimeMax);
|
_randomSwitchTime = randFloatInRange(_randomSwitchTimeMin, _randomSwitchTimeMax);
|
||||||
}
|
}
|
||||||
|
@ -172,6 +169,9 @@ void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const A
|
||||||
_lastPlayedState = nextStateNode->getID();
|
_lastPlayedState = nextStateNode->getID();
|
||||||
if (shouldInterp) {
|
if (shouldInterp) {
|
||||||
|
|
||||||
|
bool interpActive = _duringInterp;
|
||||||
|
_duringInterp = true;
|
||||||
|
|
||||||
const float FRAMES_PER_SECOND = 30.0f;
|
const float FRAMES_PER_SECOND = 30.0f;
|
||||||
|
|
||||||
auto prevStateNode = _children[_currentState->getChildIndex()];
|
auto prevStateNode = _children[_currentState->getChildIndex()];
|
||||||
|
@ -195,13 +195,21 @@ void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const A
|
||||||
}
|
}
|
||||||
_nextPoses = nextStateNode->evaluate(animVars, context, dt, triggers);
|
_nextPoses = nextStateNode->evaluate(animVars, context, dt, triggers);
|
||||||
} else if (_interpType == InterpType::SnapshotPrev) {
|
} else if (_interpType == InterpType::SnapshotPrev) {
|
||||||
// snapshot previoius pose
|
// snapshot previous pose
|
||||||
_prevPoses = _poses;
|
_prevPoses = _poses;
|
||||||
// no need to evaluate _nextPoses we will do it dynamically during the interp,
|
// no need to evaluate _nextPoses we will do it dynamically during the interp,
|
||||||
// however we need to set the current frame.
|
// however we need to set the current frame.
|
||||||
if (!desiredState->getResume()) {
|
if (!desiredState->getResume()) {
|
||||||
nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration);
|
nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration);
|
||||||
}
|
}
|
||||||
|
} else if (_interpType == InterpType::EvaluateBoth) {
|
||||||
|
// need to set current frame in destination branch.
|
||||||
|
nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration);
|
||||||
|
if (interpActive) {
|
||||||
|
// snapshot previous pose
|
||||||
|
_prevPoses = _poses;
|
||||||
|
_interpType = InterpType::SnapshotPrev;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,7 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon
|
||||||
auto prevStateNode = _children[_currentState->getChildIndex()];
|
auto prevStateNode = _children[_currentState->getChildIndex()];
|
||||||
auto nextStateNode = _children[desiredState->getChildIndex()];
|
auto nextStateNode = _children[desiredState->getChildIndex()];
|
||||||
|
|
||||||
|
bool interpActive = _duringInterp;
|
||||||
_duringInterp = true;
|
_duringInterp = true;
|
||||||
_alpha = 0.0f;
|
_alpha = 0.0f;
|
||||||
float duration = std::max(0.001f, animVars.lookup(desiredState->_interpDurationVar, desiredState->_interpDuration));
|
float duration = std::max(0.001f, animVars.lookup(desiredState->_interpDurationVar, desiredState->_interpDuration));
|
||||||
|
@ -146,11 +147,19 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon
|
||||||
nextStateNode->setCurrentFrame(desiredState->_interpTarget);
|
nextStateNode->setCurrentFrame(desiredState->_interpTarget);
|
||||||
_nextPoses = nextStateNode->evaluate(animVars, context, dt, triggers);
|
_nextPoses = nextStateNode->evaluate(animVars, context, dt, triggers);
|
||||||
} else if (_interpType == InterpType::SnapshotPrev) {
|
} else if (_interpType == InterpType::SnapshotPrev) {
|
||||||
// snapshot previoius pose
|
// snapshot previous pose
|
||||||
_prevPoses = _poses;
|
_prevPoses = _poses;
|
||||||
// no need to evaluate _nextPoses we will do it dynamically during the interp,
|
// no need to evaluate _nextPoses we will do it dynamically during the interp,
|
||||||
// however we need to set the current frame.
|
// however we need to set the current frame.
|
||||||
nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration);
|
nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration);
|
||||||
|
} else if (_interpType == InterpType::EvaluateBoth) {
|
||||||
|
// need to set current frame in destination branch.
|
||||||
|
nextStateNode->setCurrentFrame(desiredState->_interpTarget - duration);
|
||||||
|
if (interpActive) {
|
||||||
|
// snapshot previous pose
|
||||||
|
_prevPoses = _poses;
|
||||||
|
_interpType = InterpType::SnapshotPrev;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2112,8 +2112,10 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
|
||||||
}
|
}
|
||||||
float easeOutInValue = _talkIdleInterpTime < 0.5f ? 4.0f * powf(_talkIdleInterpTime, 3.0f) : 4.0f * powf((_talkIdleInterpTime - 1.0f), 3.0f) + 1.0f;
|
float easeOutInValue = _talkIdleInterpTime < 0.5f ? 4.0f * powf(_talkIdleInterpTime, 3.0f) : 4.0f * powf((_talkIdleInterpTime - 1.0f), 3.0f) + 1.0f;
|
||||||
_animVars.set("talkOverlayAlpha", easeOutInValue);
|
_animVars.set("talkOverlayAlpha", easeOutInValue);
|
||||||
|
_animVars.set("idleOverlayAlpha", easeOutInValue); // backward compatibility for older anim graphs.
|
||||||
} else {
|
} else {
|
||||||
_animVars.set("talkOverlayAlpha", 1.0f);
|
_animVars.set("talkOverlayAlpha", 1.0f);
|
||||||
|
_animVars.set("idleOverlayAlpha", 1.0f); // backward compatibility for older anim graphs.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_talkIdleInterpTime < 1.0f) {
|
if (_talkIdleInterpTime < 1.0f) {
|
||||||
|
@ -2124,8 +2126,10 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
|
||||||
float easeOutInValue = _talkIdleInterpTime < 0.5f ? 4.0f * powf(_talkIdleInterpTime, 3.0f) : 4.0f * powf((_talkIdleInterpTime - 1.0f), 3.0f) + 1.0f;
|
float easeOutInValue = _talkIdleInterpTime < 0.5f ? 4.0f * powf(_talkIdleInterpTime, 3.0f) : 4.0f * powf((_talkIdleInterpTime - 1.0f), 3.0f) + 1.0f;
|
||||||
float talkAlpha = 1.0f - easeOutInValue;
|
float talkAlpha = 1.0f - easeOutInValue;
|
||||||
_animVars.set("talkOverlayAlpha", talkAlpha);
|
_animVars.set("talkOverlayAlpha", talkAlpha);
|
||||||
|
_animVars.set("idleOverlayAlpha", talkAlpha); // backward compatibility for older anim graphs.
|
||||||
} else {
|
} else {
|
||||||
_animVars.set("talkOverlayAlpha", 0.0f);
|
_animVars.set("talkOverlayAlpha", 0.0f);
|
||||||
|
_animVars.set("idleOverlayAlpha", 0.0f); // backward compatibility for older anim graphs.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,8 @@ public:
|
||||||
void setVsyncEnabled(bool vsyncEnabled) { _vsyncEnabled = vsyncEnabled; }
|
void setVsyncEnabled(bool vsyncEnabled) { _vsyncEnabled = vsyncEnabled; }
|
||||||
bool isVsyncEnabled() const { return _vsyncEnabled; }
|
bool isVsyncEnabled() const { return _vsyncEnabled; }
|
||||||
// Three threads, one for rendering, one for texture transfers, one reserved for the GL driver
|
// Three threads, one for rendering, one for texture transfers, one reserved for the GL driver
|
||||||
int getRequiredThreadCount() const override { return 3; }
|
// Drop to one reserved for better other-task performance in desktop
|
||||||
|
int getRequiredThreadCount() const override { return 1; }
|
||||||
|
|
||||||
virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator() override;
|
virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator() override;
|
||||||
void copyTextureToQuickFramebuffer(NetworkTexturePointer source,
|
void copyTextureToQuickFramebuffer(NetworkTexturePointer source,
|
||||||
|
|
|
@ -53,6 +53,8 @@ public:
|
||||||
void updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
|
void updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
|
||||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||||
float visionSqueezeSpotlightSize);
|
float visionSqueezeSpotlightSize);
|
||||||
|
// Attempt to reserve two threads.
|
||||||
|
int getRequiredThreadCount() const override { return 2; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void hmdMountedChanged();
|
void hmdMountedChanged();
|
||||||
|
|
|
@ -33,8 +33,8 @@ using namespace gpu::gl;
|
||||||
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
|
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool GLTexelFormat::isCompressed() const {
|
bool GLTexelFormat::isCompressed(GLenum format) {
|
||||||
switch (internalFormat) {
|
switch (format) {
|
||||||
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
||||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
||||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||||
|
@ -92,6 +92,11 @@ bool GLTexelFormat::isCompressed() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLTexelFormat::isCompressed() const {
|
||||||
|
return isCompressed(internalFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) {
|
GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) {
|
||||||
GLenum result = GL_RGBA8;
|
GLenum result = GL_RGBA8;
|
||||||
switch (dstFormat.getDimension()) {
|
switch (dstFormat.getDimension()) {
|
||||||
|
|
|
@ -14,13 +14,15 @@ namespace gpu { namespace gl {
|
||||||
|
|
||||||
class GLTexelFormat {
|
class GLTexelFormat {
|
||||||
public:
|
public:
|
||||||
GLenum internalFormat;
|
GLenum internalFormat{ GL_RGBA8 };
|
||||||
GLenum format;
|
GLenum format{ GL_RGBA };
|
||||||
GLenum type;
|
GLenum type{ GL_UNSIGNED_BYTE };
|
||||||
|
|
||||||
GLTexelFormat(GLenum glinternalFormat, GLenum glformat, GLenum gltype) : internalFormat(glinternalFormat), format(glformat), type(gltype) {}
|
GLTexelFormat(GLenum glinternalFormat, GLenum glformat, GLenum gltype) : internalFormat(glinternalFormat), format(glformat), type(gltype) {}
|
||||||
GLTexelFormat(GLenum glinternalFormat) : internalFormat(glinternalFormat) {}
|
GLTexelFormat(GLenum glinternalFormat) : internalFormat(glinternalFormat) {}
|
||||||
|
|
||||||
|
static bool isCompressed(GLenum glinternalFormat);
|
||||||
|
|
||||||
bool isCompressed() const;
|
bool isCompressed() const;
|
||||||
|
|
||||||
static GLTexelFormat evalGLTexelFormat(const Element& dstFormat) {
|
static GLTexelFormat evalGLTexelFormat(const Element& dstFormat) {
|
||||||
|
|
|
@ -33,6 +33,7 @@ class GL45Backend : public GLBackend {
|
||||||
friend class Context;
|
friend class Context;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static const GLint RESOURCE_TRANSFER_TEX_UNIT { 32 };
|
||||||
static GLint MAX_COMBINED_SHADER_STORAGE_BLOCKS;
|
static GLint MAX_COMBINED_SHADER_STORAGE_BLOCKS;
|
||||||
static GLint MAX_UNIFORM_LOCATIONS;
|
static GLint MAX_UNIFORM_LOCATIONS;
|
||||||
#if GPU_BINDLESS_TEXTURES
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
|
|
@ -226,81 +226,31 @@ void GL45Texture::generateMips() const {
|
||||||
|
|
||||||
Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const {
|
Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const {
|
||||||
Size amountCopied = sourceSize;
|
Size amountCopied = sourceSize;
|
||||||
|
bool compressed = GLTexelFormat::isCompressed(internalFormat);
|
||||||
if (GL_TEXTURE_2D == _target) {
|
if (GL_TEXTURE_2D == _target) {
|
||||||
switch (internalFormat) {
|
if (compressed) {
|
||||||
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat,
|
||||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
static_cast<GLsizei>(sourceSize), sourcePointer);
|
||||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
} else {
|
||||||
case GL_COMPRESSED_RED_RGTC1:
|
glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer);
|
||||||
case GL_COMPRESSED_RG_RGTC2:
|
|
||||||
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
|
|
||||||
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
|
|
||||||
case GL_COMPRESSED_RGB8_ETC2:
|
|
||||||
case GL_COMPRESSED_SRGB8_ETC2:
|
|
||||||
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
|
||||||
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
|
||||||
case GL_COMPRESSED_RGBA8_ETC2_EAC:
|
|
||||||
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
|
||||||
case GL_COMPRESSED_R11_EAC:
|
|
||||||
case GL_COMPRESSED_SIGNED_R11_EAC:
|
|
||||||
case GL_COMPRESSED_RG11_EAC:
|
|
||||||
case GL_COMPRESSED_SIGNED_RG11_EAC:
|
|
||||||
glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat,
|
|
||||||
static_cast<GLsizei>(sourceSize), sourcePointer);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else if (GL_TEXTURE_CUBE_MAP == _target) {
|
} else if (GL_TEXTURE_CUBE_MAP == _target) {
|
||||||
switch (internalFormat) {
|
// DSA and cubemap functions are notoriously buggy. use the 4.1 compatible pathway
|
||||||
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
glActiveTexture(GL_TEXTURE0 + GL45Backend::RESOURCE_TRANSFER_TEX_UNIT);
|
||||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
glBindTexture(_target, _texture);
|
||||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
auto target = GLTexture::CUBE_FACE_LAYOUT[face];
|
||||||
case GL_COMPRESSED_RED_RGTC1:
|
if (compressed) {
|
||||||
case GL_COMPRESSED_RG_RGTC2:
|
glCompressedTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, internalFormat,
|
||||||
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
|
static_cast<GLsizei>(sourceSize), sourcePointer);
|
||||||
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
|
} else {
|
||||||
case GL_COMPRESSED_RGB8_ETC2:
|
glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer);
|
||||||
case GL_COMPRESSED_SRGB8_ETC2:
|
|
||||||
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
|
||||||
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
|
||||||
case GL_COMPRESSED_RGBA8_ETC2_EAC:
|
|
||||||
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
|
||||||
case GL_COMPRESSED_R11_EAC:
|
|
||||||
case GL_COMPRESSED_SIGNED_R11_EAC:
|
|
||||||
case GL_COMPRESSED_RG11_EAC:
|
|
||||||
case GL_COMPRESSED_SIGNED_RG11_EAC:
|
|
||||||
#if AMD_CUBE_MAP_EXT_WORKAROUND
|
|
||||||
if (glCompressedTextureSubImage2DEXT) {
|
|
||||||
auto target = GLTexture::CUBE_FACE_LAYOUT[face];
|
|
||||||
glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat,
|
|
||||||
static_cast<GLsizei>(sourceSize), sourcePointer);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
glCompressedTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, internalFormat,
|
|
||||||
static_cast<GLsizei>(sourceSize), sourcePointer);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
#if AMD_CUBE_MAP_EXT_WORKAROUND
|
|
||||||
if (glTextureSubImage2DEXT) {
|
|
||||||
auto target = GLTexture::CUBE_FACE_LAYOUT[face];
|
|
||||||
glTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
glTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, format, type, sourcePointer);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
glBindTexture(_target, 0);
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
amountCopied = 0;
|
amountCopied = 0;
|
||||||
}
|
}
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
return amountCopied;
|
return amountCopied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -334,12 +334,17 @@ void Socket::checkForReadyReadBackup() {
|
||||||
qCDebug(networking) << "Socket::checkForReadyReadyBackup() last sequence number"
|
qCDebug(networking) << "Socket::checkForReadyReadyBackup() last sequence number"
|
||||||
<< (uint32_t) _lastReceivedSequenceNumber << "from" << _lastPacketSockAddr << "-"
|
<< (uint32_t) _lastReceivedSequenceNumber << "from" << _lastPacketSockAddr << "-"
|
||||||
<< _lastPacketSizeRead << "bytes";
|
<< _lastPacketSizeRead << "bytes";
|
||||||
|
#ifdef DEBUG_EVENT_QUEUE
|
||||||
|
qCDebug(networking) << "NodeList event queue size:" << ::hifi::qt::getEventQueueSize(thread());
|
||||||
|
#endif
|
||||||
|
|
||||||
// drop all of the pending datagrams on the floor
|
// drop all of the pending datagrams on the floor
|
||||||
|
int droppedCount = 0;
|
||||||
while (_udpSocket.hasPendingDatagrams()) {
|
while (_udpSocket.hasPendingDatagrams()) {
|
||||||
_udpSocket.readDatagram(nullptr, 0);
|
_udpSocket.readDatagram(nullptr, 0);
|
||||||
|
++droppedCount;
|
||||||
}
|
}
|
||||||
|
qCDebug(networking) << "Flushed" << droppedCount << "Packets";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,9 @@ const int TREE_SCALE = 32768; // ~20 miles.. This is the number of meters of the
|
||||||
const int HALF_TREE_SCALE = TREE_SCALE / 2;
|
const int HALF_TREE_SCALE = TREE_SCALE / 2;
|
||||||
|
|
||||||
// This controls the LOD. Larger number will make smaller voxels visible at greater distance.
|
// This controls the LOD. Larger number will make smaller voxels visible at greater distance.
|
||||||
const float MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT = 400.0f; // max distance where a 1x1x1 cube is visible for 20:20 vision
|
const float DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT = 400.0f; // max distance where a 1x1x1 cube is visible for 20:20 vision
|
||||||
const float DEFAULT_OCTREE_SIZE_SCALE = TREE_SCALE * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
const float UNIT_ELEMENT_MAX_EXTENT = sqrtf(3.0f) / 2.0f; // A unit cube tilted on its edge will have its edge jutting out sqrt(3)/2 units from the center
|
||||||
|
const float DEFAULT_OCTREE_SIZE_SCALE = TREE_SCALE * DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
||||||
|
|
||||||
// Since entities like models live inside of octree cells, and they themselves can have very small mesh parts,
|
// Since entities like models live inside of octree cells, and they themselves can have very small mesh parts,
|
||||||
// we want to have some constant that controls have big a mesh part must be to render even if the octree cell itself
|
// we want to have some constant that controls have big a mesh part must be to render even if the octree cell itself
|
||||||
|
|
|
@ -18,64 +18,31 @@
|
||||||
#include <AABox.h>
|
#include <AABox.h>
|
||||||
#include <AACube.h>
|
#include <AACube.h>
|
||||||
|
|
||||||
float calculateRenderAccuracy(const glm::vec3& position,
|
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float visibilityDistance) {
|
||||||
const AABox& bounds,
|
return visibilityDistance / powf(2.0f, renderLevel);
|
||||||
float octreeSizeScale,
|
|
||||||
int boundaryLevelAdjust) {
|
|
||||||
float largestDimension = bounds.getLargestDimension();
|
|
||||||
|
|
||||||
const float maxScale = (float)TREE_SCALE;
|
|
||||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
|
|
||||||
|
|
||||||
static std::once_flag once;
|
|
||||||
static QMap<float, float> shouldRenderTable;
|
|
||||||
std::call_once(once, [&] {
|
|
||||||
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
|
|
||||||
float scale = maxScale;
|
|
||||||
float factor = 1.0f;
|
|
||||||
|
|
||||||
while (scale > SMALLEST_SCALE_IN_TABLE) {
|
|
||||||
scale /= 2.0f;
|
|
||||||
factor /= 2.0f;
|
|
||||||
shouldRenderTable[scale] = factor;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
float closestScale = maxScale;
|
|
||||||
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
|
|
||||||
QMap<float, float>::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension);
|
|
||||||
if (lowerBound != shouldRenderTable.constEnd()) {
|
|
||||||
closestScale = lowerBound.key();
|
|
||||||
visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closestScale < largestDimension) {
|
|
||||||
visibleDistanceAtClosestScale *= 2.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return
|
|
||||||
// a floating point for objects that have small angular size to indicate that they may be rendered
|
|
||||||
// with lower preciscion
|
|
||||||
float distanceToCamera = glm::length(bounds.calcCenter() - position);
|
|
||||||
return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
|
float getPerspectiveAccuracyHalfAngleTan(float visibilityDistance, int boundaryLevelAdjust) {
|
||||||
return voxelSizeScale / powf(2.0f, renderLevel);
|
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, visibilityDistance);
|
||||||
|
return UNIT_ELEMENT_MAX_EXTENT / visibleDistanceAtMaxScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getPerspectiveAccuracyAngleTan(float octreeSizeScale, int boundaryLevelAdjust) {
|
float getPerspectiveAccuracyHalfAngle(float visibilityDistance, int boundaryLevelAdjust) {
|
||||||
const float maxScale = (float)TREE_SCALE;
|
return atan(getPerspectiveAccuracyHalfAngleTan(visibilityDistance, boundaryLevelAdjust));
|
||||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
|
|
||||||
return (maxScale / visibleDistanceAtMaxScale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float getPerspectiveAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) {
|
float getVisibilityDistanceFromHalfAngle(float halfAngle) {
|
||||||
return atan(getPerspectiveAccuracyAngleTan(octreeSizeScale, boundaryLevelAdjust));
|
float halfAngleTan = tan(halfAngle);
|
||||||
|
return UNIT_ELEMENT_MAX_EXTENT / halfAngleTan;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust) {
|
float getHalfAngleFromVisibilityDistance(float visibilityDistance) {
|
||||||
|
float halfAngleTan = UNIT_ELEMENT_MAX_EXTENT / visibilityDistance;
|
||||||
|
return atan(halfAngleTan);
|
||||||
|
}
|
||||||
|
|
||||||
|
float getOrthographicAccuracySize(float visibilityDistance, int boundaryLevelAdjust) {
|
||||||
// Smallest visible element is 1cm
|
// Smallest visible element is 1cm
|
||||||
const float smallestSize = 0.01f;
|
const float smallestSize = 0.01f;
|
||||||
return (smallestSize * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) / boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale);
|
return (smallestSize * DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) / boundaryDistanceForRenderLevel(boundaryLevelAdjust, visibilityDistance);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,13 @@ class AABox;
|
||||||
class AACube;
|
class AACube;
|
||||||
class QJsonDocument;
|
class QJsonDocument;
|
||||||
|
|
||||||
/// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple
|
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float visibilityDistance);
|
||||||
/// level it returns 0.0f for things that are so small for the current settings that they could not be visible.
|
|
||||||
float calculateRenderAccuracy(const glm::vec3& position,
|
|
||||||
const AABox& bounds,
|
|
||||||
float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
|
|
||||||
int boundaryLevelAdjust = 0);
|
|
||||||
|
|
||||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
|
float getPerspectiveAccuracyHalfAngleTan(float visibilityDistance, int boundaryLevelAdjust);
|
||||||
|
float getPerspectiveAccuracyHalfAngle(float visibilityDistance, int boundaryLevelAdjust);
|
||||||
float getPerspectiveAccuracyAngleTan(float octreeSizeScale, int boundaryLevelAdjust);
|
float getVisibilityDistanceFromHalfAngle(float halfAngle);
|
||||||
float getPerspectiveAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust);
|
float getHalfAngleFromVisibilityDistance(float visibilityDistance);
|
||||||
float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust);
|
float getOrthographicAccuracySize(float visibilityDistance, int boundaryLevelAdjust);
|
||||||
|
|
||||||
// MIN_ELEMENT_ANGULAR_DIAMETER = angular diameter of 1x1x1m cube at 400m = sqrt(3) / 400 = 0.0043301 radians ~= 0.25 degrees
|
// MIN_ELEMENT_ANGULAR_DIAMETER = angular diameter of 1x1x1m cube at 400m = sqrt(3) / 400 = 0.0043301 radians ~= 0.25 degrees
|
||||||
const float MIN_ELEMENT_ANGULAR_DIAMETER = 0.0043301f; // radians
|
const float MIN_ELEMENT_ANGULAR_DIAMETER = 0.0043301f; // radians
|
||||||
|
|
|
@ -120,7 +120,7 @@ void DrawSceneOctree::run(const RenderContextPointer& renderContext, const ItemS
|
||||||
|
|
||||||
// Draw the LOD Reticle
|
// Draw the LOD Reticle
|
||||||
{
|
{
|
||||||
float angle = glm::degrees(getPerspectiveAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
|
float angle = glm::degrees(getPerspectiveAccuracyHalfAngle(args->_sizeScale, args->_boundaryLevelAdjust));
|
||||||
Transform crosshairModel;
|
Transform crosshairModel;
|
||||||
crosshairModel.setTranslation(glm::vec3(0.0, 0.0, -1000.0));
|
crosshairModel.setTranslation(glm::vec3(0.0, 0.0, -1000.0));
|
||||||
crosshairModel.setScale(1000.0f * tanf(glm::radians(angle))); // Scaling at the actual tan of the lod angle => Multiplied by TWO
|
crosshairModel.setScale(1000.0f * tanf(glm::radians(angle))); // Scaling at the actual tan of the lod angle => Multiplied by TWO
|
||||||
|
|
|
@ -30,34 +30,18 @@ Q_DECLARE_METATYPE(QByteArray*)
|
||||||
|
|
||||||
XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) :
|
XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) :
|
||||||
_engine(engine),
|
_engine(engine),
|
||||||
_async(true),
|
_timer(this) {
|
||||||
_url(),
|
|
||||||
_method(""),
|
|
||||||
_responseType(""),
|
|
||||||
_request(),
|
|
||||||
_reply(NULL),
|
|
||||||
_sendData(NULL),
|
|
||||||
_rawResponseData(),
|
|
||||||
_responseData(""),
|
|
||||||
_onTimeout(QScriptValue::NullValue),
|
|
||||||
_onReadyStateChange(QScriptValue::NullValue),
|
|
||||||
_readyState(XMLHttpRequestClass::UNSENT),
|
|
||||||
_errorCode(QNetworkReply::NoError),
|
|
||||||
_timeout(0),
|
|
||||||
_timer(this),
|
|
||||||
_numRedirects(0) {
|
|
||||||
|
|
||||||
_request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
_request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||||
_timer.setSingleShot(true);
|
_timer.setSingleShot(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLHttpRequestClass::~XMLHttpRequestClass() {
|
XMLHttpRequestClass::~XMLHttpRequestClass() {
|
||||||
if (_reply) { delete _reply; }
|
if (_reply) { _reply->deleteLater(); }
|
||||||
if (_sendData) { delete _sendData; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue XMLHttpRequestClass::constructor(QScriptContext* context, QScriptEngine* engine) {
|
QScriptValue XMLHttpRequestClass::constructor(QScriptContext* context, QScriptEngine* engine) {
|
||||||
return engine->newQObject(new XMLHttpRequestClass(engine));
|
return engine->newQObject(new XMLHttpRequestClass(engine), QScriptEngine::ScriptOwnership);
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue XMLHttpRequestClass::getStatus() const {
|
QScriptValue XMLHttpRequestClass::getStatus() const {
|
||||||
|
@ -169,13 +153,12 @@ void XMLHttpRequestClass::send() {
|
||||||
|
|
||||||
void XMLHttpRequestClass::send(const QScriptValue& data) {
|
void XMLHttpRequestClass::send(const QScriptValue& data) {
|
||||||
if (_readyState == OPENED && !_reply) {
|
if (_readyState == OPENED && !_reply) {
|
||||||
|
|
||||||
if (!data.isNull()) {
|
if (!data.isNull()) {
|
||||||
_sendData = new QBuffer(this);
|
|
||||||
if (data.isObject()) {
|
if (data.isObject()) {
|
||||||
QByteArray ba = qscriptvalue_cast<QByteArray>(data);
|
_sendData = qscriptvalue_cast<QByteArray>(data);
|
||||||
_sendData->setData(ba);
|
|
||||||
} else {
|
} else {
|
||||||
_sendData->setData(data.toString().toUtf8());
|
_sendData = data.toString().toUtf8();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +220,10 @@ void XMLHttpRequestClass::requestFinished() {
|
||||||
|
|
||||||
setReadyState(DONE);
|
setReadyState(DONE);
|
||||||
emit requestComplete();
|
emit requestComplete();
|
||||||
|
|
||||||
|
disconnectFromReply(_reply);
|
||||||
|
_reply->deleteLater();
|
||||||
|
_reply = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XMLHttpRequestClass::abortRequest() {
|
void XMLHttpRequestClass::abortRequest() {
|
||||||
|
@ -246,7 +233,7 @@ void XMLHttpRequestClass::abortRequest() {
|
||||||
disconnectFromReply(_reply);
|
disconnectFromReply(_reply);
|
||||||
_reply->abort();
|
_reply->abort();
|
||||||
_reply->deleteLater();
|
_reply->deleteLater();
|
||||||
_reply = NULL;
|
_reply = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,23 +98,23 @@ private:
|
||||||
void disconnectFromReply(QNetworkReply* reply);
|
void disconnectFromReply(QNetworkReply* reply);
|
||||||
void abortRequest();
|
void abortRequest();
|
||||||
|
|
||||||
QScriptEngine* _engine;
|
QScriptEngine* _engine { nullptr };
|
||||||
bool _async;
|
bool _async { true };
|
||||||
QUrl _url;
|
QUrl _url;
|
||||||
QString _method;
|
QString _method;
|
||||||
QString _responseType;
|
QString _responseType;
|
||||||
QNetworkRequest _request;
|
QNetworkRequest _request;
|
||||||
QNetworkReply* _reply;
|
QNetworkReply* _reply { nullptr };
|
||||||
QBuffer* _sendData;
|
QByteArray _sendData;
|
||||||
QByteArray _rawResponseData;
|
QByteArray _rawResponseData;
|
||||||
QScriptValue _responseData;
|
QScriptValue _responseData;
|
||||||
QScriptValue _onTimeout;
|
QScriptValue _onTimeout { QScriptValue::NullValue };
|
||||||
QScriptValue _onReadyStateChange;
|
QScriptValue _onReadyStateChange { QScriptValue::NullValue };
|
||||||
ReadyState _readyState;
|
ReadyState _readyState { XMLHttpRequestClass::UNSENT };
|
||||||
QNetworkReply::NetworkError _errorCode;
|
QNetworkReply::NetworkError _errorCode { QNetworkReply::NoError };
|
||||||
int _timeout;
|
int _timeout { 0 };
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
int _numRedirects;
|
int _numRedirects { 0 };
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void requestFinished();
|
void requestFinished();
|
||||||
|
|
|
@ -39,6 +39,10 @@ Q_LOGGING_CATEGORY(trace_baker, "trace.baker")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool tracingEnabled() {
|
static bool tracingEnabled() {
|
||||||
|
if (!DependencyManager::isSet<tracing::Tracer>()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Cheers, love! The cavalry's here!
|
// Cheers, love! The cavalry's here!
|
||||||
auto tracer = DependencyManager::get<tracing::Tracer>();
|
auto tracer = DependencyManager::get<tracing::Tracer>();
|
||||||
return (tracer && tracer->isEnabled());
|
return (tracer && tracer->isEnabled());
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
#ifdef WIN32
|
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
|
||||||
// Enable event queue debugging
|
// Enable event queue debugging
|
||||||
#define DEBUG_EVENT_QUEUE
|
#define DEBUG_EVENT_QUEUE
|
||||||
#endif // WIN32
|
#endif
|
||||||
|
|
||||||
namespace hifi { namespace qt {
|
namespace hifi { namespace qt {
|
||||||
void addBlockingForbiddenThread(const QString& name, QThread* thread = nullptr);
|
void addBlockingForbiddenThread(const QString& name, QThread* thread = nullptr);
|
||||||
|
|
|
@ -80,7 +80,7 @@ Item {
|
||||||
valueVar: LODManager["lodAngleDeg"]
|
valueVar: LODManager["lodAngleDeg"]
|
||||||
valueVarSetter: (function (v) { LODManager["lodAngleDeg"] = v })
|
valueVarSetter: (function (v) { LODManager["lodAngleDeg"] = v })
|
||||||
max: 90.0
|
max: 90.0
|
||||||
min: 0.5
|
min: 0.01
|
||||||
integral: false
|
integral: false
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -239,6 +239,7 @@ Item {
|
||||||
object: LODManager
|
object: LODManager
|
||||||
valueScale: 1.0
|
valueScale: 1.0
|
||||||
valueUnit: "deg"
|
valueUnit: "deg"
|
||||||
|
valueNumDigits: 2
|
||||||
plots: [
|
plots: [
|
||||||
{
|
{
|
||||||
prop: "lodAngleDeg",
|
prop: "lodAngleDeg",
|
||||||
|
|
|
@ -39,6 +39,10 @@ module.exports = {
|
||||||
if (error) {
|
if (error) {
|
||||||
response = { statusCode: httpRequest.status };
|
response = { statusCode: httpRequest.status };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Break circular reference to httpRequest so the engine can garbage collect it.
|
||||||
|
httpRequest.onreadystatechange = null;
|
||||||
|
|
||||||
callback(error, response, optionalCallbackParameter);
|
callback(error, response, optionalCallbackParameter);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -476,7 +476,7 @@ function maybeUpdateOutputDeviceMutedOverlay() {
|
||||||
var oldAutomaticLODAdjust;
|
var oldAutomaticLODAdjust;
|
||||||
var oldLODAngleDeg;
|
var oldLODAngleDeg;
|
||||||
var SIMPLIFIED_UI_AUTO_LOD_ADJUST = false;
|
var SIMPLIFIED_UI_AUTO_LOD_ADJUST = false;
|
||||||
var SIMPLIFIED_UI_LOD_ANGLE_DEG = 0.5;
|
var SIMPLIFIED_UI_LOD_ANGLE_DEG = 0.248;
|
||||||
function modifyLODSettings() {
|
function modifyLODSettings() {
|
||||||
oldAutomaticLODAdjust = LODManager.automaticLODAdjust;
|
oldAutomaticLODAdjust = LODManager.automaticLODAdjust;
|
||||||
oldLODAngleDeg = LODManager.lodAngleDeg;
|
oldLODAngleDeg = LODManager.lodAngleDeg;
|
||||||
|
|
|
@ -355,7 +355,7 @@ CameraManager = function() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.isRightButton || (event.isLeftButton && event.isControl && !event.isShifted)) {
|
if (event.isRightButton || (event.isLeftButton && event.isAlt && !event.isShifted)) {
|
||||||
that.mode = MODE_ORBIT;
|
that.mode = MODE_ORBIT;
|
||||||
} else if (event.isMiddleButton || (event.isLeftButton && event.isControl && event.isShifted)) {
|
} else if (event.isMiddleButton || (event.isLeftButton && event.isControl && event.isShifted)) {
|
||||||
that.mode = MODE_PAN;
|
that.mode = MODE_PAN;
|
||||||
|
|
|
@ -30,6 +30,8 @@ source_group("UI Files" FILES ${QT_UI_FILES})
|
||||||
# have qt5 wrap them and generate the appropriate header files
|
# have qt5 wrap them and generate the appropriate header files
|
||||||
qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
|
qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
|
||||||
|
|
||||||
|
setup_memory_debugger()
|
||||||
|
|
||||||
# add them to the nitpick source files
|
# add them to the nitpick source files
|
||||||
set(NITPICK_SRCS ${NITPICK_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
|
set(NITPICK_SRCS ${NITPICK_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,23 @@ static const QString CLI_OUTPUT_PARAMETER = "o";
|
||||||
static const QString CLI_TYPE_PARAMETER = "t";
|
static const QString CLI_TYPE_PARAMETER = "t";
|
||||||
static const QString CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER = "disable-texture-compression";
|
static const QString CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER = "disable-texture-compression";
|
||||||
|
|
||||||
|
QUrl OvenCLIApplication::_inputUrlParameter;
|
||||||
|
QUrl OvenCLIApplication::_outputUrlParameter;
|
||||||
|
QString OvenCLIApplication::_typeParameter;
|
||||||
|
|
||||||
OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
||||||
QCoreApplication(argc, argv)
|
QCoreApplication(argc, argv)
|
||||||
{
|
{
|
||||||
|
BakerCLI* cli = new BakerCLI(this);
|
||||||
|
QMetaObject::invokeMethod(cli, "bakeFile", Qt::QueuedConnection, Q_ARG(QUrl, _inputUrlParameter),
|
||||||
|
Q_ARG(QString, _outputUrlParameter.toString()), Q_ARG(QString, _typeParameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OvenCLIApplication::parseCommandLine(int argc, char* argv[]) {
|
||||||
// parse the command line parameters
|
// parse the command line parameters
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
|
|
||||||
|
parser.setApplicationDescription("High Fidelity Oven");
|
||||||
parser.addOptions({
|
parser.addOptions({
|
||||||
{ CLI_INPUT_PARAMETER, "Path to file that you would like to bake.", "input" },
|
{ CLI_INPUT_PARAMETER, "Path to file that you would like to bake.", "input" },
|
||||||
{ CLI_OUTPUT_PARAMETER, "Path to folder that will be used as output.", "output" },
|
{ CLI_OUTPUT_PARAMETER, "Path to folder that will be used as output.", "output" },
|
||||||
|
@ -37,25 +48,45 @@ OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
||||||
{ CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER, "Disable texture compression." }
|
{ CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER, "Disable texture compression." }
|
||||||
});
|
});
|
||||||
|
|
||||||
parser.addHelpOption();
|
auto versionOption = parser.addVersionOption();
|
||||||
parser.process(*this);
|
auto helpOption = parser.addHelpOption();
|
||||||
|
|
||||||
if (parser.isSet(CLI_INPUT_PARAMETER) && parser.isSet(CLI_OUTPUT_PARAMETER)) {
|
QStringList arguments;
|
||||||
BakerCLI* cli = new BakerCLI(this);
|
for (int i = 0; i < argc; ++i) {
|
||||||
QUrl inputUrl(QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER)));
|
arguments << argv[i];
|
||||||
QUrl outputUrl(QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER)));
|
|
||||||
QString type = parser.isSet(CLI_TYPE_PARAMETER) ? parser.value(CLI_TYPE_PARAMETER) : QString::null;
|
|
||||||
|
|
||||||
if (parser.isSet(CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER)) {
|
|
||||||
qDebug() << "Disabling texture compression";
|
|
||||||
TextureBaker::setCompressionEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
QMetaObject::invokeMethod(cli, "bakeFile", Qt::QueuedConnection, Q_ARG(QUrl, inputUrl),
|
|
||||||
Q_ARG(QString, outputUrl.toString()), Q_ARG(QString, type));
|
|
||||||
} else {
|
|
||||||
parser.showHelp();
|
|
||||||
QCoreApplication::quit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!parser.parse(arguments)) {
|
||||||
|
std::cout << parser.errorText().toStdString() << std::endl; // Avoid Qt log spam
|
||||||
|
QCoreApplication mockApp(argc, argv); // required for call to showHelp()
|
||||||
|
parser.showHelp();
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(versionOption)) {
|
||||||
|
parser.showVersion();
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
if (parser.isSet(helpOption)) {
|
||||||
|
QCoreApplication mockApp(argc, argv); // required for call to showHelp()
|
||||||
|
parser.showHelp();
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parser.isSet(CLI_INPUT_PARAMETER) || !parser.isSet(CLI_OUTPUT_PARAMETER)) {
|
||||||
|
std::cout << "Error: Input and Output not set" << std::endl; // Avoid Qt log spam
|
||||||
|
QCoreApplication mockApp(argc, argv); // required for call to showHelp()
|
||||||
|
parser.showHelp();
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
_inputUrlParameter = QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER));
|
||||||
|
_outputUrlParameter = QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER));
|
||||||
|
|
||||||
|
_typeParameter = parser.isSet(CLI_TYPE_PARAMETER) ? parser.value(CLI_TYPE_PARAMETER) : QString::null;
|
||||||
|
|
||||||
|
if (parser.isSet(CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER)) {
|
||||||
|
qDebug() << "Disabling texture compression";
|
||||||
|
TextureBaker::setCompressionEnabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,14 @@ class OvenCLIApplication : public QCoreApplication, public Oven {
|
||||||
public:
|
public:
|
||||||
OvenCLIApplication(int argc, char* argv[]);
|
OvenCLIApplication(int argc, char* argv[]);
|
||||||
|
|
||||||
|
static void parseCommandLine(int argc, char* argv[]);
|
||||||
|
|
||||||
static OvenCLIApplication* instance() { return dynamic_cast<OvenCLIApplication*>(QCoreApplication::instance()); }
|
static OvenCLIApplication* instance() { return dynamic_cast<OvenCLIApplication*>(QCoreApplication::instance()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QUrl _inputUrlParameter;
|
||||||
|
static QUrl _outputUrlParameter;
|
||||||
|
static QString _typeParameter;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_OvenCLIApplication_h
|
#endif // hifi_OvenCLIApplication_h
|
||||||
|
|
|
@ -18,14 +18,19 @@
|
||||||
int main (int argc, char** argv) {
|
int main (int argc, char** argv) {
|
||||||
setupHifiApplication("Oven");
|
setupHifiApplication("Oven");
|
||||||
|
|
||||||
// init the settings interface so we can save and load settings
|
|
||||||
Setting::init();
|
|
||||||
|
|
||||||
// figure out if we're launching our GUI application or just the simple command line interface
|
// figure out if we're launching our GUI application or just the simple command line interface
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
|
OvenCLIApplication::parseCommandLine(argc, argv);
|
||||||
|
|
||||||
|
// init the settings interface so we can save and load settings
|
||||||
|
Setting::init();
|
||||||
|
|
||||||
OvenCLIApplication app { argc, argv };
|
OvenCLIApplication app { argc, argv };
|
||||||
return app.exec();
|
return app.exec();
|
||||||
} else {
|
} else {
|
||||||
|
// init the settings interface so we can save and load settings
|
||||||
|
Setting::init();
|
||||||
|
|
||||||
OvenGUIApplication app { argc, argv };
|
OvenGUIApplication app { argc, argv };
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue