mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:04:13 +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.
|
||||
|
||||
### 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.
|
||||
|
||||
|
@ -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 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.
|
||||
|
||||
|
@ -31,9 +31,10 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo
|
|||
|
||||
### 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
|
||||
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.
|
||||
* Click on 'Environment Variables'
|
||||
* 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.
|
||||
|
||||
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
|
||||
|
||||
Run Command Prompt from Start and run the following commands:
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
void each(std::function<void(AvatarMixerSlave& slave)> functor);
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
void AvatarMixerSlavePool::queueStats(QJsonObject& stats);
|
||||
void queueStats(QJsonObject& stats);
|
||||
#endif
|
||||
|
||||
void setNumThreads(int numThreads);
|
||||
|
|
|
@ -71,16 +71,19 @@ endif()
|
|||
|
||||
if 'Windows' == system:
|
||||
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.vcpkgHash = '3e0ff829a74956491d57666109b3e6b5ce4ed0735c24093884317102387b2cb1b2cd1ff38af9ed9173501f6e32ffa05cc6fe6d470b77a71ca1ffc3e0aa46ab9e'
|
||||
self.hostTriplet = 'x64-windows'
|
||||
elif 'Darwin' == system:
|
||||
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.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d'
|
||||
self.hostTriplet = 'x64-osx'
|
||||
else:
|
||||
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.vcpkgHash = '6a1ce47ef6621e699a4627e8821ad32528c82fce62a6939d35b205da2d299aaa405b5f392df4a9e5343dd6a296516e341105fbb2dd8b48864781d129d7fba10d'
|
||||
self.hostTriplet = 'x64-linux'
|
||||
|
@ -141,8 +144,14 @@ endif()
|
|||
downloadVcpkg = True
|
||||
|
||||
if downloadVcpkg:
|
||||
print("Fetching vcpkg from {} to {}".format(self.vcpkgUrl, self.path))
|
||||
hifi_utils.downloadAndExtract(self.vcpkgUrl, self.path, self.vcpkgHash)
|
||||
if "HIFI_VCPKG_BOOTSTRAP" in os.environ:
|
||||
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")
|
||||
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 }
|
||||
|
||||
readonly property real treeScale: 32768; // ~20 miles.. This is the number of meters of the 0.0 to 1.0 voxel universe
|
||||
readonly property real halfTreeScale: treeScale / 2;
|
||||
|
||||
// This controls the LOD. Larger number will make smaller voxels visible at greater distance.
|
||||
readonly property real defaultOctreeSizeScale: treeScale * 400.0
|
||||
// This controls the LOD. Larger number will make smaller objects visible at greater distance.
|
||||
readonly property real defaultMaxVisibilityDistance: 400.0
|
||||
readonly property real unitElementMaxExtent: Math.sqrt(3.0) * 0.5
|
||||
|
||||
function visibilityDistanceToLODAngleDeg(visibilityDistance) {
|
||||
var lodHalfAngle = Math.atan(unitElementMaxExtent / visibilityDistance);
|
||||
var lodAngle = lodHalfAngle * 2.0;
|
||||
return lodAngle * 180.0 / Math.PI;
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.margins: 10
|
||||
|
@ -71,7 +75,7 @@ Rectangle {
|
|||
id: adjustCheckbox
|
||||
boxSize: 20
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onCheckedChanged: LODManager.setAutomaticLODAdjust(!checked);
|
||||
onCheckedChanged: LODManager.setAutomaticLODAdjust(!adjustCheckbox.checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,10 +93,10 @@ Rectangle {
|
|||
anchors.right: parent.right
|
||||
minimumValue: 5
|
||||
maximumValue: 2000
|
||||
value: LODManager.getOctreeSizeScale() / treeScale
|
||||
value: defaultMaxVisibilityDistance
|
||||
tickmarksEnabled: false
|
||||
onValueChanged: {
|
||||
LODManager.setOctreeSizeScale(value * treeScale);
|
||||
LODManager.lodAngleDeg = visibilityDistanceToLODAngleDeg(slider.value);
|
||||
whatYouCanSeeLabel.text = LODManager.getLODFeedbackText()
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +110,7 @@ Rectangle {
|
|||
colorScheme: root.colorScheme
|
||||
height: 30
|
||||
onClicked: {
|
||||
slider.value = defaultOctreeSizeScale/treeScale
|
||||
slider.value = defaultMaxVisibilityDistance
|
||||
adjustCheckbox.checked = false
|
||||
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
|
||||
// based on how many are being consumed by the application and the display plugin. However,
|
||||
// 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 JPG_EXTENSION = ".jpg";
|
||||
|
@ -4418,8 +4418,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
} else if (isMeta) {
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
dialogsManager->toggleAddressBar();
|
||||
} else if (isShifted) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::LodTools);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -6817,8 +6815,8 @@ void Application::updateRenderArgs(float deltaTime) {
|
|||
_viewFrustum.setProjection(adjustedProjection);
|
||||
_viewFrustum.calculate();
|
||||
}
|
||||
appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getVisibilityDistance(),
|
||||
lodManager->getBoundaryLevelAdjust(), lodManager->getLODHalfAngleTan(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::MONO, RenderArgs::DEFERRED, RenderArgs::RENDER_DEBUG_NONE);
|
||||
appRenderArgs._renderArgs._scene = getMain3DScene();
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "LODManager.h"
|
||||
|
||||
#include <SettingHandle.h>
|
||||
#include <OctreeUtils.h>
|
||||
#include <Util.h>
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
|
||||
|
@ -93,8 +92,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Previous values for output
|
||||
float oldOctreeSizeScale = getOctreeSizeScale();
|
||||
// Previous value for output
|
||||
float oldLODAngle = getLODAngleDeg();
|
||||
|
||||
// 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
|
||||
setLODAngleDeg(oldLODAngle + output);
|
||||
|
||||
if (oldOctreeSizeScale != _octreeSizeScale) {
|
||||
if (oldLODAngle != getLODAngleDeg()) {
|
||||
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog();
|
||||
if (lodToolsDialog) {
|
||||
lodToolsDialog->reloadSliders();
|
||||
|
@ -173,21 +171,32 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
|||
}
|
||||
}
|
||||
|
||||
float LODManager::getLODAngleHalfTan() const {
|
||||
return getPerspectiveAccuracyAngleTan(_octreeSizeScale, _boundaryLevelAdjust);
|
||||
float LODManager::getLODHalfAngleTan() const {
|
||||
return tan(_lodHalfAngle);
|
||||
}
|
||||
float LODManager::getLODAngle() const {
|
||||
return 2.0f * atanf(getLODAngleHalfTan());
|
||||
return 2.0f * _lodHalfAngle;
|
||||
}
|
||||
float LODManager::getLODAngleDeg() const {
|
||||
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) {
|
||||
auto newSolidAngle = std::max(0.5f, std::min(lodAngle, 90.f));
|
||||
auto halTan = glm::tan(glm::radians(newSolidAngle * 0.5f));
|
||||
auto octreeSizeScale = TREE_SCALE * OCTREE_TO_MESH_RATIO / halTan;
|
||||
setOctreeSizeScale(octreeSizeScale);
|
||||
auto newLODAngleDeg = std::max(0.001f, std::min(lodAngle, 90.f));
|
||||
auto newLODHalfAngle = glm::radians(newLODAngleDeg * 0.5f);
|
||||
_lodHalfAngle = newLODHalfAngle;
|
||||
}
|
||||
|
||||
void LODManager::setSmoothScale(float t) {
|
||||
|
@ -267,7 +276,11 @@ bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) {
|
|||
};
|
||||
|
||||
void LODManager::setOctreeSizeScale(float sizeScale) {
|
||||
_octreeSizeScale = sizeScale;
|
||||
setVisibilityDistance(sizeScale / TREE_SCALE);
|
||||
}
|
||||
|
||||
float LODManager::getOctreeSizeScale() const {
|
||||
return getVisibilityDistance() * TREE_SCALE;
|
||||
}
|
||||
|
||||
void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
|
||||
|
@ -293,12 +306,14 @@ QString LODManager::getLODFeedbackText() {
|
|||
} break;
|
||||
}
|
||||
// distance feedback
|
||||
float octreeSizeScale = getOctreeSizeScale();
|
||||
float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
|
||||
float visibilityDistance = getVisibilityDistance();
|
||||
float relativeToDefault = visibilityDistance / DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
||||
int relativeToTwentyTwenty = 20 / relativeToDefault;
|
||||
|
||||
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);
|
||||
} else if (relativeToDefault > 0.99f) {
|
||||
result = QString("20:20 or the default distance for average vision%1").arg(granularityFeedback);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <OctreeConstants.h>
|
||||
#include <OctreeUtils.h>
|
||||
#include <PIDController.h>
|
||||
#include <SimpleMovingAverage.h>
|
||||
#include <render/Args.h>
|
||||
|
@ -138,24 +139,28 @@ public:
|
|||
/**jsdoc
|
||||
* @function LODManager.setOctreeSizeScale
|
||||
* @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);
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getOctreeSizeScale
|
||||
* @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
|
||||
* @function LODManager.setBoundaryLevelAdjust
|
||||
* @param {number} boundaryLevelAdjust
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getBoundaryLevelAdjust
|
||||
* @returns {number}
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||
|
||||
|
@ -196,8 +201,10 @@ public:
|
|||
|
||||
float getLODAngleDeg() const;
|
||||
void setLODAngleDeg(float lodAngle);
|
||||
float getLODAngleHalfTan() const;
|
||||
float getLODHalfAngleTan() const;
|
||||
float getLODAngle() const;
|
||||
float getVisibilityDistance() const;
|
||||
void setVisibilityDistance(float distance);
|
||||
|
||||
float getPidKp() const;
|
||||
float getPidKi() const;
|
||||
|
@ -254,7 +261,7 @@ private:
|
|||
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 _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE;
|
||||
float _lodHalfAngle = getHalfAngleFromVisibilityDistance(DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT);
|
||||
int _boundaryLevelAdjust = 0;
|
||||
|
||||
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.enableSkybox(true);
|
||||
batch.enableStereo(isStereo);
|
||||
batch.clearDepthStencilFramebuffer(1.0, 0);
|
||||
batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() });
|
||||
_splashScreen->render(batch, viewFrustum, renderArgs._renderMethod == RenderArgs::RenderMethod::FORWARD);
|
||||
});
|
||||
|
|
|
@ -64,7 +64,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
|||
_lodSize->setTickPosition(QSlider::TicksBelow);
|
||||
_lodSize->setFixedWidth(SLIDER_WIDTH);
|
||||
_lodSize->setPageStep(PAGE_STEP_LOD_SIZE);
|
||||
int sliderValue = lodManager->getOctreeSizeScale() / TREE_SCALE;
|
||||
int sliderValue = lodManager->getVisibilityDistance();
|
||||
_lodSize->setValue(sliderValue);
|
||||
form->addRow("Level of Detail:", _lodSize);
|
||||
connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int)));
|
||||
|
@ -81,7 +81,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
|||
|
||||
void LodToolsDialog::reloadSliders() {
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
_lodSize->setValue(lodManager->getOctreeSizeScale() / TREE_SCALE);
|
||||
_lodSize->setValue(lodManager->getVisibilityDistance());
|
||||
_feedback->setText(lodManager->getLODFeedbackText());
|
||||
}
|
||||
|
||||
|
@ -93,15 +93,14 @@ void LodToolsDialog::updateAutomaticLODAdjust() {
|
|||
|
||||
void LodToolsDialog::sizeScaleValueChanged(int value) {
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
float realValue = value * TREE_SCALE;
|
||||
lodManager->setOctreeSizeScale(realValue);
|
||||
lodManager->setVisibilityDistance(value);
|
||||
|
||||
_feedback->setText(lodManager->getLODFeedbackText());
|
||||
}
|
||||
|
||||
void LodToolsDialog::resetClicked(bool checked) {
|
||||
|
||||
int sliderValue = DEFAULT_OCTREE_SIZE_SCALE / TREE_SCALE;
|
||||
int sliderValue = DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
||||
_lodSize->setValue(sliderValue);
|
||||
_manualLODAdjust->setChecked(false);
|
||||
|
||||
|
@ -124,8 +123,8 @@ void LodToolsDialog::closeEvent(QCloseEvent* event) {
|
|||
lodManager->setAutomaticLODAdjust(true);
|
||||
|
||||
// if the user adjusted the LOD above "normal" then always revert back to default
|
||||
if (lodManager->getOctreeSizeScale() > DEFAULT_OCTREE_SIZE_SCALE) {
|
||||
lodManager->setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE);
|
||||
if (lodManager->getVisibilityDistance() > DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) {
|
||||
lodManager->setVisibilityDistance(DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ set(src_files
|
|||
src/LaunchInterface.h
|
||||
src/CustomUI.h
|
||||
src/CustomUI.m
|
||||
src/NSTask+NSTaskExecveAdditions.h
|
||||
src/NSTask+NSTaskExecveAdditions.m
|
||||
src/main.mm
|
||||
nib/Window.xib
|
||||
nib/SplashScreen.xib
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#import "ProcessScreen.h"
|
||||
#import "ErrorViewController.h"
|
||||
#import "Settings.h"
|
||||
#import "NSTask+NSTaskExecveAdditions.h"
|
||||
|
||||
@interface Launcher ()
|
||||
|
||||
|
@ -456,8 +457,6 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
|
||||
NSURL *url = [NSURL fileURLWithPath:[workspace fullPathForApplication:[[self getAppPath] stringByAppendingString:@"interface.app/Contents/MacOS/interface"]]];
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
NSString* contentPath = [[self getDownloadPathForContentAndScripts] stringByAppendingString:@"content"];
|
||||
NSString* displayName = [ self displayName];
|
||||
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-launcher", nil];
|
||||
}
|
||||
[workspace launchApplicationAtURL:url options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:&error];
|
||||
|
||||
[NSTimer scheduledTimerWithTimeInterval: 3.0
|
||||
target: self
|
||||
selector: @selector(exitLauncher:)
|
||||
userInfo:nil
|
||||
repeats: NO];
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
task.launchPath = [url path];
|
||||
task.arguments = arguments;
|
||||
[task replaceThisProcess];
|
||||
}
|
||||
|
||||
- (ProcessState) currentProccessState
|
||||
|
@ -500,15 +497,20 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
|
||||
- (void) callLaunchInterface:(NSTimer*) timer
|
||||
{
|
||||
NSWindow* mainWindow = [[[NSApplication sharedApplication] windows] objectAtIndex:0];
|
||||
|
||||
ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil];
|
||||
[[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen];
|
||||
[self launchInterface];
|
||||
}
|
||||
|
||||
|
||||
- (void) exitLauncher:(NSTimer*) timer
|
||||
{
|
||||
[NSApp terminate:self];
|
||||
[mainWindow setContentViewController: processScreen];
|
||||
@try
|
||||
{
|
||||
[self launchInterface];
|
||||
}
|
||||
@catch (NSException *exception)
|
||||
{
|
||||
NSLog(@"Caught exception: Name: %@, Reason: %@", exception.name, exception.reason);
|
||||
ErrorViewController* errorViewController = [[ErrorViewController alloc] initWithNibName:@"ErrorScreen" bundle:nil];
|
||||
[mainWindow setContentViewController: errorViewController];
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
// compute absolute poses that correspond to relative target poses
|
||||
AnimPoseVec absolutePoses;
|
||||
|
@ -227,6 +233,8 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
|||
accumulator.clearAndClean();
|
||||
}
|
||||
|
||||
std::map<int, int> targetToChainMap;
|
||||
|
||||
float maxError = 0.0f;
|
||||
int numLoops = 0;
|
||||
const int MAX_IK_LOOPS = 16;
|
||||
|
@ -248,17 +256,13 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// on last iteration, interpolate jointChains, if necessary
|
||||
if (numLoops == MAX_IK_LOOPS) {
|
||||
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) {
|
||||
|
||||
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);
|
||||
|
||||
float alpha = getInterpolationAlpha(_prevJointChainInfoVec[i].timer);
|
||||
size_t chainSize = std::min(_prevJointChainInfoVec[i].jointInfoVec.size(), jointChainInfoVec[i].jointInfoVec.size());
|
||||
|
||||
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) {
|
||||
int tipIndex = target.getIndex();
|
||||
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.
|
||||
if (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() && target.getType() == IKTarget::Type::RotationOnly) {
|
||||
const glm::quat& targetRotation = target.getRotation();
|
||||
// compute tip's new parent-relative rotation
|
||||
// Q = Qp * q --> q' = Qp^ * Q
|
||||
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot()) * targetRotation;
|
||||
RotationConstraint* constraint = getConstraint(tipIndex);
|
||||
if (constraint) {
|
||||
constraint->apply(newRelativeRotation);
|
||||
// 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 (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() &&
|
||||
(target.getType() == IKTarget::Type::RotationOnly || target.getType() == IKTarget::Type::Unknown)) {
|
||||
if (target.getType() == IKTarget::Type::RotationOnly) {
|
||||
const glm::quat& targetRotation = target.getRotation();
|
||||
// compute tip's new parent-relative rotation
|
||||
// Q = Qp * q --> q' = Qp^ * Q
|
||||
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot()) * targetRotation;
|
||||
RotationConstraint* constraint = getConstraint(tipIndex);
|
||||
if (constraint) {
|
||||
constraint->apply(newRelativeRotation);
|
||||
// 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.getPoleVectorEnabled() != _prevJointChainInfoVec[i].target.getPoleVectorEnabled())) {
|
||||
_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 initConstraints();
|
||||
void initLimitCenterPoses();
|
||||
float getInterpolationAlpha(float timer);
|
||||
|
||||
// no copies
|
||||
AnimInverseKinematics(const AnimInverseKinematics&) = delete;
|
||||
|
@ -181,6 +182,7 @@ protected:
|
|||
AnimPoseVec _defaultRelativePoses; // poses of the relaxed state
|
||||
AnimPoseVec _relativePoses; // current relative poses
|
||||
AnimPoseVec _limitCenterPoses; // relative
|
||||
std::map<int, glm::quat> _rotationOnlyIKRotations;
|
||||
|
||||
std::map<int, AnimPose> _secondaryTargetsInRigFrame;
|
||||
|
||||
|
|
|
@ -57,14 +57,12 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
|||
lowerBound = upperBound;
|
||||
}
|
||||
if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1) {
|
||||
_duringInterp = false;
|
||||
switchRandomState(animVars, context, desiredState, _duringInterp);
|
||||
switchRandomState(animVars, context, desiredState, false);
|
||||
} else {
|
||||
// firing a random switch, be sure that we aren't completing a previously triggered transition
|
||||
if (currentStateHasPriority) {
|
||||
if (desiredState->getID() != _currentState->getID()) {
|
||||
_duringInterp = true;
|
||||
switchRandomState(animVars, context, desiredState, _duringInterp);
|
||||
switchRandomState(animVars, context, desiredState, true);
|
||||
} else {
|
||||
_duringInterp = false;
|
||||
}
|
||||
|
@ -79,8 +77,7 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
|||
// evaluate currentState transitions
|
||||
auto transitionState = evaluateTransitions(animVars);
|
||||
if (transitionState != _currentState) {
|
||||
_duringInterp = true;
|
||||
switchRandomState(animVars, context, transitionState, _duringInterp);
|
||||
switchRandomState(animVars, context, transitionState, true);
|
||||
_triggerTime = randFloatInRange(_triggerTimeMin, _triggerTimeMax);
|
||||
_randomSwitchTime = randFloatInRange(_randomSwitchTimeMin, _randomSwitchTimeMax);
|
||||
}
|
||||
|
@ -172,6 +169,9 @@ void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const A
|
|||
_lastPlayedState = nextStateNode->getID();
|
||||
if (shouldInterp) {
|
||||
|
||||
bool interpActive = _duringInterp;
|
||||
_duringInterp = true;
|
||||
|
||||
const float FRAMES_PER_SECOND = 30.0f;
|
||||
|
||||
auto prevStateNode = _children[_currentState->getChildIndex()];
|
||||
|
@ -195,13 +195,21 @@ void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const A
|
|||
}
|
||||
_nextPoses = nextStateNode->evaluate(animVars, context, dt, triggers);
|
||||
} else if (_interpType == InterpType::SnapshotPrev) {
|
||||
// snapshot previoius pose
|
||||
// snapshot previous pose
|
||||
_prevPoses = _poses;
|
||||
// no need to evaluate _nextPoses we will do it dynamically during the interp,
|
||||
// however we need to set the current frame.
|
||||
if (!desiredState->getResume()) {
|
||||
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 {
|
||||
assert(false);
|
||||
}
|
||||
|
|
|
@ -128,6 +128,7 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon
|
|||
auto prevStateNode = _children[_currentState->getChildIndex()];
|
||||
auto nextStateNode = _children[desiredState->getChildIndex()];
|
||||
|
||||
bool interpActive = _duringInterp;
|
||||
_duringInterp = true;
|
||||
_alpha = 0.0f;
|
||||
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);
|
||||
_nextPoses = nextStateNode->evaluate(animVars, context, dt, triggers);
|
||||
} else if (_interpType == InterpType::SnapshotPrev) {
|
||||
// snapshot previoius pose
|
||||
// snapshot previous pose
|
||||
_prevPoses = _poses;
|
||||
// no need to evaluate _nextPoses we will do it dynamically during the interp,
|
||||
// however we need to set the current frame.
|
||||
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 {
|
||||
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;
|
||||
_animVars.set("talkOverlayAlpha", easeOutInValue);
|
||||
_animVars.set("idleOverlayAlpha", easeOutInValue); // backward compatibility for older anim graphs.
|
||||
} else {
|
||||
_animVars.set("talkOverlayAlpha", 1.0f);
|
||||
_animVars.set("idleOverlayAlpha", 1.0f); // backward compatibility for older anim graphs.
|
||||
}
|
||||
} else {
|
||||
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 talkAlpha = 1.0f - easeOutInValue;
|
||||
_animVars.set("talkOverlayAlpha", talkAlpha);
|
||||
_animVars.set("idleOverlayAlpha", talkAlpha); // backward compatibility for older anim graphs.
|
||||
} else {
|
||||
_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; }
|
||||
bool isVsyncEnabled() const { return _vsyncEnabled; }
|
||||
// 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;
|
||||
void copyTextureToQuickFramebuffer(NetworkTexturePointer source,
|
||||
|
|
|
@ -53,6 +53,8 @@ public:
|
|||
void updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
|
||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||
float visionSqueezeSpotlightSize);
|
||||
// Attempt to reserve two threads.
|
||||
int getRequiredThreadCount() const override { return 2; }
|
||||
|
||||
signals:
|
||||
void hmdMountedChanged();
|
||||
|
|
|
@ -33,8 +33,8 @@ using namespace gpu::gl;
|
|||
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
|
||||
#endif
|
||||
|
||||
bool GLTexelFormat::isCompressed() const {
|
||||
switch (internalFormat) {
|
||||
bool GLTexelFormat::isCompressed(GLenum format) {
|
||||
switch (format) {
|
||||
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_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 result = GL_RGBA8;
|
||||
switch (dstFormat.getDimension()) {
|
||||
|
|
|
@ -14,13 +14,15 @@ namespace gpu { namespace gl {
|
|||
|
||||
class GLTexelFormat {
|
||||
public:
|
||||
GLenum internalFormat;
|
||||
GLenum format;
|
||||
GLenum type;
|
||||
GLenum internalFormat{ GL_RGBA8 };
|
||||
GLenum format{ GL_RGBA };
|
||||
GLenum type{ GL_UNSIGNED_BYTE };
|
||||
|
||||
GLTexelFormat(GLenum glinternalFormat, GLenum glformat, GLenum gltype) : internalFormat(glinternalFormat), format(glformat), type(gltype) {}
|
||||
GLTexelFormat(GLenum glinternalFormat) : internalFormat(glinternalFormat) {}
|
||||
|
||||
static bool isCompressed(GLenum glinternalFormat);
|
||||
|
||||
bool isCompressed() const;
|
||||
|
||||
static GLTexelFormat evalGLTexelFormat(const Element& dstFormat) {
|
||||
|
|
|
@ -33,6 +33,7 @@ class GL45Backend : public GLBackend {
|
|||
friend class Context;
|
||||
|
||||
public:
|
||||
static const GLint RESOURCE_TRANSFER_TEX_UNIT { 32 };
|
||||
static GLint MAX_COMBINED_SHADER_STORAGE_BLOCKS;
|
||||
static GLint MAX_UNIFORM_LOCATIONS;
|
||||
#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 amountCopied = sourceSize;
|
||||
bool compressed = GLTexelFormat::isCompressed(internalFormat);
|
||||
if (GL_TEXTURE_2D == _target) {
|
||||
switch (internalFormat) {
|
||||
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||
case GL_COMPRESSED_RED_RGTC1:
|
||||
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;
|
||||
if (compressed) {
|
||||
glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat,
|
||||
static_cast<GLsizei>(sourceSize), sourcePointer);
|
||||
} else {
|
||||
glTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer);
|
||||
}
|
||||
} else if (GL_TEXTURE_CUBE_MAP == _target) {
|
||||
switch (internalFormat) {
|
||||
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||
case GL_COMPRESSED_RED_RGTC1:
|
||||
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:
|
||||
#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;
|
||||
// DSA and cubemap functions are notoriously buggy. use the 4.1 compatible pathway
|
||||
glActiveTexture(GL_TEXTURE0 + GL45Backend::RESOURCE_TRANSFER_TEX_UNIT);
|
||||
glBindTexture(_target, _texture);
|
||||
auto target = GLTexture::CUBE_FACE_LAYOUT[face];
|
||||
if (compressed) {
|
||||
glCompressedTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, internalFormat,
|
||||
static_cast<GLsizei>(sourceSize), sourcePointer);
|
||||
} else {
|
||||
glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer);
|
||||
}
|
||||
glBindTexture(_target, 0);
|
||||
} else {
|
||||
assert(false);
|
||||
amountCopied = 0;
|
||||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
|
||||
return amountCopied;
|
||||
}
|
||||
|
||||
|
|
|
@ -334,12 +334,17 @@ void Socket::checkForReadyReadBackup() {
|
|||
qCDebug(networking) << "Socket::checkForReadyReadyBackup() last sequence number"
|
||||
<< (uint32_t) _lastReceivedSequenceNumber << "from" << _lastPacketSockAddr << "-"
|
||||
<< _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
|
||||
int droppedCount = 0;
|
||||
while (_udpSocket.hasPendingDatagrams()) {
|
||||
_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;
|
||||
|
||||
// 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_OCTREE_SIZE_SCALE = TREE_SCALE * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
||||
const float DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT = 400.0f; // max distance where a 1x1x1 cube is visible for 20:20 vision
|
||||
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,
|
||||
// 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 <AACube.h>
|
||||
|
||||
float calculateRenderAccuracy(const glm::vec3& position,
|
||||
const AABox& bounds,
|
||||
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 visibilityDistance) {
|
||||
return visibilityDistance / powf(2.0f, renderLevel);
|
||||
}
|
||||
|
||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
|
||||
return voxelSizeScale / powf(2.0f, renderLevel);
|
||||
float getPerspectiveAccuracyHalfAngleTan(float visibilityDistance, int boundaryLevelAdjust) {
|
||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, visibilityDistance);
|
||||
return UNIT_ELEMENT_MAX_EXTENT / visibleDistanceAtMaxScale;
|
||||
}
|
||||
|
||||
float getPerspectiveAccuracyAngleTan(float octreeSizeScale, int boundaryLevelAdjust) {
|
||||
const float maxScale = (float)TREE_SCALE;
|
||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
|
||||
return (maxScale / visibleDistanceAtMaxScale);
|
||||
float getPerspectiveAccuracyHalfAngle(float visibilityDistance, int boundaryLevelAdjust) {
|
||||
return atan(getPerspectiveAccuracyHalfAngleTan(visibilityDistance, boundaryLevelAdjust));
|
||||
}
|
||||
|
||||
float getPerspectiveAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) {
|
||||
return atan(getPerspectiveAccuracyAngleTan(octreeSizeScale, boundaryLevelAdjust));
|
||||
float getVisibilityDistanceFromHalfAngle(float halfAngle) {
|
||||
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
|
||||
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 QJsonDocument;
|
||||
|
||||
/// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple
|
||||
/// 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 visibilityDistance);
|
||||
|
||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
|
||||
|
||||
float getPerspectiveAccuracyAngleTan(float octreeSizeScale, int boundaryLevelAdjust);
|
||||
float getPerspectiveAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust);
|
||||
float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust);
|
||||
float getPerspectiveAccuracyHalfAngleTan(float visibilityDistance, int boundaryLevelAdjust);
|
||||
float getPerspectiveAccuracyHalfAngle(float visibilityDistance, int boundaryLevelAdjust);
|
||||
float getVisibilityDistanceFromHalfAngle(float halfAngle);
|
||||
float getHalfAngleFromVisibilityDistance(float visibilityDistance);
|
||||
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
|
||||
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
|
||||
{
|
||||
float angle = glm::degrees(getPerspectiveAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
|
||||
float angle = glm::degrees(getPerspectiveAccuracyHalfAngle(args->_sizeScale, args->_boundaryLevelAdjust));
|
||||
Transform crosshairModel;
|
||||
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
|
||||
|
|
|
@ -30,34 +30,18 @@ Q_DECLARE_METATYPE(QByteArray*)
|
|||
|
||||
XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) :
|
||||
_engine(engine),
|
||||
_async(true),
|
||||
_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) {
|
||||
_timer(this) {
|
||||
|
||||
_request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
_timer.setSingleShot(true);
|
||||
}
|
||||
|
||||
XMLHttpRequestClass::~XMLHttpRequestClass() {
|
||||
if (_reply) { delete _reply; }
|
||||
if (_sendData) { delete _sendData; }
|
||||
if (_reply) { _reply->deleteLater(); }
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -169,13 +153,12 @@ void XMLHttpRequestClass::send() {
|
|||
|
||||
void XMLHttpRequestClass::send(const QScriptValue& data) {
|
||||
if (_readyState == OPENED && !_reply) {
|
||||
|
||||
if (!data.isNull()) {
|
||||
_sendData = new QBuffer(this);
|
||||
if (data.isObject()) {
|
||||
QByteArray ba = qscriptvalue_cast<QByteArray>(data);
|
||||
_sendData->setData(ba);
|
||||
_sendData = qscriptvalue_cast<QByteArray>(data);
|
||||
} else {
|
||||
_sendData->setData(data.toString().toUtf8());
|
||||
_sendData = data.toString().toUtf8();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,6 +220,10 @@ void XMLHttpRequestClass::requestFinished() {
|
|||
|
||||
setReadyState(DONE);
|
||||
emit requestComplete();
|
||||
|
||||
disconnectFromReply(_reply);
|
||||
_reply->deleteLater();
|
||||
_reply = nullptr;
|
||||
}
|
||||
|
||||
void XMLHttpRequestClass::abortRequest() {
|
||||
|
@ -246,7 +233,7 @@ void XMLHttpRequestClass::abortRequest() {
|
|||
disconnectFromReply(_reply);
|
||||
_reply->abort();
|
||||
_reply->deleteLater();
|
||||
_reply = NULL;
|
||||
_reply = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,23 +98,23 @@ private:
|
|||
void disconnectFromReply(QNetworkReply* reply);
|
||||
void abortRequest();
|
||||
|
||||
QScriptEngine* _engine;
|
||||
bool _async;
|
||||
QScriptEngine* _engine { nullptr };
|
||||
bool _async { true };
|
||||
QUrl _url;
|
||||
QString _method;
|
||||
QString _responseType;
|
||||
QNetworkRequest _request;
|
||||
QNetworkReply* _reply;
|
||||
QBuffer* _sendData;
|
||||
QNetworkReply* _reply { nullptr };
|
||||
QByteArray _sendData;
|
||||
QByteArray _rawResponseData;
|
||||
QScriptValue _responseData;
|
||||
QScriptValue _onTimeout;
|
||||
QScriptValue _onReadyStateChange;
|
||||
ReadyState _readyState;
|
||||
QNetworkReply::NetworkError _errorCode;
|
||||
int _timeout;
|
||||
QScriptValue _onTimeout { QScriptValue::NullValue };
|
||||
QScriptValue _onReadyStateChange { QScriptValue::NullValue };
|
||||
ReadyState _readyState { XMLHttpRequestClass::UNSENT };
|
||||
QNetworkReply::NetworkError _errorCode { QNetworkReply::NoError };
|
||||
int _timeout { 0 };
|
||||
QTimer _timer;
|
||||
int _numRedirects;
|
||||
int _numRedirects { 0 };
|
||||
|
||||
private slots:
|
||||
void requestFinished();
|
||||
|
|
|
@ -39,6 +39,10 @@ Q_LOGGING_CATEGORY(trace_baker, "trace.baker")
|
|||
#endif
|
||||
|
||||
static bool tracingEnabled() {
|
||||
if (!DependencyManager::isSet<tracing::Tracer>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cheers, love! The cavalry's here!
|
||||
auto tracer = DependencyManager::get<tracing::Tracer>();
|
||||
return (tracer && tracer->isEnabled());
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#ifdef WIN32
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
|
||||
// Enable event queue debugging
|
||||
#define DEBUG_EVENT_QUEUE
|
||||
#endif // WIN32
|
||||
#endif
|
||||
|
||||
namespace hifi { namespace qt {
|
||||
void addBlockingForbiddenThread(const QString& name, QThread* thread = nullptr);
|
||||
|
|
|
@ -80,7 +80,7 @@ Item {
|
|||
valueVar: LODManager["lodAngleDeg"]
|
||||
valueVarSetter: (function (v) { LODManager["lodAngleDeg"] = v })
|
||||
max: 90.0
|
||||
min: 0.5
|
||||
min: 0.01
|
||||
integral: false
|
||||
|
||||
anchors.left: parent.left
|
||||
|
@ -239,6 +239,7 @@ Item {
|
|||
object: LODManager
|
||||
valueScale: 1.0
|
||||
valueUnit: "deg"
|
||||
valueNumDigits: 2
|
||||
plots: [
|
||||
{
|
||||
prop: "lodAngleDeg",
|
||||
|
|
|
@ -39,6 +39,10 @@ module.exports = {
|
|||
if (error) {
|
||||
response = { statusCode: httpRequest.status };
|
||||
}
|
||||
|
||||
// Break circular reference to httpRequest so the engine can garbage collect it.
|
||||
httpRequest.onreadystatechange = null;
|
||||
|
||||
callback(error, response, optionalCallbackParameter);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -476,7 +476,7 @@ function maybeUpdateOutputDeviceMutedOverlay() {
|
|||
var oldAutomaticLODAdjust;
|
||||
var oldLODAngleDeg;
|
||||
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() {
|
||||
oldAutomaticLODAdjust = LODManager.automaticLODAdjust;
|
||||
oldLODAngleDeg = LODManager.lodAngleDeg;
|
||||
|
|
|
@ -355,7 +355,7 @@ CameraManager = function() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (event.isRightButton || (event.isLeftButton && event.isControl && !event.isShifted)) {
|
||||
if (event.isRightButton || (event.isLeftButton && event.isAlt && !event.isShifted)) {
|
||||
that.mode = MODE_ORBIT;
|
||||
} else if (event.isMiddleButton || (event.isLeftButton && event.isControl && event.isShifted)) {
|
||||
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
|
||||
qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
|
||||
|
||||
setup_memory_debugger()
|
||||
|
||||
# add them to the nitpick source files
|
||||
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_DISABLE_TEXTURE_COMPRESSION_PARAMETER = "disable-texture-compression";
|
||||
|
||||
QUrl OvenCLIApplication::_inputUrlParameter;
|
||||
QUrl OvenCLIApplication::_outputUrlParameter;
|
||||
QString OvenCLIApplication::_typeParameter;
|
||||
|
||||
OvenCLIApplication::OvenCLIApplication(int argc, char* 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
|
||||
QCommandLineParser parser;
|
||||
|
||||
parser.setApplicationDescription("High Fidelity Oven");
|
||||
parser.addOptions({
|
||||
{ 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" },
|
||||
|
@ -37,25 +48,45 @@ OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
|||
{ CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER, "Disable texture compression." }
|
||||
});
|
||||
|
||||
parser.addHelpOption();
|
||||
parser.process(*this);
|
||||
auto versionOption = parser.addVersionOption();
|
||||
auto helpOption = parser.addHelpOption();
|
||||
|
||||
if (parser.isSet(CLI_INPUT_PARAMETER) && parser.isSet(CLI_OUTPUT_PARAMETER)) {
|
||||
BakerCLI* cli = new BakerCLI(this);
|
||||
QUrl inputUrl(QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER)));
|
||||
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();
|
||||
QStringList arguments;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
arguments << argv[i];
|
||||
}
|
||||
|
||||
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:
|
||||
OvenCLIApplication(int argc, char* argv[]);
|
||||
|
||||
static void parseCommandLine(int argc, char* argv[]);
|
||||
|
||||
static OvenCLIApplication* instance() { return dynamic_cast<OvenCLIApplication*>(QCoreApplication::instance()); }
|
||||
|
||||
private:
|
||||
static QUrl _inputUrlParameter;
|
||||
static QUrl _outputUrlParameter;
|
||||
static QString _typeParameter;
|
||||
};
|
||||
|
||||
#endif // hifi_OvenCLIApplication_h
|
||||
|
|
|
@ -18,14 +18,19 @@
|
|||
int main (int argc, char** argv) {
|
||||
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
|
||||
if (argc > 1) {
|
||||
OvenCLIApplication::parseCommandLine(argc, argv);
|
||||
|
||||
// init the settings interface so we can save and load settings
|
||||
Setting::init();
|
||||
|
||||
OvenCLIApplication app { argc, argv };
|
||||
return app.exec();
|
||||
} else {
|
||||
// init the settings interface so we can save and load settings
|
||||
Setting::init();
|
||||
|
||||
OvenGUIApplication app { argc, argv };
|
||||
return app.exec();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue