mirror of
https://github.com/overte-org/overte.git
synced 2025-04-07 12:53:44 +02:00
Merge pull request #1058 from ctrlaltdavid/feature/qt-update-master
Update Qt 5.15.2 feature branch to 2021.1.0 master
This commit is contained in:
commit
d7f7acec34
269 changed files with 7244 additions and 3521 deletions
6
.github/workflows/master_build.yml
vendored
6
.github/workflows/master_build.yml
vendored
|
@ -83,15 +83,15 @@ jobs:
|
|||
shell: bash
|
||||
run: |
|
||||
echo "${{ steps.buildenv1.outputs.symbols_archive }}"
|
||||
echo "ARTIFACT_PATTERN=Vircadia-Alpha-*.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
echo "ARTIFACT_PATTERN=Vircadia-*.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
# Build type variables
|
||||
echo "GIT_COMMIT_SHORT=${{ steps.buildenv1.outputs.github_sha_short }}" >> $GITHUB_ENV
|
||||
if [ "${{ matrix.build_type }}" = "full" ]; then
|
||||
echo "CLIENT_ONLY=FALSE" >> $GITHUB_ENV
|
||||
echo "INSTALLER=Vircadia-Alpha-$BUILD_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
echo "INSTALLER=Vircadia-$BUILD_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
else
|
||||
echo "CLIENT_ONLY=TRUE" >> $GITHUB_ENV
|
||||
echo "INSTALLER=Vircadia-Alpha-Interface-$BUILD_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
echo "INSTALLER=Vircadia-Interface-$BUILD_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Clear working directory
|
||||
if: startsWith(matrix.os, 'windows')
|
||||
|
|
4
.github/workflows/pr_build.yml
vendored
4
.github/workflows/pr_build.yml
vendored
|
@ -86,9 +86,9 @@ jobs:
|
|||
echo "${{ steps.buildenv1.outputs.symbols_archive }}"
|
||||
echo "GIT_COMMIT_SHORT=${{ steps.buildenv1.outputs.github_sha_short }}" >> $GITHUB_ENV
|
||||
if [[ "${{ matrix.build_type }}" != "android" ]]; then
|
||||
echo "ARTIFACT_PATTERN=Vircadia-Alpha-PR${{ github.event.number }}-*.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
echo "ARTIFACT_PATTERN=Vircadia-PR${{ github.event.number }}-*.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
# Build type variables
|
||||
echo "INSTALLER=Vircadia-Alpha-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
echo "INSTALLER=Vircadia-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
else
|
||||
echo "ARTIFACT_PATTERN=*.$INSTALLER_EXT" >> $GITHUB_ENV
|
||||
fi
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -111,3 +111,4 @@ tools/unity-avatar-exporter
|
|||
server-console/package-lock.json
|
||||
vcpkg/
|
||||
/tools/nitpick/compiledResources
|
||||
qt/
|
2
BUILD.md
2
BUILD.md
|
@ -85,7 +85,7 @@ Windows:
|
|||
|
||||
set HIFI_VCPKG_BASE=/path/to/directory
|
||||
|
||||
Where /path/to/directory is the path to a directory where you wish the build files to get stored.
|
||||
Where `/path/to/directory` is the path to a directory where you wish the build files to get stored.
|
||||
|
||||
#### Generating Build Files
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Build Android
|
||||
|
||||
*Last Updated on December 21, 2019*
|
||||
*Last Updated on December 15, 2020*
|
||||
|
||||
Please read the [general build guide](BUILD.md) for information on building other platforms. Only Android specific instructions are found in this file. **Note that these instructions apply to building for Oculus Quest.**
|
||||
Please read the [general build guide](BUILD.md) for information on building other platforms. Only Android specific instructions are found in this file. **Note that these instructions apply to building for the Oculus Quest 1.**
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
@ -14,7 +14,7 @@ Please install the dependencies for your OS using the [Windows](BUILD_WIN.md), [
|
|||
|
||||
### Android Studio
|
||||
|
||||
Download the [Android Studio](https://developer.android.com/studio/index.html) installer and run it. Once installed, at the welcome screen, click _Configure_ in the lower right corner and select _SDK Manager_.
|
||||
Download the [Android Studio](https://developer.android.com/studio/index.html) installer and run it. Once installed, click _File_ then _Settings_, expand _Appearance & Behavior_ then expand _System Settings_ and select _Android SDK_.
|
||||
|
||||
From the _SDK Platforms_ tab, select API levels 26 and 28.
|
||||
|
||||
|
@ -27,14 +27,16 @@ From the _SDK Tools_ tab, select the following
|
|||
* Android SDK Tools
|
||||
* NDK (even if you have the NDK installed separately)
|
||||
|
||||
Still in the _SDK Tools_ tab, click _Show Package Details_. Select CMake 3.6.4. Do this even if you have a separate CMake installation.
|
||||
Still in the _SDK Tools_ tab, check off _Show Package Details_ at the bottom. Select CMake 3.6.4. Do this even if you have a separate CMake installation. Also, make sure the NDK installed version is 18 (or higher).
|
||||
|
||||
Also, make sure the NDK installed version is 18 (or higher).
|
||||
Now go back to _File_ then _Project Structure_ then under _Project_ set the Android Gradle Plugin Version to `3.2.1` and Gradle Version to `4.10.1`.
|
||||
|
||||
If Android Studio pops open the "Plugin Update Recommeded" dialog, do not click update, just click X on the top right to close. Later versions of the Gradle plugin have known issues with cz.malohlava.
|
||||
|
||||
## Environment
|
||||
|
||||
### Create a keystore in Android Studio
|
||||
Follow the directions [here](https://developer.android.com/studio/publish/app-signing#generate-key) to create a keystore file. You can save it anywhere (preferably not in the `hifi` folder).
|
||||
Follow the directions [here](https://developer.android.com/studio/publish/app-signing#generate-key) to create a keystore file. You can save it anywhere (preferably not in the `vircadia` folder).
|
||||
|
||||
### Set up machine specific Gradle properties
|
||||
|
||||
|
@ -62,7 +64,11 @@ Add these lines to `gradle.properties`
|
|||
SUPPRESS_INTERFACE
|
||||
SUPPRESS_FRAME_PLAYER
|
||||
|
||||
The above code to suppress modules is not necessary, but will speed up the build process.
|
||||
|
||||
#### The Frame Player for both Android Phone and Oculus Quest is optional, so if you encounter problems with these during your build, you can skip them by adding these lines to `gradle.properties`
|
||||
|
||||
SUPPRESS_FRAME_PLAYER
|
||||
SUPPRESS_QUEST_FRAME_PLAYER
|
||||
|
||||
### Clone the repository
|
||||
|
||||
|
@ -74,12 +80,17 @@ The above code to suppress modules is not necessary, but will speed up the build
|
|||
|
||||
* Open Android Studio
|
||||
* Choose _Open an existing Android Studio project_
|
||||
* Navigate to the `hifi` repository and choose the `android` folder and select _OK_
|
||||
* Navigate to the `vircadia` repository that had you cloned and choose the `android` folder and select _OK_
|
||||
* Wait for Gradle to sync (this should take around 20 minutes the first time)
|
||||
* From the _Build_ menu select _Make Project_
|
||||
* If a dialog pops open saying "Plugin Update Recommeded" dialog, do not click update, just click X on the top right to close.
|
||||
* In the _Project_ window click on the project you wish to build (i.e. "questInterface") then click _Build_ in the top menu and choose _Make Module 'questInterface'_
|
||||
* By default this will build the "debug" apk, you can change this by opening the _Build Variants_ window along the left side and select other build types such as "release".
|
||||
* Your newly build APK should reside in `vircadia\android\apps\questInterface\release` (if you chose release).
|
||||
|
||||
### Running a Module
|
||||
|
||||
You are free to use the "adb" command line or other development tools to install (sideload on Quest) your newly built APK, or you can follow the instructions below to load the APK via Android Studio.
|
||||
|
||||
* In the toolbar at the top of Android Studio, next to the green hammer icon, you should see a dropdown menu.
|
||||
* You may already see a configuration for the module you are trying to build. If so, select it.
|
||||
* Otherwise, select _Edit Configurations_.
|
||||
|
@ -112,9 +123,17 @@ To view a more complete debug log,
|
|||
* Click the icon with the two overlapping squares in the upper left corner of the tab where the sync is running (hover text says _Toggle view_)
|
||||
* To change verbosity, click _File > Settings_. Under _Build, Execution, Deployment > Compiler_ you can add command-line flags, as per Gradle documentation
|
||||
|
||||
If you encounter CMake issues, try adding the following system environment variable:
|
||||
|
||||
With your start menu, search for 'Edit the System Environment Variables' and open it.
|
||||
* Click on 'Advanced' tab, then 'Environment Variables'
|
||||
* Select 'New' under System variables
|
||||
* Set "Variable name" to QT_CMAKE_PREFIX_PATH
|
||||
* Set "Variable value" to the directory that your android build placed the CMake 3.6.4 library CMake directory (i.e. android\qt\lib\cmake).
|
||||
|
||||
Some things you can try if you want to do a clean build
|
||||
|
||||
* Delete the `build` and `.externalNativeBuild` folders from the folder for each module you're building (for example, `hifi/android/apps/interface`)
|
||||
* Delete the `build` and `.externalNativeBuild` folders from the folder for each module you're building (for example, `vircadia/android/apps/interface`)
|
||||
* If you have set your `HIFI_VCPKG_ROOT` environment variable, delete the contents of that directory; otherwise, delete `AppData/Local/Temp/hifi`
|
||||
* In Android Studio, click _File > Invalidate Caches / Restart_ and select _Invalidate and Restart_
|
||||
|
||||
|
|
40
BUILD_WIN.md
40
BUILD_WIN.md
|
@ -1,40 +1,42 @@
|
|||
# Build Windows
|
||||
|
||||
*Last Updated on 12 Dec 2020*
|
||||
*Last Updated on 23 Feb 2021*
|
||||
|
||||
This is a stand-alone guide for creating your first Vircadia build for Windows 64-bit.
|
||||
|
||||
Note: We are now using Visual Studio 2019 and Qt 5.15.2.
|
||||
If you are upgrading from previous versions, do a clean uninstall of those versions before going through this guide.
|
||||
|
||||
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 3.x
|
||||
|
||||
If you don’t have Community or Professional edition of Visual Studio 2019, download [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/). If you have Visual Studio 2017, you need to download Visual Studio 2019.
|
||||
If you don't have Community or Professional edition of Visual Studio 2019, download [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/). If you have Visual Studio 2017, you need to download Visual Studio 2019.
|
||||
|
||||
When selecting components, check "Desktop development with C++". On the right on the Summary toolbar, select the following components.
|
||||
When selecting components, check "Desktop development with C++".
|
||||
|
||||
If you do not already have a Python 3.x development environment installed and want to install it with Visual Studio, check "Python Development". 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.
|
||||
|
||||
#### Visual Studio 2019
|
||||
|
||||
On the right on the Summary toolbar, select the following components.
|
||||
|
||||
* MSVC v142 - VS 2019 C++ X64/x86 build tools
|
||||
* 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 3.x development environment installed, also check "Python Development" in this screen.
|
||||
### Step 1a. Alternate Python
|
||||
|
||||
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.
|
||||
|
||||
### Step 1a. Alternate Python
|
||||
|
||||
If you do not wish to use the Python installation bundled with Visual Studio, you can download the installer from [here](https://www.python.org/downloads/). Ensure you get version 3.6.6 or higher.
|
||||
If you do not wish to use the Python installation bundled with Visual Studio, you can download the installer from [here](https://www.python.org/downloads/). Ensure that you get version 3.6.6 or higher.
|
||||
|
||||
### Step 2. Python Dependencies
|
||||
|
||||
In a command-line that can access Python's pip you will need to run the following command:
|
||||
In an administrator command-line that can access Python's pip you will need to run the following command:
|
||||
|
||||
`pip install distro`
|
||||
|
||||
If you do not use an administrator command-line, you will get errors.
|
||||
|
||||
### Step 3. Installing CMake
|
||||
|
||||
Download and install the latest version of CMake 3.15.
|
||||
|
@ -42,7 +44,11 @@ Download and install the latest version of CMake 3.15.
|
|||
|
||||
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 4. Create VCPKG environment variable
|
||||
### Step 4. Node.JS and NPM
|
||||
|
||||
Install version 10.15.0 LTS (or greater) of [Node.JS and NPM](<https://nodejs.org/en/download/>).
|
||||
|
||||
### Step 5. Create VCPKG environment variable
|
||||
In the next step, you will use CMake to build Vircadia. 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.
|
||||
|
||||
To create this variable:
|
||||
|
@ -61,7 +67,7 @@ To create this variable:
|
|||
* Set "Variable name" to `HIFI_VCPKG_BOOTSTRAP`
|
||||
* Set "Variable value" to `1`
|
||||
|
||||
### Step 5. Running CMake to Generate Build Files
|
||||
### Step 6. Running CMake to Generate Build Files
|
||||
|
||||
Run Command Prompt from Start and run the following commands:
|
||||
`cd "%VIRCADIA_DIR%"`
|
||||
|
@ -73,7 +79,7 @@ Run `cmake .. -G "Visual Studio 16 2019" -A x64`.
|
|||
|
||||
Where `%VIRCADIA_DIR%` is the directory for the Vircadia repository.
|
||||
|
||||
### Step 6. Making a Build
|
||||
### Step 7. Making a Build
|
||||
|
||||
Open `%VIRCADIA_DIR%\build\vircadia.sln` using Visual Studio.
|
||||
|
||||
|
@ -81,7 +87,7 @@ Change the Solution Configuration (menu ribbon under the menu bar, next to the g
|
|||
|
||||
Run from the menu bar `Build > Build Solution`.
|
||||
|
||||
### Step 7. Testing Interface
|
||||
### Step 8. Testing Interface
|
||||
|
||||
Create another environment variable (see Step #3)
|
||||
* Set "Variable name": `_NO_DEBUG_HEAP`
|
||||
|
@ -97,11 +103,11 @@ Note: You can also run Interface by launching it from command line or File Explo
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
For any problems after Step #6, first try this:
|
||||
For any problems after Step #7, first try this:
|
||||
* Delete your locally cloned copy of the Vircadia repository
|
||||
* Restart your computer
|
||||
* Redownload the [repository](https://github.com/vircadia/vircadia)
|
||||
* Restart directions from Step #6
|
||||
* Restart directions from Step #7
|
||||
|
||||
#### CMake gives you the same error message repeatedly after the build fails
|
||||
|
||||
|
|
|
@ -41,6 +41,12 @@ endif()
|
|||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" "${EXTERNAL_BUILD_ASSETS}")
|
||||
MESSAGE(STATUS "EXTERNAL_BUILD_ASSETS: ${EXTERNAL_BUILD_ASSETS}")
|
||||
|
||||
set(GLES_OPTION "$ENV{USE_GLES}")
|
||||
|
||||
# Will affect VCPKG dependencies
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_env/USE_GLES.txt" "${GLES_OPTION}")
|
||||
MESSAGE(STATUS "GLES_OPTION: ${GLES_OPTION}")
|
||||
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros/TargetPython.cmake")
|
||||
target_python()
|
||||
|
||||
|
@ -129,7 +135,6 @@ set(BUILD_TESTS_OPTION OFF)
|
|||
set(BUILD_MANUAL_TESTS_OPTION ${BUILD_TESTS_OPTION})
|
||||
set(BUILD_TOOLS_OPTION ON)
|
||||
set(BUILD_INSTALLER_OPTION ON)
|
||||
set(GLES_OPTION OFF)
|
||||
set(DISABLE_QML_OPTION OFF)
|
||||
set(DOWNLOAD_SERVERLESS_CONTENT_OPTION OFF)
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@ To produce an executable installer on Windows, the following are required:
|
|||
1. Copy `Release\ApplicationID.dll` to `C:\Program Files (x86)\NSIS\Plugins\x86-ansi\`
|
||||
1. Copy `ReleaseUnicode\ApplicationID.dll` to `C:\Program Files (x86)\NSIS\Plugins\x86-unicode\`
|
||||
|
||||
1. [Node.JS and NPM](<https://www.npmjs.com/get-npm>)
|
||||
1. Install version 10.15.0 LTS
|
||||
1. [Node.JS and NPM](<https://nodejs.org/en/download/>)
|
||||
1. Install version 10.15.0 LTS (or greater)
|
||||
|
||||
##### Code Signing (optional)
|
||||
|
2
LICENSE
2
LICENSE
|
@ -1,5 +1,5 @@
|
|||
Copyright (c) 2013-2019, High Fidelity, Inc.
|
||||
Copyright (c) 2019-2020, Vircadia contributors.
|
||||
Copyright (c) 2019-2021, Vircadia contributors.
|
||||
All rights reserved.
|
||||
https://vircadia.com
|
||||
|
||||
|
|
56
README.md
56
README.md
|
@ -1,10 +1,10 @@
|
|||
# Vircadia
|
||||
# Vircadia (Codename Athena)
|
||||
|
||||
### What is this?
|
||||
|
||||
Vircadia is a 3D social software project seeking to incrementally bring about a truly free and open metaverse, in desktop and XR.
|
||||
Vircadia™ is a 3D social software project seeking to incrementally bring about a truly free and open metaverse, in desktop and XR.
|
||||
|
||||
### [Download](https://vircadia.com/download-vircadia/)
|
||||
### [Website](https://vircadia.com/) | [Discord](https://discordapp.com/invite/Pvx2vke) | [Download](https://vircadia.com/download-vircadia/)
|
||||
|
||||
### Releases
|
||||
|
||||
|
@ -12,50 +12,46 @@ Vircadia is a 3D social software project seeking to incrementally bring about a
|
|||
|
||||
### How to build the Interface
|
||||
|
||||
[For Windows](https://github.com/vircadia/vircadia/blob/master/BUILD_WIN.md)
|
||||
|
||||
[For Mac](https://github.com/vircadia/vircadia/blob/master/BUILD_OSX.md)
|
||||
|
||||
[For Linux](https://github.com/vircadia/vircadia/blob/master/BUILD_LINUX.md)
|
||||
|
||||
[For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder)
|
||||
- [For Windows](https://github.com/vircadia/vircadia/blob/master/BUILD_WIN.md)
|
||||
- [For Mac](https://github.com/vircadia/vircadia/blob/master/BUILD_OSX.md)
|
||||
- [For Linux](https://github.com/vircadia/vircadia/blob/master/BUILD_LINUX.md)
|
||||
- [For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder)
|
||||
|
||||
### How to deploy a Server
|
||||
|
||||
[For Windows and Linux](https://vircadia.com/deploy-a-server/)
|
||||
- [For Windows and Linux](https://vircadia.com/deploy-a-server/)
|
||||
|
||||
### How to build a Server
|
||||
|
||||
[For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder)
|
||||
- [For Windows](https://github.com/vircadia/vircadia/blob/master/BUILD_WIN.md)
|
||||
- [For Linux](https://github.com/vircadia/vircadia/blob/master/BUILD_LINUX.md)
|
||||
- [For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder)
|
||||
|
||||
### How to generate an Installer
|
||||
|
||||
[For Windows](https://github.com/vircadia/vircadia/blob/master/INSTALL.md)
|
||||
- [For Windows](https://github.com/vircadia/vircadia/blob/master/INSTALLER.md)
|
||||
- [For Mac](https://github.com/vircadia/vircadia/blob/master/INSTALLER.md#os-x)
|
||||
- [For Linux - AppImage - Vircadia Builder](https://github.com/vircadia/vircadia-builder/blob/master/README.md#building-appimages)
|
||||
|
||||
[For Linux - AppImage - Vircadia Builder](https://github.com/vircadia/vircadia-builder/blob/master/README.md#building-appimages)
|
||||
|
||||
### Boot to Metaverse: The Goal
|
||||
### Boot to Metaverse: [The Goal](https://vircadia.com/vision/)
|
||||
|
||||
Having a place to experience adventure, a place to relax with calm breath, that's a world to live in. An engine to support infinite combinations and possibilities of worlds without censorship and interruption, that's a metaverse. Finding a way to make infinite realities our reality is the dream.
|
||||
|
||||
### Boot to Metaverse: The Technicals
|
||||
|
||||
Many developers have had personal combinations of High Fidelity from C++ modifications to different default scripts, all of which are lost to time as their fullest potential is never truly shared and propagated through the system.
|
||||
Vircadia consists of many projects and codebases with its unifying structure's goal being a decentralized metaverse.
|
||||
|
||||
The goal of this project is to achieve the metaverse dream through shared contribution and building. Setting goals that are achievable yet meaningful is key to making proper forward progress on the technical front whilst maintaining morale.
|
||||
- The Interface (Codename Athena) - You are here!
|
||||
- The Server (Codename Athena) - You are also here!
|
||||
- The UI Framework (Codename Nyx) - Codebase coming soon.
|
||||
- [The Metaverse (Codename Iamus)](https://github.com/vircadia/Iamus/)
|
||||
- [The Metaverse Dashboard (Codename Iamus)](https://github.com/vircadia/project-iamus-dashboard/)
|
||||
- [The Launcher (Codename Pantheon)](https://github.com/vircadia/pantheon-launcher/)
|
||||
|
||||
### Why High Fidelity's Virtual Reality Platform?
|
||||
|
||||
Because of all the options, it is the only starting point that is open-source, cross-platform, fully VR integrated + fully desktop integrated with an aim for quality visuals and performance. It also provides a foundation to build from including components like entity management, full body IK, etc.
|
||||
|
||||
WebXR offers the open-source and decentralized aspect but does not have any of the full featured starting points such as avatars, IK, etc. which means that a lot of ground work will have to be laid to make something functional. Far more work will need to be done to create a truly seamless and extensive experience as well.
|
||||
|
||||
Platforms like NeosVR or VRChat are not viable from go due to their fundamental closed-source and centralized nature. A metaverse to live in cannot have the keys handed over to any singular entity, if any at all.
|
||||
|
||||
We need to do the best we can with what we've got and our best bet as open source developers is to not redesign the wheel if we can help it!
|
||||
#### Child Projects
|
||||
- [Vircadia Builder for Linux](https://github.com/vircadia/vircadia-builder/)
|
||||
- [General Documentation](https://github.com/vircadia/vircadia-docs-sphinx/)
|
||||
|
||||
### Contribution
|
||||
|
||||
A special thanks to the contributors of Vircadia.
|
||||
|
||||
[Contribution](CONTRIBUTING.md)
|
||||
There are many contributors to Vircadia. Code writers, reviewers, testers, documentation writers, modelers, and general supporters of the project are all integral to its development and success towards its goals. Find out how you can [contribute](CONTRIBUTING.md)!
|
||||
|
|
|
@ -17,7 +17,7 @@ fi
|
|||
ANDROID_APP=interface
|
||||
ANDROID_OUTPUT_DIR=./apps/${ANDROID_APP}/build/outputs/apk/${ANDROID_BUILD_TYPE}
|
||||
ANDROID_OUTPUT_FILE=${ANDROID_APP}-${ANDROID_BUILD_TYPE}.apk
|
||||
ANDROID_APK_NAME=Vircadia-Alpha-${ANDROID_APK_SUFFIX}
|
||||
ANDROID_APK_NAME=Vircadia-${ANDROID_APK_SUFFIX}
|
||||
./gradlew -PHIFI_ANDROID_PRECOMPILED=${HIFI_ANDROID_PRECOMPILED} -PVERSION_CODE=${VERSION_CODE} -PRELEASE_NUMBER=${RELEASE_NUMBER} -PRELEASE_TYPE=${RELEASE_TYPE} ${ANDROID_APP}:${ANDROID_BUILD_TARGET}
|
||||
cp ${ANDROID_OUTPUT_DIR}/${ANDROID_OUTPUT_FILE} ./${ANDROID_APK_NAME}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <Trace.h>
|
||||
#include <StatTracker.h>
|
||||
#include <ThreadHelpers.h>
|
||||
|
||||
#include "AssignmentClientLogging.h"
|
||||
#include "AssignmentFactory.h"
|
||||
|
@ -235,10 +236,13 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer<ReceivedMessa
|
|||
qCDebug(assignment_client) << "Destination IP for assignment is" << nodeList->getDomainHandler().getIP().toString();
|
||||
|
||||
// start the deployed assignment
|
||||
QThread* workerThread = new QThread;
|
||||
QThread* workerThread = new QThread();
|
||||
workerThread->setObjectName("ThreadedAssignment Worker");
|
||||
|
||||
connect(workerThread, &QThread::started, _currentAssignment.data(), &ThreadedAssignment::run);
|
||||
connect(workerThread, &QThread::started, _currentAssignment.data(), [this] {
|
||||
setThreadName("ThreadedAssignment Worker");
|
||||
_currentAssignment->run();
|
||||
});
|
||||
|
||||
// Once the ThreadedAssignment says it is finished - we ask it to deleteLater
|
||||
// This is a queued connection so that it is put into the event loop to be processed by the worker
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
|
||||
#include "AudioMixerSlavePool.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include <ThreadHelpers.h>
|
||||
|
||||
void AudioMixerSlaveThread::run() {
|
||||
while (true) {
|
||||
wait();
|
||||
|
@ -157,6 +161,7 @@ void AudioMixerSlavePool::resize(int numThreads) {
|
|||
// start new slaves
|
||||
for (int i = 0; i < numThreads - _numThreads; ++i) {
|
||||
auto slave = new AudioMixerSlaveThread(*this, _workerSharedData);
|
||||
QObject::connect(slave, &QThread::started, [] { setThreadName("AudioMixerSlaveThread"); });
|
||||
slave->start();
|
||||
_slaves.emplace_back(slave);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <QtCore/QDir>
|
||||
|
||||
#include <OctreeDataUtils.h>
|
||||
#include <ThreadHelpers.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(octree_server, "hifi.octree-server")
|
||||
|
||||
|
@ -1192,7 +1193,10 @@ void OctreeServer::domainSettingsRequestComplete() {
|
|||
_persistAsFileType);
|
||||
_persistManager->moveToThread(&_persistThread);
|
||||
connect(&_persistThread, &QThread::finished, _persistManager, &QObject::deleteLater);
|
||||
connect(&_persistThread, &QThread::started, _persistManager, &OctreePersistThread::start);
|
||||
connect(&_persistThread, &QThread::started, _persistManager, [this] {
|
||||
setThreadName("OctreePersistThread");
|
||||
_persistManager->start();
|
||||
});
|
||||
connect(_persistManager, &OctreePersistThread::loadCompleted, this, [this]() {
|
||||
beginRunning();
|
||||
});
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
Binary file not shown.
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
|
@ -31,7 +31,7 @@ macro(GENERATE_INSTALLERS)
|
|||
set(CPACK_PACKAGE_NAME ${_DISPLAY_NAME})
|
||||
set(CPACK_PACKAGE_VENDOR "Vircadia")
|
||||
set(CPACK_PACKAGE_VERSION ${BUILD_VERSION})
|
||||
set(CPACK_PACKAGE_FILE_NAME "Vircadia-Alpha${_PACKAGE_NAME_EXTRA}-${BUILD_VERSION}")
|
||||
set(CPACK_PACKAGE_FILE_NAME "Vircadia${_PACKAGE_NAME_EXTRA}-${BUILD_VERSION}")
|
||||
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
|
||||
set(CPACK_NSIS_PACKAGE_NAME ${_DISPLAY_NAME})
|
||||
if (PR_BUILD)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
|
||||
macro(optional_win_executable_signing)
|
||||
if (WIN32 AND PRODUCTION_BUILD)
|
||||
if (WIN32 AND PRODUCTION_BUILD AND NOT BYPASS_SIGNING)
|
||||
if (DEFINED ENV{HF_PFX_FILE})
|
||||
if (DEFINED ENV{HF_PFX_PASSPHRASE})
|
||||
message(STATUS "Executable for ${TARGET_NAME} will be signed with SignTool.")
|
||||
|
|
|
@ -23,8 +23,10 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
|
||||
set_from_env(RELEASE_TYPE RELEASE_TYPE "DEV")
|
||||
set_from_env(RELEASE_NUMBER RELEASE_NUMBER "")
|
||||
set_from_env(RELEASE_NAME RELEASE_NAME "")
|
||||
set_from_env(STABLE_BUILD STABLE_BUILD 0)
|
||||
set_from_env(INITIAL_STARTUP_LOCATION INITIAL_STARTUP_LOCATION "")
|
||||
set_from_env(BYPASS_SIGNING BYPASS_SIGNING 0)
|
||||
|
||||
message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
macro(target_oculus_mobile)
|
||||
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/oculus_1.22/VrApi)
|
||||
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/ovr_sdk_mobile_1.37.0/VrApi)
|
||||
|
||||
# Mobile SDK
|
||||
set(OVR_MOBILE_INCLUDE_DIRS ${INSTALL_DIR}/Include)
|
||||
|
@ -12,7 +12,7 @@ macro(target_oculus_mobile)
|
|||
target_link_libraries(${TARGET_NAME} ${OVR_MOBILE_LIBRARIES})
|
||||
|
||||
# Platform SDK
|
||||
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/oculusPlatform)
|
||||
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/ovr_platform_sdk_23.0.0)
|
||||
set(OVR_PLATFORM_INCLUDE_DIRS ${INSTALL_DIR}/Include)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${OVR_PLATFORM_INCLUDE_DIRS})
|
||||
set(OVR_PLATFORM_LIBRARIES ${INSTALL_DIR}/Android/libs/arm64-v8a/libovrplatformloader.so)
|
||||
|
|
|
@ -2,13 +2,22 @@ include(vcpkg_common_functions)
|
|||
vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
|
||||
|
||||
file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS)
|
||||
file(READ "${VCPKG_ROOT_DIR}/_env/USE_GLES.txt" USE_GLES)
|
||||
|
||||
# GitHub Actions Android builds fail with `FILENAME` set while desktop builds with GLES fail without a set `FILENAME`.
|
||||
if (ANDROID)
|
||||
vcpkg_download_distfile(
|
||||
SOURCE_ARCHIVE
|
||||
URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad32es.zip
|
||||
SHA512 2e02ac633eed8f2ba2adbf96ea85d08998f48dd2e9ec9a88ec3c25f48eaf1405371d258066327c783772fcb3793bdb82bd7375fdabb2ba5e2ce0835468b17f65
|
||||
)
|
||||
elseif (USE_GLES)
|
||||
vcpkg_download_distfile(
|
||||
SOURCE_ARCHIVE
|
||||
URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad32es.zip
|
||||
SHA512 2e02ac633eed8f2ba2adbf96ea85d08998f48dd2e9ec9a88ec3c25f48eaf1405371d258066327c783772fcb3793bdb82bd7375fdabb2ba5e2ce0835468b17f65
|
||||
FILENAME glad32es.zip
|
||||
)
|
||||
else()
|
||||
# else Linux desktop
|
||||
vcpkg_download_distfile(
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Stephen Birarda on 1/14/16.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -24,6 +25,7 @@ namespace BuildInfo {
|
|||
const QString MODIFIED_ORGANIZATION = "@BUILD_ORGANIZATION@";
|
||||
const QString ORGANIZATION_DOMAIN = "vircadia.com";
|
||||
const QString VERSION = "@BUILD_VERSION@";
|
||||
const QString RELEASE_NAME = "@RELEASE_NAME@";
|
||||
const QString BUILD_NUMBER = "@BUILD_NUMBER@";
|
||||
const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@";
|
||||
const QString BUILD_TIME = "@BUILD_TIME@";
|
||||
|
|
|
@ -837,16 +837,24 @@ Function PostInstallOptionsPage
|
|||
!insertmacro SetInstallOption $DesktopClientCheckbox @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ ${BST_CHECKED}
|
||||
${EndIf}
|
||||
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @SANDBOX_HF_SHORTCUT_NAME@"
|
||||
;${Else}
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
|
||||
;${EndIf}
|
||||
;Pop $DesktopConsoleCheckbox
|
||||
;IntOp $CurrentOffset $CurrentOffset + 15
|
||||
;
|
||||
;; set the checkbox state depending on what is present in the registry
|
||||
;!insertmacro SetInstallOption $DesktopConsoleCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @SANDBOX_HF_SHORTCUT_NAME@"
|
||||
${Else}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
|
||||
Pop $DesktopConsoleCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $DesktopConsoleCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
Pop $DesktopConsoleCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $DesktopConsoleCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
||||
|
||||
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
|
||||
|
@ -861,31 +869,54 @@ Function PostInstallOptionsPage
|
|||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ after install"
|
||||
;${Else}
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
|
||||
;${EndIf}
|
||||
;Pop $LaunchConsoleNowCheckbox
|
||||
;
|
||||
;; set the checkbox state depending on what is present in the registry
|
||||
;!insertmacro SetInstallOption $LaunchConsoleNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_UNCHECKED}
|
||||
;${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE
|
||||
;${IfNot} $substringResult == ""
|
||||
; ${NSD_SetState} $LaunchConsoleNowCheckbox ${BST_UNCHECKED}
|
||||
;${EndIf}
|
||||
;IntOp $CurrentOffset $CurrentOffset + 15
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ after install"
|
||||
${Else}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
|
||||
${EndIf}
|
||||
Pop $LaunchConsoleNowCheckbox
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $LaunchConsoleNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_UNCHECKED}
|
||||
${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE
|
||||
${IfNot} $substringResult == ""
|
||||
Pop $LaunchConsoleNowCheckbox
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $LaunchConsoleNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_UNCHECKED}
|
||||
${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE
|
||||
${IfNot} $substringResult == ""
|
||||
${NSD_SetState} $LaunchConsoleNowCheckbox ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
${EndIf}
|
||||
IntOp $CurrentOffset $CurrentOffset + 30
|
||||
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ on startup"
|
||||
${Else}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
|
||||
${EndIf}
|
||||
Pop $ConsoleStartupCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $ConsoleStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_UNCHECKED}
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ on startup"
|
||||
;${Else}
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
|
||||
;${EndIf}
|
||||
;Pop $ConsoleStartupCheckbox
|
||||
;IntOp $CurrentOffset $CurrentOffset + 15
|
||||
;
|
||||
;; set the checkbox state depending on what is present in the registry
|
||||
;!insertmacro SetInstallOption $ConsoleStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_UNCHECKED}
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ on startup"
|
||||
Pop $ConsoleStartupCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $ConsoleStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)"
|
||||
Pop $CleanInstallCheckbox
|
||||
|
@ -957,13 +988,29 @@ FunctionEnd
|
|||
|
||||
Function ReadPostInstallOptions
|
||||
|
||||
; check if the user asked for a desktop shortcut to console
|
||||
${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState
|
||||
${LogText} "Option: Start Desktop Console: $DesktopConsoleState"
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;; check if the user asked for a desktop shortcut to console
|
||||
;${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState
|
||||
;${LogText} "Option: Start Desktop Console: $DesktopConsoleState"
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; check if the user asked for a desktop shortcut to console
|
||||
${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState
|
||||
${LogText} "Option: Start Desktop Console: $DesktopConsoleState"
|
||||
${Else}
|
||||
StrCpy $DesktopConsoleState ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
; check if the user asked to have console launched every startup
|
||||
${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState
|
||||
${LogText} "Option: Start Desktop Console On Startup: $ConsoleStartupState"
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;; check if the user asked to have console launched every startup
|
||||
;${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState
|
||||
;${LogText} "Option: Start Desktop Console On Startup: $ConsoleStartupState"
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; check if the user asked to have console launched every startup
|
||||
${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState
|
||||
${LogText} "Option: Start Desktop Console On Startup: $ConsoleStartupState"
|
||||
${Else}
|
||||
StrCpy $ConsoleStartupState ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${LogText} "Option: Install Server"
|
||||
|
@ -1308,10 +1355,13 @@ Section "-Core installation"
|
|||
${Else}
|
||||
; handling for interface only console shortcut
|
||||
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
|
||||
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||
; Set appUserModelId
|
||||
ApplicationID::Set "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
|
||||
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
|
||||
; "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||
;; Set appUserModelId
|
||||
;ApplicationID::Set "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
|
||||
|
||||
${EndIf}
|
||||
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\@UNINSTALLER_NAME@"
|
||||
|
|
|
@ -2013,6 +2013,23 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "domain_server",
|
||||
"label": "Setup Domain Server",
|
||||
"restart": false,
|
||||
"hidden": true,
|
||||
"settings": [
|
||||
{
|
||||
"name": "network_address",
|
||||
"default": ""
|
||||
},
|
||||
{
|
||||
"name": "network_port",
|
||||
"type": "int",
|
||||
"default": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "installed_content",
|
||||
"label": "Installed Content",
|
||||
|
|
|
@ -129,9 +129,10 @@ function getCurrentDomainIDType() {
|
|||
return DOMAIN_ID_TYPE_UNKNOWN;
|
||||
}
|
||||
if (DomainInfo !== null) {
|
||||
if (DomainInfo.name !== undefined) {
|
||||
return DOMAIN_ID_TYPE_TEMP;
|
||||
}
|
||||
// Disabled because detecting as temp domain... and we're not even using temp domains right now.
|
||||
// if (DomainInfo.name !== undefined) {
|
||||
// return DOMAIN_ID_TYPE_TEMP;
|
||||
// }
|
||||
return DOMAIN_ID_TYPE_FULL;
|
||||
}
|
||||
return DOMAIN_ID_TYPE_UNKNOWN;
|
||||
|
@ -504,7 +505,7 @@ function createDomainIDPrompt(callback) {
|
|||
swal({
|
||||
title: 'Finish Registering Domain',
|
||||
type: 'input',
|
||||
text: 'Enter a label for this machine.</br></br>This will help you identify which domain ID belongs to which machine.</br></br>This is a required step for registration.</br></br>',
|
||||
text: 'Enter a label for this Domain Server.</br></br>This will help you identify which domain ID belongs to which server.</br></br>This is a required step for registration.</br></br>Acceptable characters are [A-Z][a-z0-9]+-_.</br',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Create",
|
||||
closeOnConfirm: false,
|
||||
|
|
|
@ -193,7 +193,11 @@ function promptToCreateDomainID() {
|
|||
|
||||
var formJSON = {
|
||||
"metaverse": {
|
||||
"automatic_networking": "full",
|
||||
"id": domainID
|
||||
},
|
||||
"descriptors": {
|
||||
"world_name": label
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include <Gzip.h>
|
||||
|
||||
#include <OctreeDataUtils.h>
|
||||
#include <ThreadHelpers.h>
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
|
@ -68,6 +69,9 @@ Q_LOGGING_CATEGORY(domain_server_ice, "hifi.domain_server.ice")
|
|||
|
||||
const QString ACCESS_TOKEN_KEY_PATH = "metaverse.access_token";
|
||||
const QString DomainServer::REPLACEMENT_FILE_EXTENSION = ".replace";
|
||||
const QString PUBLIC_SOCKET_ADDRESS_KEY = "network_address";
|
||||
const QString PUBLIC_SOCKET_PORT_KEY = "network_port";
|
||||
const QString DOMAIN_UPDATE_AUTOMATIC_NETWORKING_KEY = "automatic_networking";
|
||||
const int MIN_PORT = 1;
|
||||
const int MAX_PORT = 65535;
|
||||
|
||||
|
@ -827,9 +831,11 @@ void DomainServer::setupNodeListAndAssignments() {
|
|||
// set a custom packetVersionMatch as the verify packet operator for the udt::Socket
|
||||
nodeList->setPacketFilterOperator(&DomainServer::isPacketVerified);
|
||||
|
||||
_assetClientThread.setObjectName("AssetClient Thread");
|
||||
QString name = "AssetClient Thread";
|
||||
_assetClientThread.setObjectName(name);
|
||||
auto assetClient = DependencyManager::set<AssetClient>();
|
||||
assetClient->moveToThread(&_assetClientThread);
|
||||
connect(&_assetClientThread, &QThread::started, [name] { setThreadName(name.toStdString()); });
|
||||
_assetClientThread.start();
|
||||
// add whatever static assignments that have been parsed to the queue
|
||||
addStaticAssignmentsToQueue();
|
||||
|
@ -901,14 +907,13 @@ void DomainServer::setupAutomaticNetworking() {
|
|||
qDebug() << "domain-server" << _automaticNetworkingSetting << "automatic networking enabled for ID"
|
||||
<< uuidStringWithoutCurlyBraces(domainID) << "via" << _oauthProviderURL.toString();
|
||||
|
||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
// send any public socket changes to the data server so nodes can find us at our new IP
|
||||
connect(nodeList.data(), &LimitedNodeList::publicSockAddrChanged, this,
|
||||
&DomainServer::performIPAddressPortUpdate);
|
||||
|
||||
if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE) {
|
||||
|
||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
// send any public socket changes to the data server so nodes can find us at our new IP
|
||||
connect(nodeList.data(), &LimitedNodeList::publicSockAddrChanged,
|
||||
this, &DomainServer::performIPAddressUpdate);
|
||||
|
||||
// have the LNL enable public socket updating via STUN
|
||||
nodeList->startSTUNPublicSocketUpdate();
|
||||
}
|
||||
|
@ -1504,13 +1509,23 @@ QJsonObject jsonForDomainSocketUpdate(const HifiSockAddr& socket) {
|
|||
return socketObject;
|
||||
}
|
||||
|
||||
const QString DOMAIN_UPDATE_AUTOMATIC_NETWORKING_KEY = "automatic_networking";
|
||||
void DomainServer::performIPAddressPortUpdate(const HifiSockAddr& newPublicSockAddr) {
|
||||
const QString& DOMAIN_SERVER_SETTINGS_KEY = "domain_server";
|
||||
const QString& publicSocketAddress = newPublicSockAddr.getAddress().toString();
|
||||
const int publicSocketPort = newPublicSockAddr.getPort();
|
||||
|
||||
void DomainServer::performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr) {
|
||||
sendHeartbeatToMetaverse(newPublicSockAddr.getAddress().toString());
|
||||
sendHeartbeatToMetaverse(publicSocketAddress, publicSocketPort);
|
||||
|
||||
QJsonObject rootObject;
|
||||
QJsonObject domainServerObject;
|
||||
domainServerObject.insert(PUBLIC_SOCKET_ADDRESS_KEY, publicSocketAddress);
|
||||
domainServerObject.insert(PUBLIC_SOCKET_PORT_KEY, publicSocketPort);
|
||||
rootObject.insert(DOMAIN_SERVER_SETTINGS_KEY, domainServerObject);
|
||||
QJsonDocument doc(rootObject);
|
||||
_settingsManager.recurseJSONObjectAndOverwriteSettings(rootObject, DomainSettings);
|
||||
}
|
||||
|
||||
void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) {
|
||||
void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress, const int port) {
|
||||
// Setup the domain object to send to the data server
|
||||
QJsonObject domainObject;
|
||||
|
||||
|
@ -1520,10 +1535,20 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) {
|
|||
static const QString PROTOCOL_VERSION_KEY = "protocol";
|
||||
domainObject[PROTOCOL_VERSION_KEY] = protocolVersionsSignatureBase64();
|
||||
|
||||
// add networking
|
||||
static const QString NETWORK_ADDRESS_SETTINGS_KEY = "domain_server." + PUBLIC_SOCKET_ADDRESS_KEY;
|
||||
const QString networkAddressFromSettings = _settingsManager.valueForKeyPath(NETWORK_ADDRESS_SETTINGS_KEY).toString();
|
||||
if (!networkAddress.isEmpty()) {
|
||||
static const QString PUBLIC_NETWORK_ADDRESS_KEY = "network_address";
|
||||
domainObject[PUBLIC_NETWORK_ADDRESS_KEY] = networkAddress;
|
||||
domainObject[PUBLIC_SOCKET_ADDRESS_KEY] = networkAddress;
|
||||
} else if (!networkAddressFromSettings.isEmpty()) {
|
||||
domainObject[PUBLIC_SOCKET_ADDRESS_KEY] = networkAddressFromSettings;
|
||||
}
|
||||
|
||||
static const QString PORT_SETTINGS_KEY = "domain_server." + PUBLIC_SOCKET_PORT_KEY;
|
||||
const int portFromSettings = _settingsManager.valueForKeyPath(PORT_SETTINGS_KEY).toInt();
|
||||
if (port != NULL) {
|
||||
domainObject[PUBLIC_SOCKET_PORT_KEY] = port;
|
||||
} else if (portFromSettings != NULL) {
|
||||
domainObject[PUBLIC_SOCKET_PORT_KEY] = portFromSettings;
|
||||
}
|
||||
|
||||
static const QString AUTOMATIC_NETWORKING_KEY = "automatic_networking";
|
||||
|
|
|
@ -112,8 +112,8 @@ private slots:
|
|||
void setupPendingAssignmentCredits();
|
||||
void sendPendingTransactionsToServer();
|
||||
|
||||
void performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr);
|
||||
void sendHeartbeatToMetaverse() { sendHeartbeatToMetaverse(QString()); }
|
||||
void performIPAddressPortUpdate(const HifiSockAddr& newPublicSockAddr);
|
||||
void sendHeartbeatToMetaverse() { sendHeartbeatToMetaverse(QString(), int()); }
|
||||
void sendHeartbeatToIceServer();
|
||||
void nodePingMonitor();
|
||||
|
||||
|
@ -176,7 +176,7 @@ private:
|
|||
void setupAutomaticNetworking();
|
||||
void setupICEHeartbeatForFullNetworking();
|
||||
void setupHeartbeatToMetaverse();
|
||||
void sendHeartbeatToMetaverse(const QString& networkAddress);
|
||||
void sendHeartbeatToMetaverse(const QString& networkAddress, const int port);
|
||||
|
||||
void randomizeICEServerAddress(bool shouldTriggerHostLookup);
|
||||
|
||||
|
|
|
@ -39,15 +39,15 @@ ANDROID_PACKAGES = {
|
|||
'sharedLibFolder': 'lib',
|
||||
'includeLibs': ['libnvtt.so', 'libnvmath.so', 'libnvimage.so', 'libnvcore.so']
|
||||
},
|
||||
'oculus_1.22': {
|
||||
'file': 'ovr_sdk_mobile_1.22.zip',
|
||||
'checksum': '1ac3c5b0521e5406f287f351015daff8',
|
||||
'ovr_sdk_mobile_1.37.0': {
|
||||
'file': 'ovr_sdk_mobile_1.37.0.zip',
|
||||
'checksum': '6040e1966f335a3e5015295154cd7383',
|
||||
'sharedLibFolder': 'VrApi/Libs/Android/arm64-v8a/Release',
|
||||
'includeLibs': ['libvrapi.so']
|
||||
},
|
||||
'oculusPlatform': {
|
||||
'file': 'OVRPlatformSDK_v1.34.0.zip',
|
||||
'checksum': '16e4c5f39520f122bc49cb6d5bb88289',
|
||||
'ovr_platform_sdk_23.0.0': {
|
||||
'file': 'ovr_platform_sdk_23.0.0.zip',
|
||||
'checksum': '29d02b560f60d0fa7b8a64cd965dd55b',
|
||||
'sharedLibFolder': 'Android/libs/arm64-v8a',
|
||||
'includeLibs': ['libovrplatformloader.so']
|
||||
},
|
||||
|
|
|
@ -90,8 +90,8 @@ endif()
|
|||
if 'Windows' == system:
|
||||
self.exe = os.path.join(self.path, 'vcpkg.exe')
|
||||
self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.bat'), '-disableMetrics' ]
|
||||
self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-win32-client.zip%3FversionId=tSFzbw01VkkVFeRQ6YuAY4dro2HxJR9U'
|
||||
self.vcpkgHash = 'a650db47a63ccdc9904b68ddd16af74772e7e78170b513ea8de5a3b47d032751a3b73dcc7526d88bcb500753ea3dd9880639ca842bb176e2bddb1710f9a58cd3'
|
||||
self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/vcpkg-win32-client-20210122.zip'
|
||||
self.vcpkgHash = '3df86b7d58c827bf08b3b7744f456f414b86a6d9bd58a507924103bc5a88f01ee495ce1f0fbf2f5b27f1ef6bfb1526e580ec13d3b9f87a89a462b3c50589fd6a'
|
||||
self.hostTriplet = 'x64-windows'
|
||||
if usePrebuilt:
|
||||
self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-win32.zip%3FversionId=3SF3mDC8dkQH1JP041m88xnYmWNzZflx"
|
||||
|
|
Binary file not shown.
|
@ -19,16 +19,17 @@ Item {
|
|||
property string url: ""
|
||||
property string scriptUrl: null
|
||||
property bool useBackground: true
|
||||
property string userAgent: ""
|
||||
|
||||
onUrlChanged: {
|
||||
load(root.url, root.scriptUrl, root.useBackground);
|
||||
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||
}
|
||||
|
||||
onScriptUrlChanged: {
|
||||
if (root.item) {
|
||||
root.item.scriptUrl = root.scriptUrl;
|
||||
} else {
|
||||
load(root.url, root.scriptUrl, root.useBackground);
|
||||
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,13 +37,21 @@ Item {
|
|||
if (root.item) {
|
||||
root.item.useBackground = root.useBackground;
|
||||
} else {
|
||||
load(root.url, root.scriptUrl, root.useBackground);
|
||||
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||
}
|
||||
}
|
||||
|
||||
onUserAgentChanged: {
|
||||
if (root.item) {
|
||||
root.item.userAgent = root.userAgent;
|
||||
} else {
|
||||
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||
}
|
||||
}
|
||||
|
||||
property var item: null
|
||||
|
||||
function load(url, scriptUrl, useBackground) {
|
||||
function load(url, scriptUrl, useBackground, userAgent) {
|
||||
// Ensure we reset any existing item to "about:blank" to ensure web audio stops: DEV-2375
|
||||
if (root.item != null) {
|
||||
root.item.url = "about:blank"
|
||||
|
@ -54,11 +63,12 @@ Item {
|
|||
root.item.url = url
|
||||
root.item.scriptUrl = scriptUrl
|
||||
root.item.useBackground = useBackground
|
||||
root.item.userAgent = userAgent
|
||||
})
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
load(root.url, root.scriptUrl, root.useBackground);
|
||||
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||
}
|
||||
|
||||
signal sendToScript(var message);
|
||||
|
|
|
@ -13,10 +13,13 @@ Item {
|
|||
property alias url: webViewCore.url
|
||||
property alias canGoBack: webViewCore.canGoBack
|
||||
property alias webViewCore: webViewCore
|
||||
property alias webViewCoreProfile: webViewCore.profile
|
||||
// FIXME - This was commented out to allow for manual setting of the userAgent.
|
||||
//
|
||||
// property alias webViewCoreProfile: webViewCore.profile
|
||||
property string webViewCoreUserAgent
|
||||
|
||||
property bool useBackground: webViewCore.useBackground
|
||||
property string userAgent: webViewCore.profile.httpUserAgent
|
||||
property string userScriptUrl: ""
|
||||
property string urlTag: "noDownload=false";
|
||||
|
||||
|
@ -34,6 +37,10 @@ Item {
|
|||
permissionPopupBackground.visible = false;
|
||||
}
|
||||
|
||||
onUserAgentChanged: {
|
||||
webViewCore.profile.httpUserAgent = flick.userAgent;
|
||||
}
|
||||
|
||||
StylesUIt.HifiConstants {
|
||||
id: hifi
|
||||
}
|
||||
|
@ -74,7 +81,7 @@ Item {
|
|||
|
||||
function onLoadingChanged(loadRequest) {
|
||||
if (WebEngineView.LoadStartedStatus === loadRequest.status) {
|
||||
|
||||
webViewCore.profile.httpUserAgent = flick.userAgent;
|
||||
// Required to support clicking on "hifi://" links
|
||||
var url = loadRequest.url.toString();
|
||||
url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag;
|
||||
|
@ -101,7 +108,6 @@ Item {
|
|||
height: parent.height
|
||||
backgroundColor: (flick.useBackground) ? "white" : "transparent"
|
||||
|
||||
profile: HFWebEngineProfile;
|
||||
settings.pluginsEnabled: true
|
||||
settings.touchIconsEnabled: true
|
||||
settings.allowRunningInsecureContent: true
|
||||
|
@ -136,8 +142,10 @@ Item {
|
|||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
|
||||
if (webViewCoreUserAgent !== undefined) {
|
||||
webViewCore.profile.httpUserAgent = webViewCoreUserAgent
|
||||
if (flick.userAgent !== undefined) {
|
||||
webViewCore.profile.httpUserAgent = flick.userAgent;
|
||||
webViewCore.profile.offTheRecord = false;
|
||||
webViewCore.profile.storageName = "qmlWebEngine";
|
||||
} else {
|
||||
webViewCore.profile.httpUserAgent += " (VircadiaInterface)";
|
||||
}
|
||||
|
|
|
@ -11,12 +11,14 @@ Item {
|
|||
property alias url: webViewCore.url
|
||||
property alias canGoBack: webViewCore.canGoBack
|
||||
property alias webViewCore: webViewCore
|
||||
property alias webViewCoreProfile: webViewCore.profile
|
||||
property string webViewCoreUserAgent
|
||||
// FIXME - This was commented out to allow for manual setting of the userAgent.
|
||||
//
|
||||
// property alias webViewCoreProfile: webViewCore.profile
|
||||
|
||||
property bool useBackground: webViewCore.useBackground
|
||||
property alias useBackground: webViewCore.useBackground
|
||||
property alias userAgent: webViewCore.userAgent
|
||||
property string userScriptUrl: ""
|
||||
property string urlTag: "noDownload=false";
|
||||
property string urlTag: "noDownload=false"
|
||||
|
||||
signal newViewRequestedCallback(var request)
|
||||
signal loadingChangedCallback(var loadRequest)
|
||||
|
|
|
@ -27,7 +27,11 @@ Item {
|
|||
}
|
||||
*/
|
||||
|
||||
property alias viewProfile: webroot.webViewCoreProfile
|
||||
// FIXME - Reimplement profiles for... why? Was it so that new windows opened share the same profile?
|
||||
// Are profiles written to by the webengine during the session?
|
||||
// Removed in PR Feature/web entity user agent #988
|
||||
//
|
||||
// property alias viewProfile: webroot.webViewCoreProfile
|
||||
|
||||
FlickableWebViewCore {
|
||||
id: webroot
|
||||
|
|
|
@ -25,7 +25,11 @@ Item {
|
|||
property bool isDesktop: false
|
||||
property alias url: web.url
|
||||
property alias webView: web.webViewCore
|
||||
property alias profile: web.webViewCoreProfile
|
||||
// FIXME - Reimplement profiles for... why? Was it so that new windows opened share the same profile?
|
||||
// Are profiles written to by the webengine during the session?
|
||||
// Removed in PR Feature/web entity user agent #988
|
||||
//
|
||||
// property alias profile: web.webViewCoreProfile
|
||||
property bool remove: false
|
||||
property bool closeButtonVisible: true
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ Item {
|
|||
property alias flickable: webroot.interactive
|
||||
property alias blurOnCtrlShift: webroot.blurOnCtrlShift
|
||||
property alias useBackground: webroot.useBackground
|
||||
property alias userAgent: webroot.userAgent
|
||||
|
||||
function stop() {
|
||||
webroot.stop();
|
||||
|
@ -37,7 +38,11 @@ Item {
|
|||
}
|
||||
*/
|
||||
|
||||
property alias viewProfile: webroot.webViewCoreProfile
|
||||
// FIXME - Reimplement profiles for... why? Was it so that new windows opened share the same profile?
|
||||
// Are profiles written to by the webengine during the session?
|
||||
// Removed in PR Feature/web entity user agent #988
|
||||
//
|
||||
// property alias viewProfile: webroot.webViewCoreProfile
|
||||
|
||||
FlickableWebViewCore {
|
||||
id: webroot
|
||||
|
|
|
@ -244,7 +244,7 @@ Item {
|
|||
color: hifi.colors.darkGray;
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: selected && pal.activeTab == "nearbyTab" && thisNameCard.userName !== "" && isPresent;
|
||||
enabled: selected && pal.activeTab == "nearbyTab" && isPresent;
|
||||
hoverEnabled: enabled
|
||||
onClicked: {
|
||||
goToUserInDomain(thisNameCard.uuid);
|
||||
|
|
|
@ -28,13 +28,18 @@ Rectangle {
|
|||
fillMode: Image.PreserveAspectFit
|
||||
source: "../../../images/vircadia-banner.svg"
|
||||
}
|
||||
Item { height: 30; width: 1 }
|
||||
Item { height: 25; width: 1 }
|
||||
Column {
|
||||
id: buildColumm
|
||||
id: buildColumn
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 70
|
||||
anchors.leftMargin: 0
|
||||
RalewayRegular {
|
||||
text: "Build " + About.buildVersion
|
||||
text: "Interface"
|
||||
size: 16
|
||||
color: "white"
|
||||
}
|
||||
RalewayRegular {
|
||||
text: "Build " + About.buildVersion + " " + About.releaseName
|
||||
size: 16
|
||||
color: "white"
|
||||
}
|
||||
|
@ -54,14 +59,25 @@ Rectangle {
|
|||
textFormat: Text.StyledText
|
||||
linkColor: "#00B4EF"
|
||||
color: "white"
|
||||
text: "<a href=\"https://github.com/vircadia/vircadia\">Vircadia Github</a>."
|
||||
text: "<a href=\"https://vircadia.com\">Website</a>"
|
||||
size: 20
|
||||
onLinkActivated: {
|
||||
About.openUrl("https:/github.com/vircadia/vircadia");
|
||||
About.openUrl("https://vircadia.com");
|
||||
}
|
||||
|
||||
}
|
||||
Item { height: 40; width: 1 }
|
||||
RalewayRegular {
|
||||
textFormat: Text.StyledText
|
||||
linkColor: "#00B4EF"
|
||||
color: "white"
|
||||
text: "<a href=\"https://github.com/vircadia/vircadia\">Source</a>"
|
||||
size: 20
|
||||
onLinkActivated: {
|
||||
About.openUrl("https://github.com/vircadia/vircadia");
|
||||
}
|
||||
|
||||
}
|
||||
Item { height: 25; width: 1 }
|
||||
Row {
|
||||
spacing: 5
|
||||
Image {
|
||||
|
@ -117,7 +133,7 @@ Rectangle {
|
|||
Item { height: 20; width: 1 }
|
||||
RalewayRegular {
|
||||
color: "white"
|
||||
text: "© 2019-2020 Vircadia contributors."
|
||||
text: "© 2019 - 2021 Vircadia contributors."
|
||||
size: 14
|
||||
}
|
||||
RalewayRegular {
|
||||
|
@ -135,5 +151,23 @@ Rectangle {
|
|||
About.openUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
|
||||
}
|
||||
}
|
||||
Item { height: 35; width: 1 }
|
||||
RalewayRegular {
|
||||
color: "white"
|
||||
text: "In memoriam,"
|
||||
size: 14
|
||||
}
|
||||
RalewayRegular {
|
||||
color: "white"
|
||||
text: "2012 - 2019 the High Fidelity virtual reality project."
|
||||
size: 14
|
||||
}
|
||||
Item { height: 5; width: 1 }
|
||||
Image {
|
||||
id: hifiLogo
|
||||
width: 200; height: 50
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "../../../images/about-highfidelity.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Vlad Stelmahovsky on 15/5/2018.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -40,6 +41,10 @@ QString AboutUtil::getBuildVersion() const {
|
|||
return BuildInfo::VERSION;
|
||||
}
|
||||
|
||||
QString AboutUtil::getReleaseName() const {
|
||||
return BuildInfo::RELEASE_NAME;
|
||||
}
|
||||
|
||||
QString AboutUtil::getQtVersion() const {
|
||||
return qVersion();
|
||||
}
|
||||
|
@ -57,15 +62,15 @@ void AboutUtil::openUrl(const QString& url) const {
|
|||
|
||||
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto offscreenUI = DependencyManager::get<OffscreenUi>();
|
||||
|
||||
if (tablet->getToolbarMode()) {
|
||||
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
if (tablet->getToolbarMode() && offscreenUI) {
|
||||
offscreenUI->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
newObject->setProperty("url", url);
|
||||
});
|
||||
} else {
|
||||
if (!hmd->getShouldShowTablet() && !qApp->isHMDMode()) {
|
||||
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
if (!hmd->getShouldShowTablet() && !qApp->isHMDMode() && offscreenUI) {
|
||||
offscreenUI->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
newObject->setProperty("url", url);
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -30,12 +30,14 @@
|
|||
* <em>Read-only.</em>
|
||||
* @property {string} buildDate - The build date of Interface that is currently running. <em>Read-only.</em>
|
||||
* @property {string} buildVersion - The build version of Interface that is currently running. <em>Read-only.</em>
|
||||
* @property {string} releaseName - The release codename of the version that Interface is currently running. <em>Read-only.</em>
|
||||
* @property {string} qtVersion - The Qt version used in Interface that is currently running. <em>Read-only.</em>
|
||||
*
|
||||
* @example <caption>Report information on the version of Interface currently running.</caption>
|
||||
* print("Interface platform: " + About.platform);
|
||||
* print("Interface build date: " + About.buildDate);
|
||||
* print("Interface version: " + About.buildVersion);
|
||||
* print("Interface release name: " + About.releaseName);
|
||||
* print("Qt version: " + About.qtVersion);
|
||||
*/
|
||||
|
||||
|
@ -66,6 +68,7 @@ class AboutUtil : public QObject {
|
|||
Q_PROPERTY(QString platform READ getPlatformName CONSTANT)
|
||||
Q_PROPERTY(QString buildDate READ getBuildDate CONSTANT)
|
||||
Q_PROPERTY(QString buildVersion READ getBuildVersion CONSTANT)
|
||||
Q_PROPERTY(QString releaseName READ getReleaseName CONSTANT)
|
||||
Q_PROPERTY(QString qtVersion READ getQtVersion CONSTANT)
|
||||
public:
|
||||
static AboutUtil* getInstance();
|
||||
|
@ -74,6 +77,7 @@ public:
|
|||
QString getPlatformName() const { return "Vircadia"; }
|
||||
QString getBuildDate() const;
|
||||
QString getBuildVersion() const;
|
||||
QString getReleaseName() const;
|
||||
QString getQtVersion() const;
|
||||
|
||||
public slots:
|
||||
|
|
|
@ -254,6 +254,7 @@
|
|||
|
||||
#include "AboutUtil.h"
|
||||
#include "ExternalResource.h"
|
||||
#include <ThreadHelpers.h>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <VersionHelpers.h>
|
||||
|
@ -1168,6 +1169,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
if (!DISABLE_WATCHDOG) {
|
||||
auto deadlockWatchdogThread = new DeadlockWatchdogThread();
|
||||
deadlockWatchdogThread->setMainThreadID(QThread::currentThreadId());
|
||||
connect(deadlockWatchdogThread, &QThread::started, [] { setThreadName("DeadlockWatchdogThread"); });
|
||||
deadlockWatchdogThread->start();
|
||||
|
||||
// Pause the deadlock watchdog when we sleep, or it might
|
||||
|
@ -2455,13 +2457,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value);
|
||||
});
|
||||
|
||||
EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos) {
|
||||
BillboardModeHelpers::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation,
|
||||
BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) {
|
||||
const glm::quat ROTATE_90X = glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT);
|
||||
if (billboardMode == BillboardMode::YAW) {
|
||||
//rotate about vertical to face the camera
|
||||
glm::vec3 dPosition = frustumPos - position;
|
||||
// If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
|
||||
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
|
||||
return glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
|
||||
glm::quat result = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)) * rotation;
|
||||
if (rotate90x) {
|
||||
result *= ROTATE_90X;
|
||||
}
|
||||
return result;
|
||||
} else if (billboardMode == BillboardMode::FULL) {
|
||||
// use the referencial from the avatar, y isn't always up
|
||||
glm::vec3 avatarUP = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;
|
||||
|
@ -2470,12 +2478,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
// make sure s is not NaN for any component
|
||||
if (glm::length2(s) > 0.0f) {
|
||||
return glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP)));
|
||||
glm::quat result = glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP))) * rotation;
|
||||
if (rotate90x) {
|
||||
result *= ROTATE_90X;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return rotation;
|
||||
});
|
||||
EntityItem::setPrimaryViewFrustumPositionOperator([this]() {
|
||||
BillboardModeHelpers::setPrimaryViewFrustumPositionOperator([this]() {
|
||||
ViewFrustum viewFrustum;
|
||||
copyViewFrustum(viewFrustum);
|
||||
return viewFrustum.getPosition();
|
||||
|
@ -5196,6 +5208,7 @@ void getCpuUsage(vec3& systemAndUser) {
|
|||
void setupCpuMonitorThread() {
|
||||
initCpuUsage();
|
||||
auto cpuMonitorThread = QThread::currentThread();
|
||||
setThreadName("CPU Monitor Thread");
|
||||
|
||||
QTimer* timer = new QTimer();
|
||||
timer->setInterval(50);
|
||||
|
@ -7180,6 +7193,10 @@ void Application::updateWindowTitle() const {
|
|||
QString buildVersion = " - Vircadia - "
|
||||
+ (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? QString("Version") : QString("Build"))
|
||||
+ " " + applicationVersion();
|
||||
|
||||
if (BuildInfo::RELEASE_NAME != "") {
|
||||
buildVersion += " - " + BuildInfo::RELEASE_NAME;
|
||||
}
|
||||
|
||||
QString connectionStatus = isInErrorState ? " (ERROR CONNECTING)" :
|
||||
nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED)";
|
||||
|
|
|
@ -61,7 +61,6 @@ void Bookmarks::deleteBookmark(const QString& bookmarkName) {
|
|||
void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QVariant& bookmark) {
|
||||
Menu* menubar = Menu::getInstance();
|
||||
if (contains(bookmarkName)) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
ModalDialogListener* dlg = OffscreenUi::asyncWarning("Duplicate Bookmark",
|
||||
"The bookmark name you entered already exists in your list.",
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
|
|
|
@ -509,7 +509,7 @@ Menu::Menu() {
|
|||
|
||||
action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MaterialProceduralShaders, 0, false);
|
||||
connect(action, &QAction::triggered, [action] {
|
||||
MeshPartPayload::enableMaterialProceduralShaders = action->isChecked();
|
||||
ModelMeshPartPayload::enableMaterialProceduralShaders = action->isChecked();
|
||||
});
|
||||
|
||||
{
|
||||
|
|
|
@ -767,6 +767,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
|
|||
glm::vec3 rayDirectionInv = { rayDirection.x != 0.0f ? 1.0f / rayDirection.x : INFINITY,
|
||||
rayDirection.y != 0.0f ? 1.0f / rayDirection.y : INFINITY,
|
||||
rayDirection.z != 0.0f ? 1.0f / rayDirection.z : INFINITY };
|
||||
glm::vec3 viewFrustumPos = BillboardModeHelpers::getPrimaryViewFrustumPosition();
|
||||
|
||||
for (auto &hit : physicsResults) {
|
||||
auto avatarID = hit._intersectWithAvatar;
|
||||
|
@ -842,7 +843,8 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
|
|||
BoxFace subMeshFace = BoxFace::UNKNOWN_FACE;
|
||||
glm::vec3 subMeshSurfaceNormal;
|
||||
QVariantMap subMeshExtraInfo;
|
||||
if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, subMeshDistance, subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) {
|
||||
if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, viewFrustumPos, subMeshDistance,
|
||||
subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) {
|
||||
rayAvatarResult._distance = subMeshDistance;
|
||||
rayAvatarResult._intersectionPoint = ray.origin + subMeshDistance * rayDirection;
|
||||
rayAvatarResult._intersectionNormal = subMeshSurfaceNormal;
|
||||
|
@ -932,6 +934,7 @@ ParabolaToAvatarIntersectionResult AvatarManager::findParabolaIntersectionVector
|
|||
std::sort(sortedAvatars.begin(), sortedAvatars.end(), comparator);
|
||||
}
|
||||
|
||||
glm::vec3 viewFrustumPos = BillboardModeHelpers::getPrimaryViewFrustumPosition();
|
||||
for (auto it = sortedAvatars.begin(); it != sortedAvatars.end(); ++it) {
|
||||
const SortedAvatar& sortedAvatar = *it;
|
||||
// We can exit once avatarCapsuleDistance > bestDistance
|
||||
|
@ -944,7 +947,7 @@ ParabolaToAvatarIntersectionResult AvatarManager::findParabolaIntersectionVector
|
|||
glm::vec3 surfaceNormal;
|
||||
QVariantMap extraInfo;
|
||||
SkeletonModelPointer avatarModel = sortedAvatar.second->getSkeletonModel();
|
||||
if (avatarModel->findParabolaIntersectionAgainstSubMeshes(pick.origin, pick.velocity, pick.acceleration, parabolicDistance, face, surfaceNormal, extraInfo, true)) {
|
||||
if (avatarModel->findParabolaIntersectionAgainstSubMeshes(pick.origin, pick.velocity, pick.acceleration, viewFrustumPos, parabolicDistance, face, surfaceNormal, extraInfo, true)) {
|
||||
if (parabolicDistance < result.parabolicDistance) {
|
||||
result.intersects = true;
|
||||
result.avatarID = sortedAvatar.second->getID();
|
||||
|
|
|
@ -58,7 +58,9 @@ bool AvatarPackager::open() {
|
|||
|
||||
if (tablet->getToolbarMode()) {
|
||||
static const QUrl url{ "hifi/AvatarPackagerWindow.qml" };
|
||||
DependencyManager::get<OffscreenUi>()->show(url, "AvatarPackager", packageModelDialogCreated);
|
||||
if (auto offscreenUI = DependencyManager::get<OffscreenUi>()) {
|
||||
offscreenUI->show(url, "AvatarPackager", packageModelDialogCreated);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -283,15 +283,16 @@ class MyAvatar : public Avatar {
|
|||
* the value.</p>
|
||||
* @property {number} analogPlusSprintSpeed - The sprint (run) speed of your avatar for the "AnalogPlus" control scheme.
|
||||
* @property {MyAvatar.SitStandModelType} userRecenterModel - Controls avatar leaning and recentering behavior.
|
||||
* @property {number} isInSittingState - <code>true</code> if the user wearing the HMD is determined to be sitting
|
||||
* (avatar leaning is disabled, recentering is enabled), <code>false</code> if the user wearing the HMD is
|
||||
* determined to be standing (avatar leaning is enabled, and avatar recenters if it leans too far).
|
||||
* If <code>userRecenterModel == 2</code> (i.e., "auto") the property value automatically updates as the user sits
|
||||
* or stands, unless <code>isSitStandStateLocked == true</code>. Setting the property value overrides the current
|
||||
* sitting / standing state, which is updated when the user next sits or stands unless
|
||||
* <code>isSitStandStateLocked == true</code>.
|
||||
* <p class="important">Deprecated: This property is deprecated and will be removed.</p>
|
||||
* @property {boolean} isInSittingState - <code>true</code> if the user wearing the HMD is determined to be sitting;
|
||||
* <code>false</code> if the user wearing the HMD is determined to be standing. This can affect whether the avatar
|
||||
* is allowed to stand, lean or recenter its footing, depending on user preferences.
|
||||
* The property value automatically updates as the user sits or stands. Setting the property value overrides the current
|
||||
* sitting / standing state, which is updated when the user next sits or stands.
|
||||
* @property {boolean} isSitStandStateLocked - <code>true</code> to lock the avatar sitting/standing state, i.e., use this
|
||||
* to disable automatically changing state.
|
||||
* <p class="important">Deprecated: This property is deprecated and will be removed.
|
||||
* See also: <code>getUserRecenterModel</code> and <code>setUserRecenterModel</code>.</p>
|
||||
* @property {boolean} allowTeleporting - <code>true</code> if teleporting is enabled in the Interface settings,
|
||||
* <code>false</code> if it isn't. <em>Read-only.</em>
|
||||
*
|
||||
|
@ -413,8 +414,8 @@ class MyAvatar : public Avatar {
|
|||
Q_PROPERTY(float walkBackwardSpeed READ getWalkBackwardSpeed WRITE setWalkBackwardSpeed NOTIFY walkBackwardSpeedChanged);
|
||||
Q_PROPERTY(float sprintSpeed READ getSprintSpeed WRITE setSprintSpeed NOTIFY sprintSpeedChanged);
|
||||
Q_PROPERTY(bool isInSittingState READ getIsInSittingState WRITE setIsInSittingState);
|
||||
Q_PROPERTY(MyAvatar::SitStandModelType userRecenterModel READ getUserRecenterModel WRITE setUserRecenterModel);
|
||||
Q_PROPERTY(bool isSitStandStateLocked READ getIsSitStandStateLocked WRITE setIsSitStandStateLocked);
|
||||
Q_PROPERTY(MyAvatar::SitStandModelType userRecenterModel READ getUserRecenterModel WRITE setUserRecenterModel); // Deprecated
|
||||
Q_PROPERTY(bool isSitStandStateLocked READ getIsSitStandStateLocked WRITE setIsSitStandStateLocked); // Deprecated
|
||||
Q_PROPERTY(bool allowTeleporting READ getAllowTeleporting)
|
||||
|
||||
const QString DOMINANT_LEFT_HAND = "left";
|
||||
|
@ -519,6 +520,7 @@ public:
|
|||
|
||||
/**jsdoc
|
||||
* <p>Specifies different avatar leaning and recentering behaviors.</p>
|
||||
* <p class="important">Deprecated: This type is deprecated and will be removed.</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Name</th><th>Description</th></tr>
|
||||
|
@ -549,6 +551,29 @@ public:
|
|||
};
|
||||
Q_ENUM(SitStandModelType)
|
||||
|
||||
// Note: The option strings in setupPreferences (PreferencesDialog.cpp) must match this order.
|
||||
enum class AllowAvatarStandingPreference : uint {
|
||||
WhenUserIsStanding,
|
||||
Always,
|
||||
Count,
|
||||
Default = Always
|
||||
};
|
||||
Q_ENUM(AllowAvatarStandingPreference)
|
||||
|
||||
// Note: The option strings in setupPreferences (PreferencesDialog.cpp) must match this order.
|
||||
enum class AllowAvatarLeaningPreference : uint {
|
||||
WhenUserIsStanding,
|
||||
Always,
|
||||
Never,
|
||||
AlwaysNoRecenter, // experimental
|
||||
Count,
|
||||
Default = WhenUserIsStanding
|
||||
};
|
||||
Q_ENUM(AllowAvatarLeaningPreference)
|
||||
|
||||
static const std::array<QString, (uint)AllowAvatarStandingPreference::Count> allowAvatarStandingPreferenceStrings;
|
||||
static const std::array<QString, (uint)AllowAvatarLeaningPreference::Count> allowAvatarLeaningPreferenceStrings;
|
||||
|
||||
explicit MyAvatar(QThread* thread);
|
||||
virtual ~MyAvatar();
|
||||
|
||||
|
@ -1417,7 +1442,6 @@ public:
|
|||
controller::Pose getControllerPoseInSensorFrame(controller::Action action) const;
|
||||
controller::Pose getControllerPoseInWorldFrame(controller::Action action) const;
|
||||
controller::Pose getControllerPoseInAvatarFrame(controller::Action action) const;
|
||||
glm::quat getOffHandRotation() const;
|
||||
|
||||
bool hasDriveInput() const;
|
||||
|
||||
|
@ -1596,7 +1620,7 @@ public:
|
|||
* @function MyAvatar.getAvatarScale
|
||||
* @returns {number} The target scale for the avatar, range <code>0.005</code> – <code>1000.0</code>.
|
||||
*/
|
||||
Q_INVOKABLE float getAvatarScale();
|
||||
Q_INVOKABLE float getAvatarScale() const;
|
||||
|
||||
/**jsdoc
|
||||
* Sets the target scale of the avatar. The target scale is the desired scale of the avatar without any restrictions on
|
||||
|
@ -1709,7 +1733,7 @@ public:
|
|||
|
||||
// derive avatar body position and orientation from the current HMD Sensor location.
|
||||
// results are in sensor frame (-z forward)
|
||||
glm::mat4 deriveBodyFromHMDSensor() const;
|
||||
glm::mat4 deriveBodyFromHMDSensor(const bool forceFollowYPos = false) const;
|
||||
|
||||
glm::mat4 getSpine2RotationRigSpace() const;
|
||||
|
||||
|
@ -1753,10 +1777,14 @@ public:
|
|||
bool getIsInWalkingState() const;
|
||||
void setIsInSittingState(bool isSitting);
|
||||
bool getIsInSittingState() const;
|
||||
void setUserRecenterModel(MyAvatar::SitStandModelType modelName);
|
||||
MyAvatar::SitStandModelType getUserRecenterModel() const;
|
||||
void setIsSitStandStateLocked(bool isLocked);
|
||||
bool getIsSitStandStateLocked() const;
|
||||
void setUserRecenterModel(MyAvatar::SitStandModelType modelName); // Deprecated, will be removed.
|
||||
MyAvatar::SitStandModelType getUserRecenterModel() const; // Deprecated, will be removed.
|
||||
void setIsSitStandStateLocked(bool isLocked); // Deprecated, will be removed.
|
||||
bool getIsSitStandStateLocked() const; // Deprecated, will be removed.
|
||||
void setAllowAvatarStandingPreference(const AllowAvatarStandingPreference preference);
|
||||
AllowAvatarStandingPreference getAllowAvatarStandingPreference() const;
|
||||
void setAllowAvatarLeaningPreference(const AllowAvatarLeaningPreference preference);
|
||||
AllowAvatarLeaningPreference getAllowAvatarLeaningPreference() const;
|
||||
void setWalkSpeed(float value);
|
||||
float getWalkSpeed() const;
|
||||
void setWalkBackwardSpeed(float value);
|
||||
|
@ -1989,6 +2017,10 @@ public:
|
|||
glm::vec3 getLookAtPivotPoint();
|
||||
glm::vec3 getCameraEyesPosition(float deltaTime);
|
||||
bool isJumping();
|
||||
bool getHMDCrouchRecenterEnabled() const;
|
||||
bool isAllowedToLean() const;
|
||||
bool areFeetTracked() const { return _isBodyPartTracked._feet; }; // Determine if the feet are under direct control.
|
||||
bool areHipsTracked() const { return _isBodyPartTracked._hips; }; // Determine if the hips are under direct control.
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -2709,6 +2741,16 @@ private:
|
|||
bool _isBraking { false };
|
||||
bool _isAway { false };
|
||||
|
||||
// Indicates which parts of the body are under direct control (tracked).
|
||||
struct {
|
||||
bool _feet { false }; // Left or right foot.
|
||||
bool _feetPreviousUpdate{ false };// Value of _feet on the previous update.
|
||||
bool _hips{ false };
|
||||
bool _leftHand{ false };
|
||||
bool _rightHand{ false };
|
||||
bool _head{ false };
|
||||
} _isBodyPartTracked;
|
||||
|
||||
float _boomLength { ZOOM_DEFAULT };
|
||||
float _yawSpeed; // degrees/sec
|
||||
float _pitchSpeed; // degrees/sec
|
||||
|
@ -2791,6 +2833,7 @@ private:
|
|||
void resetLookAtRotation(const glm::vec3& avatarPosition, const glm::quat& avatarOrientation);
|
||||
void resetPointAt();
|
||||
static glm::vec3 aimToBlendValues(const glm::vec3& aimVector, const glm::quat& frameOrientation);
|
||||
void centerBodyInternal(const bool forceFollowYPos = false);
|
||||
|
||||
// Avatar Preferences
|
||||
QUrl _fullAvatarURLFromPreferences;
|
||||
|
@ -2841,26 +2884,21 @@ private:
|
|||
struct FollowHelper {
|
||||
FollowHelper();
|
||||
|
||||
enum FollowType {
|
||||
Rotation = 0,
|
||||
Horizontal,
|
||||
Vertical,
|
||||
NumFollowTypes
|
||||
};
|
||||
float _timeRemaining[NumFollowTypes];
|
||||
CharacterController::FollowTimePerType _timeRemaining;
|
||||
|
||||
void deactivate();
|
||||
void deactivate(FollowType type);
|
||||
void activate();
|
||||
void activate(FollowType type);
|
||||
void deactivate(CharacterController::FollowType type);
|
||||
void activate(CharacterController::FollowType type, const bool snapFollow);
|
||||
bool isActive() const;
|
||||
bool isActive(FollowType followType) const;
|
||||
float getMaxTimeRemaining() const;
|
||||
bool isActive(CharacterController::FollowType followType) const;
|
||||
void decrementTimeRemaining(float dt);
|
||||
bool shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const;
|
||||
bool shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix, bool& shouldSnapOut) const;
|
||||
bool shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const;
|
||||
bool shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const;
|
||||
bool shouldActivateHorizontalCG(MyAvatar& myAvatar) const;
|
||||
bool shouldActivateHorizontal(const MyAvatar& myAvatar,
|
||||
const glm::mat4& desiredBodyMatrix,
|
||||
const glm::mat4& currentBodyMatrix,
|
||||
bool& resetModeOut,
|
||||
bool& goToWalkingStateOut) const;
|
||||
void prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& bodySensorMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput);
|
||||
glm::mat4 postPhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix);
|
||||
bool getForceActivateRotation() const;
|
||||
|
@ -2871,16 +2909,23 @@ private:
|
|||
void setForceActivateHorizontal(bool val);
|
||||
bool getToggleHipsFollowing() const;
|
||||
void setToggleHipsFollowing(bool followHead);
|
||||
bool _squatDetected { false };
|
||||
std::atomic<bool> _forceActivateRotation { false };
|
||||
std::atomic<bool> _forceActivateVertical { false };
|
||||
std::atomic<bool> _forceActivateHorizontal { false };
|
||||
std::atomic<bool> _toggleHipsFollowing { true };
|
||||
|
||||
private:
|
||||
bool shouldActivateHorizontal_userSitting(const MyAvatar& myAvatar,
|
||||
const glm::mat4& desiredBodyMatrix,
|
||||
const glm::mat4& currentBodyMatrix) const;
|
||||
bool shouldActivateHorizontal_userStanding(const MyAvatar& myAvatar,
|
||||
bool& resetModeOut,
|
||||
bool& goToWalkingStateOut) const;
|
||||
};
|
||||
|
||||
FollowHelper _follow;
|
||||
|
||||
bool isFollowActive(FollowHelper::FollowType followType) const;
|
||||
bool isFollowActive(CharacterController::FollowType followType) const;
|
||||
|
||||
bool _goToPending { false };
|
||||
bool _physicsSafetyPending { false };
|
||||
|
@ -2922,6 +2967,9 @@ private:
|
|||
|
||||
bool _centerOfGravityModelEnabled { true };
|
||||
bool _hmdLeanRecenterEnabled { true };
|
||||
bool _hmdCrouchRecenterEnabled {
|
||||
true
|
||||
}; // Is MyAvatar allowed to recenter vertically (stand) when the user is sitting in the real world.
|
||||
bool _sprint { false };
|
||||
|
||||
AnimPose _prePhysicsRoomPose;
|
||||
|
@ -2953,7 +3001,6 @@ private:
|
|||
ThreadSafeValueCache<float> _userHeight { DEFAULT_AVATAR_HEIGHT };
|
||||
float _averageUserHeightSensorSpace { _userHeight.get() };
|
||||
bool _sitStandStateChange { false };
|
||||
ThreadSafeValueCache<bool> _lockSitStandState { false };
|
||||
|
||||
// max unscaled forward movement speed
|
||||
ThreadSafeValueCache<float> _defaultWalkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED };
|
||||
|
@ -2969,9 +3016,13 @@ private:
|
|||
float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR };
|
||||
bool _isInWalkingState { false };
|
||||
ThreadSafeValueCache<bool> _isInSittingState { false };
|
||||
ThreadSafeValueCache<MyAvatar::SitStandModelType> _userRecenterModel { MyAvatar::SitStandModelType::Auto };
|
||||
ThreadSafeValueCache<MyAvatar::AllowAvatarStandingPreference> _allowAvatarStandingPreference{
|
||||
MyAvatar::AllowAvatarStandingPreference::Default
|
||||
}; // The user preference of when MyAvatar may stand.
|
||||
ThreadSafeValueCache<MyAvatar::AllowAvatarLeaningPreference> _allowAvatarLeaningPreference{
|
||||
MyAvatar::AllowAvatarLeaningPreference::Default
|
||||
}; // The user preference of when MyAvatar may lean.
|
||||
float _sitStandStateTimer { 0.0f };
|
||||
float _squatTimer { 0.0f };
|
||||
float _tippingPoint { _userHeight.get() };
|
||||
|
||||
// load avatar scripts once when rig is ready
|
||||
|
@ -3012,7 +3063,8 @@ private:
|
|||
Setting::Handle<int> _controlSchemeIndexSetting;
|
||||
std::vector<Setting::Handle<QUuid>> _avatarEntityIDSettings;
|
||||
std::vector<Setting::Handle<QByteArray>> _avatarEntityDataSettings;
|
||||
Setting::Handle<QString> _userRecenterModelSetting;
|
||||
Setting::Handle<QString> _allowAvatarStandingPreferenceSetting;
|
||||
Setting::Handle<QString> _allowAvatarLeaningPreferenceSetting;
|
||||
|
||||
// AvatarEntities stuff:
|
||||
// We cache the "map of unfortunately-formatted-binary-blobs" because they are expensive to compute
|
||||
|
|
|
@ -26,7 +26,9 @@ void MyCharacterController::RayShotgunResult::reset() {
|
|||
walkable = true;
|
||||
}
|
||||
|
||||
MyCharacterController::MyCharacterController(std::shared_ptr<MyAvatar> avatar) {
|
||||
MyCharacterController::MyCharacterController(std::shared_ptr<MyAvatar> avatar,
|
||||
const FollowTimePerType& followTimeRemainingPerType) :
|
||||
CharacterController(followTimeRemainingPerType) {
|
||||
|
||||
assert(avatar);
|
||||
_avatar = avatar;
|
||||
|
|
|
@ -23,7 +23,7 @@ class DetailedMotionState;
|
|||
|
||||
class MyCharacterController : public CharacterController {
|
||||
public:
|
||||
explicit MyCharacterController(std::shared_ptr<MyAvatar> avatar);
|
||||
explicit MyCharacterController(std::shared_ptr<MyAvatar> avatar, const FollowTimePerType& followTimeRemainingPerType);
|
||||
~MyCharacterController ();
|
||||
|
||||
void addToWorld() override;
|
||||
|
|
|
@ -65,13 +65,21 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Use the center-of-gravity model if the user and the avatar are standing, unless flying or walking.
|
||||
// If artificial standing is disabled, use center-of-gravity regardless of the user's sit/stand state.
|
||||
bool useCenterOfGravityModel =
|
||||
myAvatar->getCenterOfGravityModelEnabled() && !isFlying && !myAvatar->getIsInWalkingState() &&
|
||||
(!myAvatar->getHMDCrouchRecenterEnabled() || !myAvatar->getIsInSittingState()) &&
|
||||
myAvatar->getHMDLeanRecenterEnabled() &&
|
||||
(myAvatar->getAllowAvatarLeaningPreference() != MyAvatar::AllowAvatarLeaningPreference::AlwaysNoRecenter);
|
||||
|
||||
glm::mat4 hipsMat;
|
||||
if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying && !(myAvatar->getIsInWalkingState()) && !(myAvatar->getIsInSittingState()) && myAvatar->getHMDLeanRecenterEnabled()) {
|
||||
if (useCenterOfGravityModel) {
|
||||
// then we use center of gravity model
|
||||
hipsMat = myAvatar->deriveBodyUsingCgModel();
|
||||
} else {
|
||||
// otherwise use the default of putting the hips under the head
|
||||
hipsMat = myAvatar->deriveBodyFromHMDSensor();
|
||||
hipsMat = myAvatar->deriveBodyFromHMDSensor(true);
|
||||
}
|
||||
glm::vec3 hipsPos = extractTranslation(hipsMat);
|
||||
glm::quat hipsRot = glmExtractRotation(hipsMat);
|
||||
|
@ -82,7 +90,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
|
|||
|
||||
// dampen hips rotation, by mixing it with the avatar orientation in sensor space
|
||||
// turning this off for center of gravity model because it is already mixed in there
|
||||
if (!(myAvatar->getCenterOfGravityModelEnabled())) {
|
||||
if (!useCenterOfGravityModel) {
|
||||
const float MIX_RATIO = 0.5f;
|
||||
hipsRot = safeLerp(glmExtractRotation(avatarToSensorMat), hipsRot, MIX_RATIO);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID };
|
|||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); }
|
||||
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
|
||||
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { return Item::Bound(); }
|
||||
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
|
||||
PerformanceTimer perfTimer("worldBox");
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff);
|
||||
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff);
|
||||
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args);
|
||||
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args);
|
||||
}
|
||||
|
||||
|
|
|
@ -415,7 +415,7 @@ gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabo
|
|||
|
||||
for (auto& key : keys) {
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setDepthTest(true, !std::get<0>(key), gpu::LESS_EQUAL);
|
||||
if (std::get<0>(key)) {
|
||||
PrepareStencil::testMask(*state);
|
||||
} else {
|
||||
|
@ -462,9 +462,9 @@ namespace render {
|
|||
template <> const ItemKey payloadGetKey(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload) {
|
||||
return payload->getKey();
|
||||
}
|
||||
template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload) {
|
||||
template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload, RenderArgs* args) {
|
||||
if (payload) {
|
||||
return payload->getBound();
|
||||
return payload->getBound(args);
|
||||
}
|
||||
return Item::Bound();
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
|
||||
void render(RenderArgs* args);
|
||||
render::Item::Bound& editBound() { return _bound; }
|
||||
const render::Item::Bound& getBound() { return _bound; }
|
||||
const render::Item::Bound& getBound(RenderArgs* args) { return _bound; }
|
||||
render::ItemKey getKey() const { return _key; }
|
||||
|
||||
void setVisible(bool visible);
|
||||
|
@ -128,7 +128,7 @@ private:
|
|||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload);
|
||||
template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload);
|
||||
template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload, RenderArgs* args);
|
||||
template <> void payloadRender(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload, RenderArgs* args);
|
||||
template <> const ShapeKey shapeGetShapeKey(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload);
|
||||
}
|
||||
|
|
|
@ -76,8 +76,13 @@ void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping,
|
|||
"Use the field below to place your file in a specific folder or to rename it. "
|
||||
"Specifying a new folder name will automatically create that folder for you.";
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto result = offscreenUi->inputDialog(OffscreenUi::ICON_INFORMATION, "Specify Asset Path",
|
||||
auto offscreenUI = DependencyManager::get<OffscreenUi>();
|
||||
if (!offscreenUI) {
|
||||
completedCallback.call({ -1 });
|
||||
return;
|
||||
}
|
||||
|
||||
auto result = offscreenUI->inputDialog(OffscreenUi::ICON_INFORMATION, "Specify Asset Path",
|
||||
dropEvent ? dropHelpText : helpText, mapping);
|
||||
|
||||
if (!result.isValid() || result.toString() == "") {
|
||||
|
@ -94,7 +99,7 @@ void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping,
|
|||
// Check for override
|
||||
if (isKnownMapping(mapping)) {
|
||||
auto message = mapping + "\n" + "This file already exists. Do you want to overwrite it?";
|
||||
auto button = offscreenUi->messageBox(OffscreenUi::ICON_QUESTION, "Overwrite File", message,
|
||||
auto button = offscreenUI->messageBox(OffscreenUi::ICON_QUESTION, "Overwrite File", message,
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if (button == QMessageBox::No) {
|
||||
completedCallback.call({ -1 });
|
||||
|
|
|
@ -99,11 +99,16 @@ void DesktopScriptingInterface::setHUDAlpha(float alpha) {
|
|||
}
|
||||
|
||||
void DesktopScriptingInterface::show(const QString& path, const QString& title) {
|
||||
auto offscreenUI = DependencyManager::get<OffscreenUi>();
|
||||
if (!offscreenUI) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "show", Qt::QueuedConnection, Q_ARG(QString, path), Q_ARG(QString, title));
|
||||
return;
|
||||
}
|
||||
DependencyManager::get<OffscreenUi>()->show(path, title);
|
||||
offscreenUI->show(path, title);
|
||||
}
|
||||
|
||||
InteractiveWindowPointer DesktopScriptingInterface::createWindow(const QString& sourceUrl, const QVariantMap& properties) {
|
||||
|
|
|
@ -96,8 +96,9 @@ bool HMDScriptingInterface::shouldShowHandControllers() const {
|
|||
|
||||
void HMDScriptingInterface::activateHMDHandMouse() {
|
||||
QWriteLocker lock(&_hmdHandMouseLock);
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", true);
|
||||
if (auto offscreenUI = DependencyManager::get<OffscreenUi>()) {
|
||||
offscreenUI->getDesktop()->setProperty("hmdHandMouseActive", true);
|
||||
}
|
||||
_hmdHandMouseCount++;
|
||||
}
|
||||
|
||||
|
@ -105,8 +106,9 @@ void HMDScriptingInterface::deactivateHMDHandMouse() {
|
|||
QWriteLocker lock(&_hmdHandMouseLock);
|
||||
_hmdHandMouseCount = std::max(_hmdHandMouseCount - 1, 0);
|
||||
if (_hmdHandMouseCount == 0) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", false);
|
||||
if (auto offscreenUI = DependencyManager::get<OffscreenUi>()) {
|
||||
offscreenUI->getDesktop()->setProperty("hmdHandMouseActive", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ PlatformInfoScriptingInterface::PlatformTier PlatformInfoScriptingInterface::get
|
|||
}
|
||||
|
||||
QStringList PlatformInfoScriptingInterface::getPlatformTierNames() {
|
||||
static const QStringList platformTierNames = { "UNKNWON", "LOW", "MID", "HIGH" };
|
||||
static const QStringList platformTierNames = { "UNKNOWN", "LOW", "MID", "HIGH" };
|
||||
return platformTierNames;
|
||||
}
|
||||
|
||||
|
|
|
@ -199,9 +199,9 @@ void WindowScriptingInterface::setInterstitialModeEnabled(bool enableInterstitia
|
|||
DependencyManager::get<NodeList>()->getDomainHandler().setInterstitialModeEnabled(enableInterstitialMode);
|
||||
}
|
||||
|
||||
bool WindowScriptingInterface::isPointOnDesktopWindow(QVariant point) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
return offscreenUi->isPointOnDesktopWindow(point);
|
||||
bool WindowScriptingInterface::isPointOnDesktopWindow(QVariant point) {
|
||||
auto offscreenUI = DependencyManager::get<OffscreenUi>();
|
||||
return offscreenUI ? offscreenUI->isPointOnDesktopWindow(point) : false;
|
||||
}
|
||||
|
||||
/// Makes sure that the reticle is visible, use this in blocking forms that require a reticle and
|
||||
|
@ -553,12 +553,14 @@ int WindowScriptingInterface::openMessageBox(QString title, QString text, int bu
|
|||
* @typedef {number} Window.MessageBoxButton
|
||||
*/
|
||||
int WindowScriptingInterface::createMessageBox(QString title, QString text, int buttons, int defaultButton) {
|
||||
auto messageBox = DependencyManager::get<OffscreenUi>()->createMessageBox(OffscreenUi::ICON_INFORMATION, title, text,
|
||||
static_cast<QFlags<QMessageBox::StandardButton>>(buttons), static_cast<QMessageBox::StandardButton>(defaultButton));
|
||||
connect(messageBox, SIGNAL(selected(int)), this, SLOT(onMessageBoxSelected(int)));
|
||||
if (auto offscreenUI = DependencyManager::get<OffscreenUi>()) {
|
||||
auto messageBox = offscreenUI->createMessageBox(OffscreenUi::ICON_INFORMATION, title, text,
|
||||
static_cast<QFlags<QMessageBox::StandardButton>>(buttons), static_cast<QMessageBox::StandardButton>(defaultButton));
|
||||
connect(messageBox, SIGNAL(selected(int)), this, SLOT(onMessageBoxSelected(int)));
|
||||
|
||||
_lastMessageBoxID += 1;
|
||||
_messageBoxes.insert(_lastMessageBoxID, messageBox);
|
||||
_lastMessageBoxID += 1;
|
||||
_messageBoxes.insert(_lastMessageBoxID, messageBox);
|
||||
}
|
||||
|
||||
return _lastMessageBoxID;
|
||||
}
|
||||
|
@ -646,13 +648,17 @@ void WindowScriptingInterface::setActiveDisplayPlugin(int index) {
|
|||
}
|
||||
|
||||
void WindowScriptingInterface::openWebBrowser(const QString& url) {
|
||||
auto offscreenUI = DependencyManager::get<OffscreenUi>();
|
||||
if (!offscreenUI) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "openWebBrowser", Q_ARG(const QString&, url));
|
||||
return;
|
||||
}
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
offscreenUI->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
if (!url.isEmpty()) {
|
||||
newObject->setProperty("url", url);
|
||||
}
|
||||
|
|
|
@ -67,13 +67,13 @@ void AnimStats::updateStats(bool force) {
|
|||
|
||||
// print if we are recentering or not.
|
||||
_recenterText = "Recenter: ";
|
||||
if (myAvatar->isFollowActive(MyAvatar::FollowHelper::Rotation)) {
|
||||
if (myAvatar->isFollowActive(CharacterController::FollowType::Rotation)) {
|
||||
_recenterText += "Rotation ";
|
||||
}
|
||||
if (myAvatar->isFollowActive(MyAvatar::FollowHelper::Horizontal)) {
|
||||
if (myAvatar->isFollowActive(CharacterController::FollowType::Horizontal)) {
|
||||
_recenterText += "Horizontal ";
|
||||
}
|
||||
if (myAvatar->isFollowActive(MyAvatar::FollowHelper::Vertical)) {
|
||||
if (myAvatar->isFollowActive(CharacterController::FollowType::Vertical)) {
|
||||
_recenterText += "Vertical ";
|
||||
}
|
||||
emit recenterTextChanged();
|
||||
|
|
|
@ -100,10 +100,10 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) {
|
|||
// threads, we need to use a sync object to deteremine when
|
||||
// the current UI texture is no longer being read from, and only
|
||||
// then release it back to the UI for re-use
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto offscreenUI = DependencyManager::get<OffscreenUi>();
|
||||
|
||||
OffscreenQmlSurface::TextureAndFence newTextureAndFence;
|
||||
bool newTextureAvailable = offscreenUi->fetchTexture(newTextureAndFence);
|
||||
bool newTextureAvailable = offscreenUI ? offscreenUI->fetchTexture(newTextureAndFence) : false;
|
||||
if (newTextureAvailable) {
|
||||
_uiTexture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second);
|
||||
}
|
||||
|
|
|
@ -362,10 +362,11 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
|
|||
object->setObjectName("InteractiveWindow");
|
||||
object->setProperty(SOURCE_PROPERTY, sourceURL);
|
||||
};
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
|
||||
// Build the event bridge and wrapper on the main thread
|
||||
offscreenUi->loadInNewContext(CONTENT_WINDOW_QML, objectInitLambda, contextInitLambda);
|
||||
if (auto offscreenUI = DependencyManager::get<OffscreenUi>()) {
|
||||
// Build the event bridge and wrapper on the main thread
|
||||
offscreenUI->loadInNewContext(CONTENT_WINDOW_QML, objectInitLambda, contextInitLambda);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -422,40 +422,40 @@ void setupPreferences() {
|
|||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [myAvatar]()->int {
|
||||
switch (myAvatar->getUserRecenterModel()) {
|
||||
case MyAvatar::SitStandModelType::Auto:
|
||||
default:
|
||||
return 0;
|
||||
case MyAvatar::SitStandModelType::ForceSit:
|
||||
return 1;
|
||||
case MyAvatar::SitStandModelType::ForceStand:
|
||||
return 2;
|
||||
case MyAvatar::SitStandModelType::DisableHMDLean:
|
||||
return 3;
|
||||
}
|
||||
IntPreference::Getter getter = [myAvatar]() -> int {
|
||||
return static_cast<int>(myAvatar->getAllowAvatarStandingPreference());
|
||||
};
|
||||
auto setter = [myAvatar](int value) {
|
||||
switch (value) {
|
||||
case 0:
|
||||
default:
|
||||
myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::Auto);
|
||||
break;
|
||||
case 1:
|
||||
myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::ForceSit);
|
||||
break;
|
||||
case 2:
|
||||
myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::ForceStand);
|
||||
break;
|
||||
case 3:
|
||||
myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::DisableHMDLean);
|
||||
break;
|
||||
}
|
||||
|
||||
IntPreference::Setter setter = [myAvatar](const int& value) {
|
||||
myAvatar->setAllowAvatarStandingPreference(static_cast<MyAvatar::AllowAvatarStandingPreference>(value));
|
||||
};
|
||||
auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Auto / Force Sit / Force Stand / Disable Recenter", getter, setter);
|
||||
|
||||
auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Allow my avatar to stand", getter, setter);
|
||||
QStringList items;
|
||||
items << "Auto - turns on avatar leaning when standing in real world" << "Seated - disables all avatar leaning while sitting in real world" << "Standing - enables avatar leaning while sitting in real world" << "Disabled - allows avatar sitting on the floor [Experimental]";
|
||||
preference->setHeading("Avatar leaning behavior");
|
||||
items << "When I'm standing"
|
||||
<< "Always"; // Must match the order in MyAvatar::AllowAvatarStandingPreference.
|
||||
assert(items.size() == static_cast<uint>(MyAvatar::AllowAvatarStandingPreference::Count));
|
||||
preference->setHeading("Allow my avatar to stand:");
|
||||
preference->setItems(items);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
IntPreference::Getter getter = [myAvatar]() -> int {
|
||||
return static_cast<int>(myAvatar->getAllowAvatarLeaningPreference());
|
||||
};
|
||||
|
||||
IntPreference::Setter setter = [myAvatar](const int& value) {
|
||||
myAvatar->setAllowAvatarLeaningPreference(static_cast<MyAvatar::AllowAvatarLeaningPreference>(value));
|
||||
};
|
||||
|
||||
auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Allow my avatar to lean", getter, setter);
|
||||
QStringList items;
|
||||
items << "When I'm standing"
|
||||
<< "Always"
|
||||
<< "Never"
|
||||
<< "Always, no recenter (Experimental)"; // Must match the order in MyAvatar::AllowAvatarLeaningPreference.
|
||||
assert(items.size() == static_cast<uint>(MyAvatar::AllowAvatarLeaningPreference::Count));
|
||||
preference->setHeading("Allow my avatar to lean:");
|
||||
preference->setItems(items);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
|
|
@ -248,9 +248,9 @@ private: \
|
|||
* <em>Read-only.</em>
|
||||
* @property {string} lodStatus - Description of the current LOD.
|
||||
* <em>Read-only.</em>
|
||||
* @property {string} numEntityUpdates - The number of entity updates that happened last frame.
|
||||
* @property {number} numEntityUpdates - The number of entity updates that happened last frame.
|
||||
* <em>Read-only.</em>
|
||||
* @property {string} numNeededEntityUpdates - The total number of entity updates scheduled for last frame.
|
||||
* @property {number} numNeededEntityUpdates - The total number of entity updates scheduled for last frame.
|
||||
* <em>Read-only.</em>
|
||||
* @property {string} timingStats - Details of the average time (ms) spent in and number of calls made to different parts of
|
||||
* the code. Provided only if <code>timingExpanded</code> is <code>true</code>. Only the top 10 items are provided if
|
||||
|
@ -547,8 +547,8 @@ class Stats : public QQuickItem {
|
|||
STATS_PROPERTY(int, lodAngle, 0)
|
||||
STATS_PROPERTY(int, lodTargetFramerate, 0)
|
||||
STATS_PROPERTY(QString, lodStatus, QString())
|
||||
STATS_PROPERTY(int, numEntityUpdates, 0)
|
||||
STATS_PROPERTY(int, numNeededEntityUpdates, 0)
|
||||
STATS_PROPERTY(quint64, numEntityUpdates, 0)
|
||||
STATS_PROPERTY(quint64, numNeededEntityUpdates, 0)
|
||||
STATS_PROPERTY(QString, timingStats, QString())
|
||||
STATS_PROPERTY(QString, gameUpdateStats, QString())
|
||||
STATS_PROPERTY(int, serverElements, 0)
|
||||
|
|
|
@ -66,7 +66,7 @@ private:
|
|||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay);
|
||||
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay);
|
||||
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay, RenderArgs* args);
|
||||
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args);
|
||||
template <> const ShapeKey shapeGetShapeKey(const Overlay::Pointer& overlay);
|
||||
template <> uint32_t metaFetchMetaSubItems(const Overlay::Pointer& overlay, ItemIDs& subItems);
|
||||
|
|
|
@ -1212,8 +1212,8 @@ float Overlays::width() {
|
|||
return result;
|
||||
}
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
return offscreenUi->getWindow()->size().width();
|
||||
auto offscreenUI = DependencyManager::get<OffscreenUi>();
|
||||
return offscreenUI ? offscreenUI->getWindow()->size().width() : -1.0f;
|
||||
}
|
||||
|
||||
float Overlays::height() {
|
||||
|
@ -1224,8 +1224,8 @@ float Overlays::height() {
|
|||
return result;
|
||||
}
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
return offscreenUi->getWindow()->size().height();
|
||||
auto offscreenUI = DependencyManager::get<OffscreenUi>();
|
||||
return offscreenUI ? offscreenUI->getWindow()->size().height() : -1.0f;
|
||||
}
|
||||
|
||||
void Overlays::mousePressOnPointerEvent(const QUuid& id, const PointerEvent& event) {
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace render {
|
|||
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
|
||||
return overlay->getKey();
|
||||
}
|
||||
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) {
|
||||
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay, RenderArgs* args) {
|
||||
return overlay->getBounds();
|
||||
}
|
||||
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) {
|
||||
|
|
|
@ -24,13 +24,17 @@ QmlOverlay::QmlOverlay(const QUrl& url, const QmlOverlay* overlay)
|
|||
}
|
||||
|
||||
void QmlOverlay::buildQmlElement(const QUrl& url) {
|
||||
auto offscreenUI = DependencyManager::get<OffscreenUi>();
|
||||
if (!offscreenUI) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "buildQmlElement", Q_ARG(QUrl, url));
|
||||
return;
|
||||
}
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->load(url, [=](QQmlContext* context, QObject* object) {
|
||||
offscreenUI->load(url, [=](QQmlContext* context, QObject* object) {
|
||||
_qmlElement = dynamic_cast<QQuickItem*>(object);
|
||||
connect(_qmlElement, &QObject::destroyed, this, &QmlOverlay::qmlElementDestroyed);
|
||||
});
|
||||
|
|
|
@ -82,9 +82,9 @@ namespace render {
|
|||
template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) {
|
||||
return payload->getKey();
|
||||
}
|
||||
template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) {
|
||||
template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args) {
|
||||
if (payload) {
|
||||
return payload->getBound();
|
||||
return payload->getBound(args);
|
||||
}
|
||||
return Item::Bound();
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
void render(RenderArgs* args);
|
||||
|
||||
render::Item::Bound& editBound() { return _bound; }
|
||||
const render::Item::Bound& getBound() { return _bound; }
|
||||
const render::Item::Bound& getBound(RenderArgs* args) { return _bound; }
|
||||
|
||||
void setVisible(bool visible);
|
||||
void showProxies(bool show);
|
||||
|
@ -96,7 +96,7 @@ protected:
|
|||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload);
|
||||
template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload);
|
||||
template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args);
|
||||
template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args);
|
||||
template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload);
|
||||
}
|
||||
|
|
|
@ -1855,6 +1855,16 @@ glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const HFMJoin
|
|||
return position;
|
||||
}
|
||||
|
||||
// Get the scale factor to convert distances in the geometry frame into the unscaled rig frame.
|
||||
// Typically it will be the unit conversion from cm to m.
|
||||
float Rig::GetScaleFactorGeometryToUnscaledRig() const {
|
||||
// Normally the model offset transform will contain the avatar scale factor; we explicitly remove it here.
|
||||
AnimPose modelOffsetWithoutAvatarScale(glm::vec3(1.0f), getModelOffsetPose().rot(), getModelOffsetPose().trans());
|
||||
AnimPose geomToRigWithoutAvatarScale = modelOffsetWithoutAvatarScale * getGeometryOffsetPose();
|
||||
|
||||
return geomToRigWithoutAvatarScale.scale().x; // in practice this is always a uniform scale factor.
|
||||
}
|
||||
|
||||
void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
|
||||
bool leftArmEnabled, bool rightArmEnabled, bool headEnabled, float dt,
|
||||
const AnimPose& leftHandPose, const AnimPose& rightHandPose,
|
||||
|
@ -2703,10 +2713,10 @@ void Rig::computeAvatarBoundingCapsule(
|
|||
Extents totalExtents;
|
||||
totalExtents.reset();
|
||||
|
||||
// HACK by convention our Avatars are always modeled such that y=0 is the ground plane.
|
||||
// add the zero point so that our avatars will always have bounding volumes that are flush with the ground
|
||||
// HACK by convention our Avatars are always modeled such that y=0 (GEOMETRY_GROUND_Y) is the ground plane.
|
||||
// add the ground point so that our avatars will always have bounding volumes that are flush with the ground
|
||||
// even if they do not have legs (default robot)
|
||||
totalExtents.addPoint(glm::vec3(0.0f));
|
||||
totalExtents.addPoint(glm::vec3(0.0f, GEOMETRY_GROUND_Y, 0.0f));
|
||||
|
||||
// To reduce the radius of the bounding capsule to be tight with the torso, we only consider joints
|
||||
// from the head to the hips when computing the rest of the bounding capsule.
|
||||
|
@ -2747,24 +2757,20 @@ void Rig::initFlow(bool isActive) {
|
|||
}
|
||||
}
|
||||
|
||||
// Get the vertical position of eye joints, in the rig coordinate frame, ignoring the avatar scale.
|
||||
float Rig::getUnscaledEyeHeight() const {
|
||||
// Normally the model offset transform will contain the avatar scale factor, we explicitly remove it here.
|
||||
AnimPose modelOffsetWithoutAvatarScale(glm::vec3(1.0f), getModelOffsetPose().rot(), getModelOffsetPose().trans());
|
||||
AnimPose geomToRigWithoutAvatarScale = modelOffsetWithoutAvatarScale * getGeometryOffsetPose();
|
||||
|
||||
// This factor can be used to scale distances in the geometry frame into the unscaled rig frame.
|
||||
// Typically it will be the unit conversion from cm to m.
|
||||
float scaleFactor = geomToRigWithoutAvatarScale.scale().x; // in practice this always a uniform scale factor.
|
||||
// Factor to scale distances in the geometry frame into the unscaled rig frame.
|
||||
float scaleFactor = GetScaleFactorGeometryToUnscaledRig();
|
||||
|
||||
int headTopJoint = indexOfJoint("HeadTop_End");
|
||||
int headJoint = indexOfJoint("Head");
|
||||
int eyeJoint = indexOfJoint("LeftEye") != -1 ? indexOfJoint("LeftEye") : indexOfJoint("RightEye");
|
||||
int toeJoint = indexOfJoint("LeftToeBase") != -1 ? indexOfJoint("LeftToeBase") : indexOfJoint("RightToeBase");
|
||||
|
||||
// Makes assumption that the y = 0 plane in geometry is the ground plane.
|
||||
// We also make that assumption in Rig::computeAvatarBoundingCapsule()
|
||||
const float GROUND_Y = 0.0f;
|
||||
|
||||
// Values from the skeleton are in the geometry coordinate frame.
|
||||
auto skeleton = getAnimSkeleton();
|
||||
if (eyeJoint >= 0 && toeJoint >= 0) {
|
||||
|
@ -2772,8 +2778,8 @@ float Rig::getUnscaledEyeHeight() const {
|
|||
float eyeHeight = skeleton->getAbsoluteDefaultPose(eyeJoint).trans().y - skeleton->getAbsoluteDefaultPose(toeJoint).trans().y;
|
||||
return scaleFactor * eyeHeight;
|
||||
} else if (eyeJoint >= 0) {
|
||||
// Measure Eye joint to y = 0 plane.
|
||||
float eyeHeight = skeleton->getAbsoluteDefaultPose(eyeJoint).trans().y - GROUND_Y;
|
||||
// Measure Eye joint to ground plane.
|
||||
float eyeHeight = skeleton->getAbsoluteDefaultPose(eyeJoint).trans().y - GEOMETRY_GROUND_Y;
|
||||
return scaleFactor * eyeHeight;
|
||||
} else if (headTopJoint >= 0 && toeJoint >= 0) {
|
||||
// Measure from ToeBase joint to HeadTop_End joint, then remove forehead distance.
|
||||
|
@ -2783,19 +2789,36 @@ float Rig::getUnscaledEyeHeight() const {
|
|||
} else if (headTopJoint >= 0) {
|
||||
// Measure from HeadTop_End joint to the ground, then remove forehead distance.
|
||||
const float ratio = DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT;
|
||||
float headHeight = skeleton->getAbsoluteDefaultPose(headTopJoint).trans().y - GROUND_Y;
|
||||
float headHeight = skeleton->getAbsoluteDefaultPose(headTopJoint).trans().y - GEOMETRY_GROUND_Y;
|
||||
return scaleFactor * (headHeight - headHeight * ratio);
|
||||
} else if (headJoint >= 0) {
|
||||
// Measure Head joint to the ground, then add in distance from neck to eye.
|
||||
const float DEFAULT_AVATAR_NECK_TO_EYE = DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD - DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD;
|
||||
const float ratio = DEFAULT_AVATAR_NECK_TO_EYE / DEFAULT_AVATAR_NECK_HEIGHT;
|
||||
float neckHeight = skeleton->getAbsoluteDefaultPose(headJoint).trans().y - GROUND_Y;
|
||||
float neckHeight = skeleton->getAbsoluteDefaultPose(headJoint).trans().y - GEOMETRY_GROUND_Y;
|
||||
return scaleFactor * (neckHeight + neckHeight * ratio);
|
||||
} else {
|
||||
return DEFAULT_AVATAR_EYE_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the vertical position of the hips joint, in the rig coordinate frame, ignoring the avatar scale.
|
||||
float Rig::getUnscaledHipsHeight() const {
|
||||
// This factor can be used to scale distances in the geometry frame into the unscaled rig frame.
|
||||
float scaleFactor = GetScaleFactorGeometryToUnscaledRig();
|
||||
|
||||
int hipsJoint = indexOfJoint("Hips");
|
||||
|
||||
// Values from the skeleton are in the geometry coordinate frame.
|
||||
if (hipsJoint >= 0) {
|
||||
// Measure hip joint to ground plane.
|
||||
float hipsHeight = getAnimSkeleton()->getAbsoluteDefaultPose(hipsJoint).trans().y - GEOMETRY_GROUND_Y;
|
||||
return scaleFactor * hipsHeight;
|
||||
} else {
|
||||
return DEFAULT_AVATAR_HIPS_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
void Rig::setDirectionalBlending(const QString& targetName, const glm::vec3& blendingTarget, const QString& alphaName, float alpha) {
|
||||
_animVars.set(targetName, blendingTarget);
|
||||
_animVars.set(alphaName, alpha);
|
||||
|
|
|
@ -251,6 +251,7 @@ public:
|
|||
Flow& getFlow() { return _internalFlow; }
|
||||
|
||||
float getUnscaledEyeHeight() const;
|
||||
float getUnscaledHipsHeight() const;
|
||||
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const;
|
||||
|
||||
int getOverrideJointCount() const;
|
||||
|
@ -287,6 +288,11 @@ protected:
|
|||
glm::vec3 deflectHandFromTorso(const glm::vec3& handPosition, const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
|
||||
const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo) const;
|
||||
|
||||
// Get the scale factor to convert distances in the geometry frame into the unscaled rig frame.
|
||||
float GetScaleFactorGeometryToUnscaledRig() const;
|
||||
|
||||
// The ground plane Y position in geometry space.
|
||||
static constexpr float GEOMETRY_GROUND_Y = 0.0f;
|
||||
|
||||
AnimPose _modelOffset; // model to rig space
|
||||
AnimPose _geometryOffset; // geometry to model space (includes unit offset & fst offsets)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <SharedUtil.h>
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <ThreadHelpers.h>
|
||||
|
||||
#include "AudioConstants.h"
|
||||
#include "AudioInjector.h"
|
||||
|
@ -54,11 +55,14 @@ AudioInjectorManager::~AudioInjectorManager() {
|
|||
}
|
||||
|
||||
void AudioInjectorManager::createThread() {
|
||||
_thread = new QThread;
|
||||
_thread = new QThread();
|
||||
_thread->setObjectName("Audio Injector Thread");
|
||||
|
||||
// when the thread is started, have it call our run to handle injection of audio
|
||||
connect(_thread, &QThread::started, this, &AudioInjectorManager::run, Qt::DirectConnection);
|
||||
connect(_thread, &QThread::started, this, [this] {
|
||||
setThreadName("AudioInjectorManager");
|
||||
run();
|
||||
}, Qt::DirectConnection);
|
||||
|
||||
moveToThread(_thread);
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace render {
|
|||
}
|
||||
return keyBuilder.build();
|
||||
}
|
||||
template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar) {
|
||||
template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar, RenderArgs* args) {
|
||||
auto avatarPtr = static_pointer_cast<Avatar>(avatar);
|
||||
if (avatarPtr) {
|
||||
return avatarPtr->getRenderBounds();
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar);
|
||||
template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar);
|
||||
template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar, RenderArgs* args);
|
||||
template <> void payloadRender(const AvatarSharedPointer& avatar, RenderArgs* args);
|
||||
template <> uint32_t metaFetchMetaSubItems(const AvatarSharedPointer& avatar, ItemIDs& subItems);
|
||||
}
|
||||
|
|
|
@ -156,17 +156,13 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
updateAttitude(_owningAvatar->getWorldOrientation());
|
||||
setBlendshapeCoefficients(_owningAvatar->getHead()->getSummedBlendshapeCoefficients());
|
||||
|
||||
Parent::simulate(deltaTime, fullUpdate);
|
||||
if (fullUpdate) {
|
||||
|
||||
Parent::simulate(deltaTime, fullUpdate);
|
||||
|
||||
// let rig compute the model offset
|
||||
glm::vec3 registrationPoint;
|
||||
if (_rig.getModelRegistrationPoint(registrationPoint)) {
|
||||
setOffset(registrationPoint);
|
||||
}
|
||||
} else {
|
||||
Parent::simulate(deltaTime, fullUpdate);
|
||||
}
|
||||
|
||||
// FIXME: This texture loading logic should probably live in Avatar, to mirror RenderableModelEntityItem,
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "CompositorHelper.h"
|
||||
#include "Logging.h"
|
||||
#include "RefreshRateController.h"
|
||||
#include <ThreadHelpers.h>
|
||||
|
||||
using namespace shader::gpu::program;
|
||||
|
||||
|
@ -285,6 +286,7 @@ bool OpenGLDisplayPlugin::activate() {
|
|||
widget->context()->doneCurrent();
|
||||
|
||||
presentThread->setContext(widget->context());
|
||||
connect(presentThread.data(), &QThread::started, [] { setThreadName("OpenGL Present Thread"); });
|
||||
// Start execution
|
||||
presentThread->start();
|
||||
}
|
||||
|
|
|
@ -136,8 +136,8 @@ public:
|
|||
static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName);
|
||||
static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName);
|
||||
|
||||
int getPrevNumEntityUpdates() const { return _prevNumEntityUpdates; }
|
||||
int getPrevTotalNeededEntityUpdates() const { return _prevTotalNeededEntityUpdates; }
|
||||
size_t getPrevNumEntityUpdates() const { return _prevNumEntityUpdates; }
|
||||
size_t getPrevTotalNeededEntityUpdates() const { return _prevTotalNeededEntityUpdates; }
|
||||
|
||||
signals:
|
||||
void enterEntity(const EntityItemID& entityItemID);
|
||||
|
@ -253,8 +253,8 @@ private:
|
|||
|
||||
ReadWriteLockable _changedEntitiesGuard;
|
||||
std::unordered_set<EntityItemID> _changedEntities;
|
||||
int _prevNumEntityUpdates { 0 };
|
||||
int _prevTotalNeededEntityUpdates { 0 };
|
||||
size_t _prevNumEntityUpdates { 0 };
|
||||
size_t _prevTotalNeededEntityUpdates { 0 };
|
||||
|
||||
std::unordered_set<EntityRendererPointer> _renderablesToUpdate;
|
||||
std::unordered_map<EntityItemID, EntityRendererPointer> _entitiesInScene;
|
||||
|
|
|
@ -137,8 +137,15 @@ EntityRenderer::~EntityRenderer() {}
|
|||
// Smart payload proxy members, implementing the payload interface
|
||||
//
|
||||
|
||||
Item::Bound EntityRenderer::getBound() {
|
||||
return _bound;
|
||||
Item::Bound EntityRenderer::getBound(RenderArgs* args) {
|
||||
auto bound = _bound;
|
||||
if (_billboardMode != BillboardMode::NONE) {
|
||||
glm::vec3 dimensions = bound.getScale();
|
||||
float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z));
|
||||
const float SQRT_2 = 1.41421356237f;
|
||||
bound.setScaleStayCentered(glm::vec3(SQRT_2 * max));
|
||||
}
|
||||
return bound;
|
||||
}
|
||||
|
||||
ShapeKey EntityRenderer::getShapeKey() {
|
||||
|
@ -198,12 +205,9 @@ uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const {
|
|||
}
|
||||
|
||||
bool EntityRenderer::passesZoneOcclusionTest(const std::unordered_set<QUuid>& containingZones) const {
|
||||
auto renderWithZones = resultWithReadLock<QVector<QUuid>>([&] {
|
||||
return _renderWithZones;
|
||||
});
|
||||
if (!renderWithZones.isEmpty()) {
|
||||
if (!_renderWithZones.isEmpty()) {
|
||||
if (!containingZones.empty()) {
|
||||
for (auto renderWithZone : renderWithZones) {
|
||||
for (auto renderWithZone : _renderWithZones) {
|
||||
if (containingZones.find(renderWithZone) != containingZones.end()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -364,6 +368,11 @@ bool EntityRenderer::needsRenderUpdate() const {
|
|||
return needsRenderUpdateFromEntity(_entity);
|
||||
}
|
||||
|
||||
Transform EntityRenderer::getTransformToCenterWithMaybeOnlyLocalRotation(const EntityItemPointer& entity, bool& success) const {
|
||||
return entity->getBillboardMode() == BillboardMode::NONE ? entity->getTransformToCenter(success) :
|
||||
entity->getTransformToCenterWithOnlyLocalRotation(success);
|
||||
}
|
||||
|
||||
// Returns true if the item in question needs to have updateInScene called because of changes in the entity
|
||||
bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity) const {
|
||||
if (entity->needsRenderUpdate()) {
|
||||
|
@ -375,12 +384,12 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
|
|||
}
|
||||
|
||||
bool success = false;
|
||||
auto bound = _entity->getAABox(success);
|
||||
auto bound = entity->getAABox(success);
|
||||
if (success && _bound != bound) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto newModelTransform = _entity->getTransformToCenter(success);
|
||||
auto newModelTransform = getTransformToCenterWithMaybeOnlyLocalRotation(entity, success);
|
||||
// FIXME can we use a stale model transform here?
|
||||
if (success && newModelTransform != _modelTransform) {
|
||||
return true;
|
||||
|
@ -397,15 +406,15 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
|
|||
return false;
|
||||
}
|
||||
|
||||
void EntityRenderer::updateModelTransformAndBound() {
|
||||
void EntityRenderer::updateModelTransformAndBound(const EntityItemPointer& entity) {
|
||||
bool success = false;
|
||||
auto newModelTransform = _entity->getTransformToCenter(success);
|
||||
auto newModelTransform = getTransformToCenterWithMaybeOnlyLocalRotation(entity, success);
|
||||
if (success) {
|
||||
_modelTransform = newModelTransform;
|
||||
}
|
||||
|
||||
success = false;
|
||||
auto bound = _entity->getAABox(success);
|
||||
auto bound = entity->getAABox(success);
|
||||
if (success) {
|
||||
_bound = bound;
|
||||
}
|
||||
|
@ -425,24 +434,28 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
|
|||
|
||||
_prevIsTransparent = transparent;
|
||||
|
||||
updateModelTransformAndBound();
|
||||
updateModelTransformAndBound(entity);
|
||||
|
||||
_moving = entity->isMovingRelativeToParent();
|
||||
_visible = entity->getVisible();
|
||||
setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera());
|
||||
setRenderLayer(entity->getRenderLayer());
|
||||
_primitiveMode = entity->getPrimitiveMode();
|
||||
_canCastShadow = entity->getCanCastShadow();
|
||||
setCullWithParent(entity->getCullWithParent());
|
||||
_cauterized = entity->getCauterized();
|
||||
if (entity->needsZoneOcclusionUpdate()) {
|
||||
entity->resetNeedsZoneOcclusionUpdate();
|
||||
_renderWithZones = entity->getRenderWithZones();
|
||||
}
|
||||
entity->setNeedsRenderUpdate(false);
|
||||
});
|
||||
}
|
||||
|
||||
void EntityRenderer::doRenderUpdateAsynchronous(const EntityItemPointer& entity) {
|
||||
setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera());
|
||||
setRenderLayer(entity->getRenderLayer());
|
||||
_billboardMode = entity->getBillboardMode();
|
||||
_primitiveMode = entity->getPrimitiveMode();
|
||||
_canCastShadow = entity->getCanCastShadow();
|
||||
setCullWithParent(entity->getCullWithParent());
|
||||
_cauterized = entity->getCauterized();
|
||||
if (entity->needsZoneOcclusionUpdate()) {
|
||||
entity->resetNeedsZoneOcclusionUpdate();
|
||||
_renderWithZones = entity->getRenderWithZones();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityRenderer::onAddToScene(const EntityItemPointer& entity) {
|
||||
QObject::connect(this, &EntityRenderer::requestRenderUpdate, this, [this] {
|
||||
auto renderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
static glm::vec3 calculatePulseColor(const glm::vec3& color, const PulsePropertyGroup& pulseProperties, quint64 start);
|
||||
|
||||
virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override;
|
||||
virtual Item::Bound getBound() override;
|
||||
virtual Item::Bound getBound(RenderArgs* args) override;
|
||||
bool passesZoneOcclusionTest(const std::unordered_set<QUuid>& containingZones) const override;
|
||||
|
||||
protected:
|
||||
|
@ -95,14 +95,13 @@ protected:
|
|||
// Will be called by the lambda posted to the scene in updateInScene.
|
||||
// This function will execute on the rendering thread, so you cannot use network caches to fetch
|
||||
// data in this method if using multi-threaded rendering
|
||||
|
||||
virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity) { }
|
||||
virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity);
|
||||
|
||||
// Called by the `render` method after `needsRenderUpdate`
|
||||
virtual void doRender(RenderArgs* args) = 0;
|
||||
|
||||
virtual bool isFading() const { return _isFading; }
|
||||
virtual void updateModelTransformAndBound();
|
||||
virtual void updateModelTransformAndBound(const EntityItemPointer& entity);
|
||||
virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
||||
inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
|
||||
|
||||
|
@ -110,16 +109,14 @@ protected:
|
|||
virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
|
||||
virtual void setCullWithParent(bool value) { _cullWithParent = value; }
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
std::shared_ptr<T> asTypedEntity() { return std::static_pointer_cast<T>(_entity); }
|
||||
|
||||
static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters);
|
||||
const Transform& getModelTransform() const;
|
||||
|
||||
Transform getTransformToCenterWithMaybeOnlyLocalRotation(const EntityItemPointer& entity, bool& success) const;
|
||||
|
||||
Item::Bound _bound;
|
||||
SharedSoundPointer _collisionSound;
|
||||
QUuid _changeHandlerId;
|
||||
|
@ -135,6 +132,7 @@ protected:
|
|||
RenderLayer _renderLayer { RenderLayer::WORLD };
|
||||
PrimitiveMode _primitiveMode { PrimitiveMode::SOLID };
|
||||
QVector<QUuid> _renderWithZones;
|
||||
BillboardMode _billboardMode;
|
||||
bool _cauterized { false };
|
||||
bool _moving { false };
|
||||
Transform _renderTransform;
|
||||
|
@ -154,6 +152,9 @@ protected:
|
|||
const EntityItemPointer _entity;
|
||||
|
||||
QUuid _entityID;
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -195,8 +195,8 @@ void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
}
|
||||
}
|
||||
|
||||
Item::Bound GizmoEntityRenderer::getBound() {
|
||||
auto bound = Parent::getBound();
|
||||
Item::Bound GizmoEntityRenderer::getBound(RenderArgs* args) {
|
||||
auto bound = Parent::getBound(args);
|
||||
if (_ringProperties.getHasTickMarks()) {
|
||||
glm::vec3 scale = bound.getScale();
|
||||
for (int i = 0; i < 3; i += 2) {
|
||||
|
@ -242,18 +242,20 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) {
|
|||
bool hasTickMarks = _ringProperties.getHasTickMarks();
|
||||
glm::vec4 tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(),
|
||||
_ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength());
|
||||
bool forward;
|
||||
bool wireframe;
|
||||
|
||||
bool transparent;
|
||||
withReadLock([&] {
|
||||
transform = _renderTransform;
|
||||
transparent = isTransparent();
|
||||
wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
});
|
||||
|
||||
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||
bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
|
||||
geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
||||
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), true));
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
// Background circle
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
~GizmoEntityRenderer();
|
||||
|
||||
protected:
|
||||
Item::Bound getBound() override;
|
||||
Item::Bound getBound(RenderArgs* args) override;
|
||||
ShapeKey getShapeKey() override;
|
||||
|
||||
bool isTransparent() const override;
|
||||
|
|
|
@ -49,13 +49,13 @@ void GridEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
|
|||
_minorGridEvery = entity->getMinorGridEvery();
|
||||
}
|
||||
|
||||
Item::Bound GridEntityRenderer::getBound() {
|
||||
Item::Bound GridEntityRenderer::getBound(RenderArgs* args) {
|
||||
if (_followCamera) {
|
||||
// This is a UI element that should always be in view, lie to the octree to avoid culling
|
||||
const AABox DOMAIN_BOX = AABox(glm::vec3(-TREE_SCALE / 2), TREE_SCALE);
|
||||
return DOMAIN_BOX;
|
||||
}
|
||||
return Parent::getBound();
|
||||
return Parent::getBound(args);
|
||||
}
|
||||
|
||||
ShapeKey GridEntityRenderer::getShapeKey() {
|
||||
|
@ -77,17 +77,17 @@ void GridEntityRenderer::doRender(RenderArgs* args) {
|
|||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
glm::vec3 dimensions;
|
||||
Transform renderTransform;
|
||||
bool forward;
|
||||
withReadLock([&] {
|
||||
dimensions = _dimensions;
|
||||
renderTransform = _renderTransform;
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
});
|
||||
|
||||
if (!_visible || color.a == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
|
||||
auto batch = args->_batch;
|
||||
|
||||
Transform transform;
|
||||
|
@ -103,6 +103,8 @@ void GridEntityRenderer::doRender(RenderArgs* args) {
|
|||
} else {
|
||||
transform.setTranslation(renderTransform.getTranslation());
|
||||
}
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition()));
|
||||
batch->setModelTransform(transform);
|
||||
|
||||
auto minCorner = glm::vec2(-0.5f, -0.5f);
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
~GridEntityRenderer();
|
||||
|
||||
protected:
|
||||
Item::Bound getBound() override;
|
||||
Item::Bound getBound(RenderArgs* args) override;
|
||||
ShapeKey getShapeKey() override;
|
||||
|
||||
bool isTransparent() const override;
|
||||
|
|
|
@ -58,7 +58,6 @@ void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
_color = entity->getColor();
|
||||
_alpha = entity->getAlpha();
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
_billboardMode = entity->getBillboardMode();
|
||||
|
||||
if (!_textureIsLoaded) {
|
||||
emit requestRenderUpdate();
|
||||
|
@ -66,17 +65,6 @@ void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
_textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed());
|
||||
}
|
||||
|
||||
Item::Bound ImageEntityRenderer::getBound() {
|
||||
auto bound = Parent::getBound();
|
||||
if (_billboardMode != BillboardMode::NONE) {
|
||||
glm::vec3 dimensions = bound.getScale();
|
||||
float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z));
|
||||
const float SQRT_2 = 1.41421356237f;
|
||||
bound.setScaleStayCentered(glm::vec3(SQRT_2 * max));
|
||||
}
|
||||
return bound;
|
||||
}
|
||||
|
||||
ShapeKey ImageEntityRenderer::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
|
||||
if (isTransparent()) {
|
||||
|
@ -109,7 +97,8 @@ void ImageEntityRenderer::doRender(RenderArgs* args) {
|
|||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch* batch = args->_batch;
|
||||
|
||||
transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition()));
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition()));
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||
|
|
|
@ -23,7 +23,6 @@ public:
|
|||
~ImageEntityRenderer();
|
||||
|
||||
protected:
|
||||
Item::Bound getBound() override;
|
||||
ShapeKey getShapeKey() override;
|
||||
|
||||
bool isTransparent() const override;
|
||||
|
@ -44,7 +43,6 @@ private:
|
|||
glm::u8vec3 _color;
|
||||
float _alpha;
|
||||
PulsePropertyGroup _pulseProperties;
|
||||
BillboardMode _billboardMode;
|
||||
|
||||
int _geometryId { 0 };
|
||||
};
|
||||
|
|
|
@ -60,8 +60,8 @@ ItemKey LightEntityRenderer::getKey() {
|
|||
return payloadGetKey(_lightPayload);
|
||||
}
|
||||
|
||||
Item::Bound LightEntityRenderer::getBound() {
|
||||
return payloadGetBound(_lightPayload);
|
||||
Item::Bound LightEntityRenderer::getBound(RenderArgs* args) {
|
||||
return payloadGetBound(_lightPayload, args);
|
||||
}
|
||||
|
||||
void LightEntityRenderer::doRender(RenderArgs* args) {
|
||||
|
|
|
@ -29,7 +29,7 @@ protected:
|
|||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
virtual ItemKey getKey() override;
|
||||
virtual Item::Bound getBound() override;
|
||||
virtual Item::Bound getBound(RenderArgs* args) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -47,7 +47,8 @@ void LineEntityRenderer::doRender(RenderArgs* args) {
|
|||
const auto& modelTransform = getModelTransform();
|
||||
Transform transform = Transform();
|
||||
transform.setTranslation(modelTransform.getTranslation());
|
||||
transform.setRotation(modelTransform.getRotation());
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition()));
|
||||
batch.setModelTransform(transform);
|
||||
if (_linePoints.size() > 1) {
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, false, true,
|
||||
|
|
|
@ -259,9 +259,9 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
|||
textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot)));
|
||||
textureTransform.setScale(glm::vec3(_materialMappingScale, 1));
|
||||
|
||||
Transform renderTransform;
|
||||
Transform transform;
|
||||
withReadLock([&] {
|
||||
renderTransform = _renderTransform;
|
||||
transform = _renderTransform;
|
||||
});
|
||||
|
||||
if (!drawMaterial) {
|
||||
|
@ -272,7 +272,9 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
|||
proceduralRender = true;
|
||||
}
|
||||
|
||||
batch.setModelTransform(renderTransform);
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition()));
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
if (!proceduralRender) {
|
||||
drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true);
|
||||
|
@ -287,8 +289,8 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
|||
auto proceduralDrawMaterial = std::static_pointer_cast<graphics::ProceduralMaterial>(drawMaterial);
|
||||
glm::vec4 outColor = glm::vec4(drawMaterial->getAlbedo(), drawMaterial->getOpacity());
|
||||
outColor = proceduralDrawMaterial->getColor(outColor);
|
||||
proceduralDrawMaterial->prepare(batch, renderTransform.getTranslation(), renderTransform.getScale(),
|
||||
renderTransform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
proceduralDrawMaterial->prepare(batch, transform.getTranslation(), transform.getScale(),
|
||||
transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) {
|
||||
DependencyManager::get<GeometryCache>()->renderWireSphere(batch, outColor);
|
||||
} else {
|
||||
|
@ -374,7 +376,7 @@ void MaterialEntityRenderer::applyMaterial(const TypedEntityPointer& entity) {
|
|||
|
||||
if (material->isProcedural()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(material);
|
||||
procedural->setBoundOperator([this] { return getBound(); });
|
||||
procedural->setBoundOperator([this](RenderArgs* args) { return getBound(args); });
|
||||
entity->setHasVertexShader(procedural->hasVertexShader());
|
||||
}
|
||||
|
||||
|
|
|
@ -115,11 +115,12 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
|||
}
|
||||
|
||||
bool success;
|
||||
auto transform = getTransform(success);
|
||||
auto transform = getBillboardMode() == BillboardMode::NONE ? getTransform(success) : getTransformWithOnlyLocalRotation(success);
|
||||
if (success) {
|
||||
if (model->getTranslation() != transform.getTranslation()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (model->getRotation() != transform.getRotation()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -149,10 +150,12 @@ void RenderableModelEntityItem::updateModelBounds() {
|
|||
bool overridingModelTransform = model->isOverridingModelTransformAndOffset();
|
||||
glm::vec3 scaledDimensions = getScaledDimensions();
|
||||
glm::vec3 registrationPoint = getRegistrationPoint();
|
||||
bool needsSimulate = false;
|
||||
if (!overridingModelTransform &&
|
||||
(model->getScaleToFitDimensions() != scaledDimensions ||
|
||||
model->getRegistrationPoint() != registrationPoint ||
|
||||
!model->getIsScaledToFit() || _needsToRescaleModel)) {
|
||||
model->getRegistrationPoint() != registrationPoint ||
|
||||
!model->getIsScaledToFit() || _needsToRescaleModel ||
|
||||
_useOriginalPivot == model->getSnapModelToRegistrationPoint())) {
|
||||
// The machinery for updateModelBounds will give existing models the opportunity to fix their
|
||||
// translation/rotation/scale/registration. The first two are straightforward, but the latter two
|
||||
// have guards to make sure they don't happen after they've already been set. Here we reset those guards.
|
||||
|
@ -162,24 +165,25 @@ void RenderableModelEntityItem::updateModelBounds() {
|
|||
|
||||
// now recalculate the bounds and registration
|
||||
model->setScaleToFit(true, scaledDimensions);
|
||||
model->setSnapModelToRegistrationPoint(true, registrationPoint);
|
||||
model->setSnapModelToRegistrationPoint(!_useOriginalPivot, registrationPoint);
|
||||
updateRenderItems = true;
|
||||
model->scaleToFit();
|
||||
needsSimulate = true;
|
||||
_needsToRescaleModel = false;
|
||||
}
|
||||
|
||||
bool success;
|
||||
auto transform = getTransform(success);
|
||||
auto transform = getBillboardMode() == BillboardMode::NONE ? getTransform(success) : getTransformWithOnlyLocalRotation(success);
|
||||
if (success && (model->getTranslation() != transform.getTranslation() ||
|
||||
model->getRotation() != transform.getRotation())) {
|
||||
model->setTransformNoUpdateRenderItems(transform);
|
||||
updateRenderItems = true;
|
||||
}
|
||||
|
||||
if (_needsInitialSimulation || _needsJointSimulation || isAnimatingSomething()) {
|
||||
if (_needsInitialSimulation || _needsJointSimulation || needsSimulate || isAnimatingSomething()) {
|
||||
// NOTE: on isAnimatingSomething() we need to call Model::simulate() which calls Rig::updateRig()
|
||||
// TODO: there is opportunity to further optimize the isAnimatingSomething() case.
|
||||
model->simulate(0.0f);
|
||||
locationChanged();
|
||||
_needsInitialSimulation = false;
|
||||
_needsJointSimulation = false;
|
||||
updateRenderItems = true;
|
||||
|
@ -189,9 +193,6 @@ void RenderableModelEntityItem::updateModelBounds() {
|
|||
glm::vec3 scale = model->getScale();
|
||||
model->setUseDualQuaternionSkinning(!isNonUniformScale(scale));
|
||||
model->updateRenderItems();
|
||||
|
||||
markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
locationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,31 +223,41 @@ EntityItemProperties RenderableModelEntityItem::getProperties(const EntityProper
|
|||
return properties;
|
||||
}
|
||||
|
||||
glm::vec3 RenderableModelEntityItem::getPivot() const {
|
||||
auto model = getModel();
|
||||
auto pivot = EntityItem::getPivot();
|
||||
if (!model || !model->isLoaded() || !_useOriginalPivot) {
|
||||
return pivot;
|
||||
}
|
||||
|
||||
return pivot + model->getOriginalOffset();
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::supportsDetailedIntersection() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElementPointer& element, float& distance, BoxFace& face,
|
||||
const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face,
|
||||
glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
auto model = getModel();
|
||||
if (!model || !model->isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return model->findRayIntersectionAgainstSubMeshes(origin, direction, distance,
|
||||
return model->findRayIntersectionAgainstSubMeshes(origin, direction, viewFrustumPos, distance,
|
||||
face, surfaceNormal, extraInfo, precisionPicking, false);
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
|
||||
const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face,
|
||||
glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
auto model = getModel();
|
||||
if (!model || !model->isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, parabolicDistance,
|
||||
return model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, viewFrustumPos, parabolicDistance,
|
||||
face, surfaceNormal, extraInfo, precisionPicking, false);
|
||||
}
|
||||
|
||||
|
@ -446,14 +457,15 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
// multiply each point by scale before handing the point-set off to the physics engine.
|
||||
// also determine the extents of the collision model.
|
||||
glm::vec3 registrationOffset = dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint());
|
||||
glm::vec3 offset = model->getSnapModelToRegistrationPoint() ? model->getOffset() : glm::vec3(0.0f);
|
||||
for (int32_t i = 0; i < pointCollection.size(); i++) {
|
||||
for (int32_t j = 0; j < pointCollection[i].size(); j++) {
|
||||
// back compensate for registration so we can apply that offset to the shapeInfo later
|
||||
pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + model->getOffset()) - registrationOffset;
|
||||
pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + offset) - registrationOffset;
|
||||
}
|
||||
}
|
||||
shapeInfo.setParams(type, 0.5f * extents, getCompoundShapeURL());
|
||||
adjustShapeInfoByRegistration(shapeInfo);
|
||||
shapeInfo.setParams(type, 0.5f * extents, getCompoundShapeURL() + model->getSnapModelToRegistrationPoint());
|
||||
adjustShapeInfoByRegistration(shapeInfo, model->getSnapModelToRegistrationPoint());
|
||||
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
|
||||
updateModelBounds();
|
||||
model->updateGeometry();
|
||||
|
@ -685,8 +697,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
shapeInfo.setParams(type, 0.5f * extents.size(), getModelURL());
|
||||
adjustShapeInfoByRegistration(shapeInfo);
|
||||
shapeInfo.setParams(type, 0.5f * extents.size(), getModelURL() + model->getSnapModelToRegistrationPoint());
|
||||
adjustShapeInfoByRegistration(shapeInfo, model->getSnapModelToRegistrationPoint());
|
||||
} else {
|
||||
EntityItem::computeShapeInfo(shapeInfo);
|
||||
}
|
||||
|
@ -1257,6 +1269,7 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
_model->setTagMask(getTagMask(), scene);
|
||||
_model->setHifiRenderLayer(getHifiRenderLayer(), scene);
|
||||
_model->setPrimitiveMode(_primitiveMode, scene);
|
||||
_model->setBillboardMode(_billboardMode, scene);
|
||||
_model->setCullWithParent(_cullWithParent, scene);
|
||||
_model->setRenderWithZones(_renderWithZones, scene);
|
||||
});
|
||||
|
@ -1267,6 +1280,9 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
entity->_originalTexturesRead = false;
|
||||
entity->_needsJointSimulation = true;
|
||||
entity->_needsToRescaleModel = true;
|
||||
|
||||
entity->markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
entity->locationChanged();
|
||||
emit requestRenderUpdate();
|
||||
});
|
||||
scene->enqueueTransaction(transaction);
|
||||
|
@ -1332,6 +1348,7 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
|||
model->setTagMask(getTagMask(), scene);
|
||||
model->setHifiRenderLayer(getHifiRenderLayer(), scene);
|
||||
model->setPrimitiveMode(_primitiveMode, scene);
|
||||
model->setBillboardMode(_billboardMode, scene);
|
||||
model->setCullWithParent(_cullWithParent, scene);
|
||||
model->setRenderWithZones(_renderWithZones, scene);
|
||||
});
|
||||
|
|
|
@ -42,7 +42,7 @@ protected:
|
|||
void setModel(const ModelPointer& model);
|
||||
ModelPointer getModel() const;
|
||||
|
||||
bool _needsInitialSimulation{ true };
|
||||
bool _needsInitialSimulation { true };
|
||||
private:
|
||||
ModelPointer _model;
|
||||
};
|
||||
|
@ -63,14 +63,15 @@ public:
|
|||
virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
|
||||
void updateModelBounds();
|
||||
|
||||
glm::vec3 getPivot() const override;
|
||||
virtual bool supportsDetailedIntersection() const override;
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElementPointer& element, float& distance,
|
||||
const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const override;
|
||||
virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
|
||||
const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const override;
|
||||
|
||||
virtual void setShapeType(ShapeType type) override;
|
||||
|
|
|
@ -161,7 +161,7 @@ ShapeKey ParticleEffectEntityRenderer::getShapeKey() {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
Item::Bound ParticleEffectEntityRenderer::getBound() {
|
||||
Item::Bound ParticleEffectEntityRenderer::getBound(RenderArgs* args) {
|
||||
return _bound;
|
||||
}
|
||||
|
||||
|
@ -456,6 +456,7 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
|
|||
color.spread = EntityRenderer::calculatePulseColor(_particleProperties.getColorSpread(), _pulseProperties, _created);
|
||||
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
batch.setUniformBuffer(0, _uniformBuffer);
|
||||
batch.setInputFormat(_vertexFormat);
|
||||
batch.setInputBuffer(0, _particleBuffer, 0, sizeof(GpuParticle));
|
||||
|
|
|
@ -30,7 +30,7 @@ protected:
|
|||
|
||||
virtual ItemKey getKey() override;
|
||||
virtual ShapeKey getShapeKey() override;
|
||||
virtual Item::Bound getBound() override;
|
||||
virtual Item::Bound getBound(RenderArgs* args) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -41,13 +41,13 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
|
|||
}
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::updateModelTransformAndBound() {
|
||||
void PolyLineEntityRenderer::updateModelTransformAndBound(const EntityItemPointer& entity) {
|
||||
bool success = false;
|
||||
auto newModelTransform = _entity->getTransformToCenter(success);
|
||||
auto newModelTransform = getTransformToCenterWithMaybeOnlyLocalRotation(entity, success);
|
||||
if (success) {
|
||||
_modelTransform = newModelTransform;
|
||||
|
||||
auto lineEntity = std::static_pointer_cast<PolyLineEntityItem>(_entity);
|
||||
auto lineEntity = std::static_pointer_cast<PolyLineEntityItem>(entity);
|
||||
AABox bound;
|
||||
lineEntity->computeTightLocalBoundingBox(bound);
|
||||
bound.transform(newModelTransform);
|
||||
|
@ -325,8 +325,11 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
|
|||
buildPipelines();
|
||||
}
|
||||
|
||||
batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]);
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition()));
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]);
|
||||
batch.setResourceTexture(0, texture);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * _numVertices), 0);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class PolyLineEntityRenderer : public TypedEntityRenderer<PolyLineEntityItem> {
|
|||
public:
|
||||
PolyLineEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
void updateModelTransformAndBound() override;
|
||||
void updateModelTransformAndBound(const EntityItemPointer& entity) override;
|
||||
|
||||
virtual bool isTransparent() const override;
|
||||
|
||||
|
|
|
@ -238,53 +238,6 @@ void RenderablePolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxel
|
|||
startUpdates();
|
||||
}
|
||||
|
||||
glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const {
|
||||
glm::vec3 result;
|
||||
withReadLock([&] {
|
||||
glm::vec3 scale = getScaledDimensions() / _voxelVolumeSize; // meters / voxel-units
|
||||
if (isEdged(_voxelSurfaceStyle)) {
|
||||
result = scale / -2.0f;
|
||||
}
|
||||
return scale / 2.0f;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const {
|
||||
glm::vec3 voxelVolumeSize;
|
||||
withReadLock([&] {
|
||||
voxelVolumeSize = _voxelVolumeSize;
|
||||
});
|
||||
|
||||
glm::vec3 dimensions = getScaledDimensions();
|
||||
glm::vec3 scale = dimensions / voxelVolumeSize; // meters / voxel-units
|
||||
bool success; // TODO -- Does this actually have to happen in world space?
|
||||
glm::vec3 center = getCenterPosition(success); // this handles registrationPoint changes
|
||||
glm::vec3 position = getWorldPosition(success);
|
||||
glm::vec3 positionToCenter = center - position;
|
||||
|
||||
positionToCenter -= dimensions * Vectors::HALF - getSurfacePositionAdjustment();
|
||||
glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter);
|
||||
glm::mat4 scaled = glm::scale(centerToCorner, scale);
|
||||
return scaled;
|
||||
}
|
||||
|
||||
glm::mat4 RenderablePolyVoxEntityItem::localToVoxelMatrix() const {
|
||||
glm::mat4 localToModelMatrix = glm::inverse(voxelToLocalMatrix());
|
||||
return localToModelMatrix;
|
||||
}
|
||||
|
||||
glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() const {
|
||||
glm::mat4 rotation = glm::mat4_cast(getWorldOrientation());
|
||||
glm::mat4 translation = glm::translate(getWorldPosition());
|
||||
return translation * rotation * voxelToLocalMatrix();
|
||||
}
|
||||
|
||||
glm::mat4 RenderablePolyVoxEntityItem::worldToVoxelMatrix() const {
|
||||
glm::mat4 worldToModelMatrix = glm::inverse(voxelToWorldMatrix());
|
||||
return worldToModelMatrix;
|
||||
}
|
||||
|
||||
bool RenderablePolyVoxEntityItem::setVoxel(const ivec3& v, uint8_t toValue) {
|
||||
if (_locked) {
|
||||
return false;
|
||||
|
@ -573,7 +526,7 @@ public:
|
|||
#endif
|
||||
|
||||
bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElementPointer& element,
|
||||
const glm::vec3& viewFrustumPos, OctreeElementPointer& element,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
// TODO -- correctly pick against marching-cube generated meshes
|
||||
|
@ -582,7 +535,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
|
|||
return true;
|
||||
}
|
||||
|
||||
glm::mat4 wtvMatrix = worldToVoxelMatrix();
|
||||
glm::mat4 wtvMatrix = worldToVoxelMatrix(true);
|
||||
glm::vec3 normDirection = glm::normalize(direction);
|
||||
|
||||
// the PolyVox ray intersection code requires a near and far point.
|
||||
|
@ -614,7 +567,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
|
|||
}
|
||||
|
||||
bool RenderablePolyVoxEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
|
||||
const glm::vec3& acceleration, OctreeElementPointer& element,
|
||||
const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
// TODO -- correctly pick against marching-cube generated meshes
|
||||
|
@ -623,7 +576,7 @@ bool RenderablePolyVoxEntityItem::findDetailedParabolaIntersection(const glm::ve
|
|||
return true;
|
||||
}
|
||||
|
||||
glm::mat4 wtvMatrix = worldToVoxelMatrix();
|
||||
glm::mat4 wtvMatrix = worldToVoxelMatrix(true);
|
||||
glm::vec4 originInVoxel = wtvMatrix * glm::vec4(origin, 1.0f);
|
||||
glm::vec4 velocityInVoxel = wtvMatrix * glm::vec4(velocity, 0.0f);
|
||||
glm::vec4 accelerationInVoxel = wtvMatrix * glm::vec4(acceleration, 0.0f);
|
||||
|
@ -723,8 +676,10 @@ ShapeType RenderablePolyVoxEntityItem::getShapeType() const {
|
|||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::setRegistrationPoint(const glm::vec3& value) {
|
||||
if (value != _registrationPoint) {
|
||||
_shapeReady = false;
|
||||
if (value != getRegistrationPoint()) {
|
||||
withWriteLock([&] {
|
||||
_shapeReady = false;
|
||||
});
|
||||
EntityItem::setRegistrationPoint(value);
|
||||
startUpdates();
|
||||
}
|
||||
|
@ -1803,7 +1758,7 @@ ShapeKey PolyVoxEntityRenderer::getShapeKey() {
|
|||
|
||||
bool PolyVoxEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
if (entity->voxelToWorldMatrix() != _lastVoxelToWorldMatrix) {
|
||||
if (entity->voxelToLocalMatrix() != _lastVoxelToLocalMatrix) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1829,7 +1784,10 @@ void PolyVoxEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& s
|
|||
}
|
||||
|
||||
void PolyVoxEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
_lastVoxelToWorldMatrix = entity->voxelToWorldMatrix();
|
||||
_lastVoxelToLocalMatrix = entity->voxelToLocalMatrix();
|
||||
bool success;
|
||||
_position = entity->getCenterPosition(success);
|
||||
_orientation = entity->getBillboardMode() == BillboardMode::NONE ? entity->getWorldOrientation() : entity->getLocalOrientation();
|
||||
_lastVoxelVolumeSize = entity->getVoxelVolumeSize();
|
||||
_params->setSubData(0, vec4(_lastVoxelVolumeSize, 0.0));
|
||||
graphics::MeshPointer newMesh;
|
||||
|
@ -1862,17 +1820,18 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render");
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
Transform transform(_lastVoxelToWorldMatrix);
|
||||
glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(_position, _orientation, _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition()));
|
||||
Transform transform(glm::translate(_position) * rotation * _lastVoxelToLocalMatrix);
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
batch.setInputFormat(_vertexFormat);
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, _mesh->getVertexBuffer()._buffer, 0,
|
||||
sizeof(PolyVox::PositionMaterialNormal));
|
||||
|
||||
|
||||
// TODO -- should we be setting this?
|
||||
// batch.setInputBuffer(gpu::Stream::NORMAL, mesh->getVertexBuffer()._buffer,
|
||||
// 12,
|
||||
|
|
|
@ -71,24 +71,18 @@ public:
|
|||
|
||||
virtual bool supportsDetailedIntersection() const override { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElementPointer& element, float& distance,
|
||||
const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const override;
|
||||
virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const vec3& accleration,
|
||||
OctreeElementPointer& element, float& parabolicDistance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
const glm::vec3& viewFrustumPos, OctreeElementPointer& element,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const override;
|
||||
|
||||
virtual void setVoxelData(const QByteArray& voxelData) override;
|
||||
virtual void setVoxelVolumeSize(const glm::vec3& voxelVolumeSize) override;
|
||||
virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) override;
|
||||
|
||||
glm::vec3 getSurfacePositionAdjustment() const;
|
||||
glm::mat4 voxelToWorldMatrix() const;
|
||||
glm::mat4 worldToVoxelMatrix() const;
|
||||
glm::mat4 voxelToLocalMatrix() const;
|
||||
glm::mat4 localToVoxelMatrix() const;
|
||||
|
||||
virtual ShapeType getShapeType() const override;
|
||||
virtual bool isReadyToComputeShape() const override;
|
||||
virtual void computeShapeInfo(ShapeInfo& info) override;
|
||||
|
@ -226,7 +220,9 @@ private:
|
|||
gpu::BufferPointer _params;
|
||||
std::array<NetworkTexturePointer, 3> _xyzTextures;
|
||||
glm::vec3 _lastVoxelVolumeSize;
|
||||
glm::mat4 _lastVoxelToWorldMatrix;
|
||||
glm::mat4 _lastVoxelToLocalMatrix;
|
||||
glm::vec3 _position;
|
||||
glm::quat _orientation;
|
||||
PolyVoxEntityItem::PolyVoxSurfaceStyle _lastSurfaceStyle { PolyVoxEntityItem::SURFACE_MARCHING_CUBES };
|
||||
std::array<QString, 3> _xyzTextureUrls;
|
||||
};
|
||||
|
|
|
@ -55,21 +55,18 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
withWriteLock([&] {
|
||||
_position = entity->getWorldPosition();
|
||||
_dimensions = entity->getUnscaledDimensions(); // get unscaled to avoid scaling twice
|
||||
_orientation = entity->getWorldOrientation();
|
||||
_shape = entity->getShape();
|
||||
_renderTransform = getModelTransform(); // contains parent scale, if this entity scales with its parent
|
||||
if (_shape == entity::Sphere) {
|
||||
_renderTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
}
|
||||
|
||||
_renderTransform.postScale(_dimensions);
|
||||
_renderTransform.postScale(entity->getUnscaledDimensions());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
_shape = entity->getShape();
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
|
||||
bool materialChanged = false;
|
||||
|
@ -200,16 +197,16 @@ ShapeKey ShapeEntityRenderer::getShapeKey() {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
Item::Bound ShapeEntityRenderer::getBound() {
|
||||
Item::Bound ShapeEntityRenderer::getBound(RenderArgs* args) {
|
||||
auto mat = _materials.find("0");
|
||||
if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() &&
|
||||
mat->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(mat->second.top().material);
|
||||
if (procedural->hasVertexShader() && procedural->hasBoundOperator()) {
|
||||
return procedural->getBound();
|
||||
return procedural->getBound(args);
|
||||
}
|
||||
}
|
||||
return Parent::getBound();
|
||||
return Parent::getBound(args);
|
||||
}
|
||||
|
||||
void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||
|
@ -221,14 +218,11 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
graphics::MultiMaterial materials;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
GeometryCache::Shape geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
||||
PrimitiveMode primitiveMode;
|
||||
RenderLayer renderLayer;
|
||||
glm::vec4 outColor;
|
||||
Pipeline pipelineType;
|
||||
Transform transform;
|
||||
withReadLock([&] {
|
||||
primitiveMode = _primitiveMode;
|
||||
renderLayer = _renderLayer;
|
||||
batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation
|
||||
transform = _renderTransform;
|
||||
materials = _materials["0"];
|
||||
pipelineType = getPipelineType(materials);
|
||||
auto& schema = materials.getSchemaBuffer().get<graphics::MultiMaterial::Schema>();
|
||||
|
@ -241,15 +235,20 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
return;
|
||||
}
|
||||
|
||||
transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode,
|
||||
args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(),
|
||||
_shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron));
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
if (pipelineType == Pipeline::PROCEDURAL) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials.top().material);
|
||||
outColor = procedural->getColor(outColor);
|
||||
outColor.a *= procedural->isFading() ? Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) : 1.0f;
|
||||
withReadLock([&] {
|
||||
procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
});
|
||||
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) {
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) {
|
||||
geometryCache->renderWireShape(batch, geometryShape, outColor);
|
||||
} else {
|
||||
geometryCache->renderShape(batch, geometryShape, outColor);
|
||||
|
@ -258,8 +257,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false,
|
||||
renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode());
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) {
|
||||
_renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode());
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) {
|
||||
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||
} else {
|
||||
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue