mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-05 18:01:56 +02:00
Update spotless and ktlint (#1528)
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com> Co-authored-by: loucass003 <loucass003@gmail.com>
This commit is contained in:
@@ -14,7 +14,7 @@ android.nonTransitiveRClass=true
|
||||
org.gradle.unsafe.configuration-cache=false
|
||||
|
||||
kotlinVersion=2.0.20
|
||||
spotlessVersion=7.0.2
|
||||
spotlessVersion=8.0.0
|
||||
shadowJarVersion=8.3.2
|
||||
buildconfigVersion=5.5.0
|
||||
grgitVersion=5.2.2
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,8 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
34
gradlew
vendored
34
gradlew
vendored
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -83,10 +85,9 @@ done
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -133,10 +134,13 @@ location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
@@ -144,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
@@ -152,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
@@ -197,11 +201,15 @@ if "$cygwin" || "$msys" ; then
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
|
||||
22
gradlew.bat
vendored
22
gradlew.bat
vendored
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ configure<com.diffplug.gradle.spotless.SpotlessExtension> {
|
||||
",solarxr_protocol.rpc.*,kotlinx.coroutines.*,com.illposed.osc.*,android.app.*",
|
||||
"ij_kotlin_allow_trailing_comma" to true,
|
||||
)
|
||||
val ktlintVersion = "1.2.1"
|
||||
val ktlintVersion = "1.7.1"
|
||||
kotlinGradle {
|
||||
target("**/*.gradle.kts") // default target for kotlinGradle
|
||||
ktlint(ktlintVersion)
|
||||
@@ -61,8 +61,8 @@ configure<com.diffplug.gradle.spotless.SpotlessExtension> {
|
||||
|
||||
removeUnusedImports()
|
||||
// Use eclipse JDT formatter
|
||||
eclipse()
|
||||
eclipse("4.36")
|
||||
.configFile("spotless.xml")
|
||||
.withP2Mirrors(mapOf("https://download.eclipse.org/" to "https://mirror.umd.edu/eclipse/"))
|
||||
// .withP2Mirrors(mapOf("https://download.eclipse.org/" to "https://mirror.umd.edu/eclipse/"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,13 +455,17 @@ object FastMath {
|
||||
val det13 = m21 * m33 - m23 * m31
|
||||
val det23 = m22 * m33 - m23 * m32
|
||||
return (
|
||||
m00 * (m11 * det23 - m12 * det13 + m13 * det12) -
|
||||
m00 *
|
||||
(m11 * det23 - m12 * det13 + m13 * det12) -
|
||||
m01
|
||||
* (m10 * det23 - m12 * det03 + m13 * det02) +
|
||||
*
|
||||
(m10 * det23 - m12 * det03 + m13 * det02) +
|
||||
m02
|
||||
* (m10 * det13 - m11 * det03 + m13 * det01) -
|
||||
*
|
||||
(m10 * det13 - m11 * det03 + m13 * det01) -
|
||||
m03
|
||||
* (m10 * det12 - m11 * det02 + m12 * det01)
|
||||
*
|
||||
(m10 * det12 - m11 * det02 + m12 * det01)
|
||||
).toFloat()
|
||||
}
|
||||
|
||||
@@ -606,7 +610,7 @@ object FastMath {
|
||||
*
|
||||
* Source:
|
||||
* [
|
||||
* http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf](http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf)<br></br>
|
||||
* http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf](http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf)<br></br>
|
||||
* **broken link**
|
||||
*
|
||||
* @param half The half floating point value as a short.
|
||||
|
||||
@@ -42,6 +42,7 @@ class BodyProportionError : IAutoBoneError {
|
||||
|
||||
// "Expected" are values from Drillis and Contini (1966)
|
||||
// Default are values from experimentation by the SlimeVR community
|
||||
|
||||
/**
|
||||
* Proportions are based off the headset height (or eye height), not the total height of the user.
|
||||
* To use the total height of the user, multiply it by [eyeHeightToHeightRatio] and use that in the limiters.
|
||||
|
||||
@@ -20,7 +20,8 @@ class SlideError : IAutoBoneError {
|
||||
return (
|
||||
getSlideError(skeleton1, skeleton2, BoneType.LEFT_LOWER_LEG) +
|
||||
getSlideError(skeleton1, skeleton2, BoneType.RIGHT_LOWER_LEG)
|
||||
) / 2f
|
||||
) /
|
||||
2f
|
||||
}
|
||||
|
||||
fun getSlideError(
|
||||
|
||||
@@ -11,52 +11,38 @@ import kotlin.math.*
|
||||
@JvmInline
|
||||
value class Angle(private val rad: Float) {
|
||||
|
||||
fun toRad() =
|
||||
rad
|
||||
fun toRad() = rad
|
||||
|
||||
fun toDeg() =
|
||||
rad * FastMath.RAD_TO_DEG
|
||||
fun toDeg() = rad * FastMath.RAD_TO_DEG
|
||||
|
||||
operator fun unaryPlus() =
|
||||
this
|
||||
operator fun unaryPlus() = this
|
||||
|
||||
operator fun unaryMinus() =
|
||||
Angle(normalize(-rad))
|
||||
operator fun unaryMinus() = Angle(normalize(-rad))
|
||||
|
||||
operator fun plus(other: Angle) =
|
||||
Angle(normalize(rad + other.rad))
|
||||
operator fun plus(other: Angle) = Angle(normalize(rad + other.rad))
|
||||
|
||||
operator fun minus(other: Angle) =
|
||||
Angle(normalize(rad - other.rad))
|
||||
operator fun minus(other: Angle) = Angle(normalize(rad - other.rad))
|
||||
|
||||
operator fun times(scale: Float) =
|
||||
Angle(normalize(rad * scale))
|
||||
operator fun times(scale: Float) = Angle(normalize(rad * scale))
|
||||
|
||||
operator fun div(scale: Float) =
|
||||
Angle(normalize(rad / scale))
|
||||
operator fun div(scale: Float) = Angle(normalize(rad / scale))
|
||||
|
||||
operator fun compareTo(other: Angle) =
|
||||
rad.compareTo(other.rad)
|
||||
operator fun compareTo(other: Angle) = rad.compareTo(other.rad)
|
||||
|
||||
override fun toString() =
|
||||
"${toDeg()} deg"
|
||||
override fun toString() = "${toDeg()} deg"
|
||||
|
||||
companion object {
|
||||
val ZERO = Angle(0.0f)
|
||||
|
||||
fun ofRad(rad: Float) =
|
||||
Angle(normalize(rad))
|
||||
fun ofRad(rad: Float) = Angle(normalize(rad))
|
||||
|
||||
fun ofDeg(deg: Float) =
|
||||
Angle(normalize(deg * FastMath.DEG_TO_RAD))
|
||||
fun ofDeg(deg: Float) = Angle(normalize(deg * FastMath.DEG_TO_RAD))
|
||||
|
||||
// Angle between two vectors
|
||||
fun absBetween(a: Vector3, b: Vector3) =
|
||||
Angle(normalize(a.angleTo(b)))
|
||||
fun absBetween(a: Vector3, b: Vector3) = Angle(normalize(a.angleTo(b)))
|
||||
|
||||
// Angle between two rotations in rotation space
|
||||
fun absBetween(a: Quaternion, b: Quaternion) =
|
||||
Angle(normalize(a.angleToR(b)))
|
||||
fun absBetween(a: Quaternion, b: Quaternion) = Angle(normalize(a.angleToR(b)))
|
||||
|
||||
/**
|
||||
* Normalizes an angle to [-PI, PI)
|
||||
|
||||
@@ -23,16 +23,14 @@ class AngleAverage {
|
||||
/**
|
||||
* Gets the average angle.
|
||||
*/
|
||||
fun toAngle(): Angle =
|
||||
if (isEmpty()) {
|
||||
Angle.ZERO
|
||||
} else {
|
||||
Angle.ofRad(atan2(sumY, sumX))
|
||||
}
|
||||
fun toAngle(): Angle = if (isEmpty()) {
|
||||
Angle.ZERO
|
||||
} else {
|
||||
Angle.ofRad(atan2(sumY, sumX))
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether there are any angles to average.
|
||||
*/
|
||||
fun isEmpty() =
|
||||
sumX == 0.0f && sumY == 0.0f
|
||||
fun isEmpty() = sumX == 0.0f && sumY == 0.0f
|
||||
}
|
||||
|
||||
@@ -10,6 +10,5 @@ class AngleErrors {
|
||||
sumSqrErrors += error.toRad() * error.toRad()
|
||||
}
|
||||
|
||||
fun toL2Norm() =
|
||||
Angle.ofRad(sqrt(sumSqrErrors))
|
||||
fun toL2Norm() = Angle.ofRad(sqrt(sumSqrErrors))
|
||||
}
|
||||
|
||||
@@ -216,7 +216,8 @@ class UnityArmature(localRot: Boolean) {
|
||||
val hipsAverage = (
|
||||
leftHipNode.worldTransform.translation +
|
||||
rightHipNode.worldTransform.translation
|
||||
) * 0.5f
|
||||
) *
|
||||
0.5f
|
||||
node.worldTransform.translation * 2f - hipsAverage + rootPosition
|
||||
} else {
|
||||
node.worldTransform.translation + rootPosition
|
||||
@@ -233,7 +234,8 @@ class UnityArmature(localRot: Boolean) {
|
||||
val hipsAverage = (
|
||||
leftHipNode.worldTransform.translation +
|
||||
rightHipNode.worldTransform.translation
|
||||
) * 0.5f
|
||||
) *
|
||||
0.5f
|
||||
node.worldTransform.translation * 2f - hipsAverage + rootPosition
|
||||
} else {
|
||||
node.localTransform.translation
|
||||
|
||||
@@ -244,51 +244,103 @@ enum class UnityBone(
|
||||
/**
|
||||
* Returns true if the bone is part of the left arm (incl. fingers, excl. shoulder)
|
||||
*/
|
||||
fun isLeftArmBone(bone: UnityBone): Boolean = bone == LEFT_UPPER_ARM || bone == LEFT_LOWER_ARM || bone == LEFT_HAND ||
|
||||
bone == LEFT_THUMB_PROXIMAL || bone == LEFT_THUMB_INTERMEDIATE || bone == LEFT_THUMB_DISTAL ||
|
||||
bone == LEFT_INDEX_PROXIMAL || bone == LEFT_INDEX_INTERMEDIATE || bone == LEFT_INDEX_DISTAL ||
|
||||
bone == LEFT_MIDDLE_PROXIMAL || bone == LEFT_MIDDLE_INTERMEDIATE || bone == LEFT_MIDDLE_DISTAL ||
|
||||
bone == LEFT_RING_PROXIMAL || bone == LEFT_RING_INTERMEDIATE || bone == LEFT_RING_DISTAL ||
|
||||
bone == LEFT_LITTLE_PROXIMAL || bone == LEFT_LITTLE_INTERMEDIATE || bone == LEFT_LITTLE_DISTAL
|
||||
fun isLeftArmBone(bone: UnityBone): Boolean = bone == LEFT_UPPER_ARM ||
|
||||
bone == LEFT_LOWER_ARM ||
|
||||
bone == LEFT_HAND ||
|
||||
bone == LEFT_THUMB_PROXIMAL ||
|
||||
bone == LEFT_THUMB_INTERMEDIATE ||
|
||||
bone == LEFT_THUMB_DISTAL ||
|
||||
bone == LEFT_INDEX_PROXIMAL ||
|
||||
bone == LEFT_INDEX_INTERMEDIATE ||
|
||||
bone == LEFT_INDEX_DISTAL ||
|
||||
bone == LEFT_MIDDLE_PROXIMAL ||
|
||||
bone == LEFT_MIDDLE_INTERMEDIATE ||
|
||||
bone == LEFT_MIDDLE_DISTAL ||
|
||||
bone == LEFT_RING_PROXIMAL ||
|
||||
bone == LEFT_RING_INTERMEDIATE ||
|
||||
bone == LEFT_RING_DISTAL ||
|
||||
bone == LEFT_LITTLE_PROXIMAL ||
|
||||
bone == LEFT_LITTLE_INTERMEDIATE ||
|
||||
bone == LEFT_LITTLE_DISTAL
|
||||
|
||||
/**
|
||||
* Returns true if the bone is part of the right arm (incl. fingers, excl. shoulder)
|
||||
*/
|
||||
fun isRightArmBone(bone: UnityBone): Boolean = bone == RIGHT_UPPER_ARM || bone == RIGHT_LOWER_ARM || bone == RIGHT_HAND ||
|
||||
bone == RIGHT_THUMB_PROXIMAL || bone == RIGHT_THUMB_INTERMEDIATE || bone == RIGHT_THUMB_DISTAL ||
|
||||
bone == RIGHT_INDEX_PROXIMAL || bone == RIGHT_INDEX_INTERMEDIATE || bone == RIGHT_INDEX_DISTAL ||
|
||||
bone == RIGHT_MIDDLE_PROXIMAL || bone == RIGHT_MIDDLE_INTERMEDIATE || bone == RIGHT_MIDDLE_DISTAL ||
|
||||
bone == RIGHT_RING_PROXIMAL || bone == RIGHT_RING_INTERMEDIATE || bone == RIGHT_RING_DISTAL ||
|
||||
bone == RIGHT_LITTLE_PROXIMAL || bone == RIGHT_LITTLE_INTERMEDIATE || bone == RIGHT_LITTLE_DISTAL
|
||||
fun isRightArmBone(bone: UnityBone): Boolean = bone == RIGHT_UPPER_ARM ||
|
||||
bone == RIGHT_LOWER_ARM ||
|
||||
bone == RIGHT_HAND ||
|
||||
bone == RIGHT_THUMB_PROXIMAL ||
|
||||
bone == RIGHT_THUMB_INTERMEDIATE ||
|
||||
bone == RIGHT_THUMB_DISTAL ||
|
||||
bone == RIGHT_INDEX_PROXIMAL ||
|
||||
bone == RIGHT_INDEX_INTERMEDIATE ||
|
||||
bone == RIGHT_INDEX_DISTAL ||
|
||||
bone == RIGHT_MIDDLE_PROXIMAL ||
|
||||
bone == RIGHT_MIDDLE_INTERMEDIATE ||
|
||||
bone == RIGHT_MIDDLE_DISTAL ||
|
||||
bone == RIGHT_RING_PROXIMAL ||
|
||||
bone == RIGHT_RING_INTERMEDIATE ||
|
||||
bone == RIGHT_RING_DISTAL ||
|
||||
bone == RIGHT_LITTLE_PROXIMAL ||
|
||||
bone == RIGHT_LITTLE_INTERMEDIATE ||
|
||||
bone == RIGHT_LITTLE_DISTAL
|
||||
|
||||
/**
|
||||
* Returns true if the bone is the left upper arm or proximal left finger bone
|
||||
*/
|
||||
fun isLeftStartOfArmOrFingerBone(bone: UnityBone): Boolean = bone == LEFT_UPPER_ARM || bone == LEFT_THUMB_PROXIMAL ||
|
||||
bone == LEFT_INDEX_PROXIMAL || bone == LEFT_MIDDLE_PROXIMAL || bone == LEFT_RING_PROXIMAL || bone == LEFT_LITTLE_PROXIMAL
|
||||
fun isLeftStartOfArmOrFingerBone(bone: UnityBone): Boolean = bone == LEFT_UPPER_ARM ||
|
||||
bone == LEFT_THUMB_PROXIMAL ||
|
||||
bone == LEFT_INDEX_PROXIMAL ||
|
||||
bone == LEFT_MIDDLE_PROXIMAL ||
|
||||
bone == LEFT_RING_PROXIMAL ||
|
||||
bone == LEFT_LITTLE_PROXIMAL
|
||||
|
||||
/**
|
||||
* Returns true if the bone is the right upper arm or proximal right finger bone
|
||||
*/
|
||||
fun isRightStartOfArmOrFingerBone(bone: UnityBone): Boolean = bone == RIGHT_UPPER_ARM || bone == RIGHT_THUMB_PROXIMAL ||
|
||||
bone == RIGHT_INDEX_PROXIMAL || bone == RIGHT_MIDDLE_PROXIMAL || bone == RIGHT_RING_PROXIMAL || bone == RIGHT_LITTLE_PROXIMAL
|
||||
fun isRightStartOfArmOrFingerBone(bone: UnityBone): Boolean = bone == RIGHT_UPPER_ARM ||
|
||||
bone == RIGHT_THUMB_PROXIMAL ||
|
||||
bone == RIGHT_INDEX_PROXIMAL ||
|
||||
bone == RIGHT_MIDDLE_PROXIMAL ||
|
||||
bone == RIGHT_RING_PROXIMAL ||
|
||||
bone == RIGHT_LITTLE_PROXIMAL
|
||||
|
||||
/**
|
||||
* Returns true if the bone is part of the left fingers
|
||||
*/
|
||||
fun isLeftFingerBone(bone: UnityBone): Boolean = bone == LEFT_THUMB_PROXIMAL || bone == LEFT_THUMB_INTERMEDIATE || bone == LEFT_THUMB_DISTAL ||
|
||||
bone == LEFT_INDEX_PROXIMAL || bone == LEFT_INDEX_INTERMEDIATE || bone == LEFT_INDEX_DISTAL ||
|
||||
bone == LEFT_MIDDLE_PROXIMAL || bone == LEFT_MIDDLE_INTERMEDIATE || bone == LEFT_MIDDLE_DISTAL ||
|
||||
bone == LEFT_RING_PROXIMAL || bone == LEFT_RING_INTERMEDIATE || bone == LEFT_RING_DISTAL ||
|
||||
bone == LEFT_LITTLE_PROXIMAL || bone == LEFT_LITTLE_INTERMEDIATE || bone == LEFT_LITTLE_DISTAL
|
||||
fun isLeftFingerBone(bone: UnityBone): Boolean = bone == LEFT_THUMB_PROXIMAL ||
|
||||
bone == LEFT_THUMB_INTERMEDIATE ||
|
||||
bone == LEFT_THUMB_DISTAL ||
|
||||
bone == LEFT_INDEX_PROXIMAL ||
|
||||
bone == LEFT_INDEX_INTERMEDIATE ||
|
||||
bone == LEFT_INDEX_DISTAL ||
|
||||
bone == LEFT_MIDDLE_PROXIMAL ||
|
||||
bone == LEFT_MIDDLE_INTERMEDIATE ||
|
||||
bone == LEFT_MIDDLE_DISTAL ||
|
||||
bone == LEFT_RING_PROXIMAL ||
|
||||
bone == LEFT_RING_INTERMEDIATE ||
|
||||
bone == LEFT_RING_DISTAL ||
|
||||
bone == LEFT_LITTLE_PROXIMAL ||
|
||||
bone == LEFT_LITTLE_INTERMEDIATE ||
|
||||
bone == LEFT_LITTLE_DISTAL
|
||||
|
||||
/**
|
||||
* Returns true if the bone part of the right fingers
|
||||
*/
|
||||
fun isRightFingerBone(bone: UnityBone): Boolean = bone == RIGHT_THUMB_PROXIMAL || bone == RIGHT_THUMB_INTERMEDIATE || bone == RIGHT_THUMB_DISTAL ||
|
||||
bone == RIGHT_INDEX_PROXIMAL || bone == RIGHT_INDEX_INTERMEDIATE || bone == RIGHT_INDEX_DISTAL ||
|
||||
bone == RIGHT_MIDDLE_PROXIMAL || bone == RIGHT_MIDDLE_INTERMEDIATE || bone == RIGHT_MIDDLE_DISTAL ||
|
||||
bone == RIGHT_RING_PROXIMAL || bone == RIGHT_RING_INTERMEDIATE || bone == RIGHT_RING_DISTAL ||
|
||||
bone == RIGHT_LITTLE_PROXIMAL || bone == RIGHT_LITTLE_INTERMEDIATE || bone == RIGHT_LITTLE_DISTAL
|
||||
fun isRightFingerBone(bone: UnityBone): Boolean = bone == RIGHT_THUMB_PROXIMAL ||
|
||||
bone == RIGHT_THUMB_INTERMEDIATE ||
|
||||
bone == RIGHT_THUMB_DISTAL ||
|
||||
bone == RIGHT_INDEX_PROXIMAL ||
|
||||
bone == RIGHT_INDEX_INTERMEDIATE ||
|
||||
bone == RIGHT_INDEX_DISTAL ||
|
||||
bone == RIGHT_MIDDLE_PROXIMAL ||
|
||||
bone == RIGHT_MIDDLE_INTERMEDIATE ||
|
||||
bone == RIGHT_MIDDLE_DISTAL ||
|
||||
bone == RIGHT_RING_PROXIMAL ||
|
||||
bone == RIGHT_RING_INTERMEDIATE ||
|
||||
bone == RIGHT_RING_DISTAL ||
|
||||
bone == RIGHT_LITTLE_PROXIMAL ||
|
||||
bone == RIGHT_LITTLE_INTERMEDIATE ||
|
||||
bone == RIGHT_LITTLE_DISTAL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,8 +428,7 @@ class VMCHandler(
|
||||
val role = tracker.trackerPosition
|
||||
address = if (role == TrackerPosition.HEAD) {
|
||||
"/VMC/Ext/Hmd/Pos"
|
||||
} else if (role == TrackerPosition.LEFT_HAND || role == TrackerPosition.RIGHT_HAND
|
||||
) {
|
||||
} else if (role == TrackerPosition.LEFT_HAND || role == TrackerPosition.RIGHT_HAND) {
|
||||
"/VMC/Ext/Con/Pos"
|
||||
} else {
|
||||
"/VMC/Ext/Tra/Pos"
|
||||
|
||||
@@ -385,8 +385,10 @@ class VRCOSCHandler(
|
||||
event.message.arguments[0] as Float,
|
||||
event.message.arguments[1] as Float,
|
||||
-(event.message.arguments[2] as Float),
|
||||
) - receivingPositionOffset,
|
||||
) + postReceivingPositionOffset
|
||||
) -
|
||||
receivingPositionOffset,
|
||||
) +
|
||||
postReceivingPositionOffset
|
||||
} else {
|
||||
// Update tracker rotation
|
||||
val (w, x, y, z) = EulerAngles(
|
||||
|
||||
@@ -178,8 +178,7 @@ object PfrIO {
|
||||
null
|
||||
}
|
||||
|
||||
fun readFromFile(file: File): PoseFrames =
|
||||
DataInputStream(BufferedInputStream(FileInputStream(file))).use { readFrames(it) }
|
||||
fun readFromFile(file: File): PoseFrames = DataInputStream(BufferedInputStream(FileInputStream(file))).use { readFrames(it) }
|
||||
|
||||
fun tryReadFromFile(file: File): PoseFrames? = try {
|
||||
readFromFile(file)
|
||||
|
||||
@@ -186,8 +186,7 @@ object PfsIO {
|
||||
null
|
||||
}
|
||||
|
||||
fun readFromFile(file: File): PoseFrames =
|
||||
DataInputStream(BufferedInputStream(FileInputStream(file))).use { readFrames(it) }
|
||||
fun readFromFile(file: File): PoseFrames = DataInputStream(BufferedInputStream(FileInputStream(file))).use { readFrames(it) }
|
||||
|
||||
fun tryReadFromFile(file: File): PoseFrames? = try {
|
||||
readFromFile(file)
|
||||
|
||||
@@ -46,6 +46,7 @@ class PoseFrames : Iterable<Array<TrackerFrame?>> {
|
||||
}
|
||||
|
||||
// region Data Utilities
|
||||
|
||||
/**
|
||||
* @return The maximum Y value of the [TrackerFrames] associated with the
|
||||
* [TrackerPosition.HEAD] tracker position on the first frame, otherwise `0f` if
|
||||
|
||||
@@ -403,8 +403,7 @@ class RPCHandler(private val api: ProtocolAPI) : ProtocolHandler<RpcMessageHeade
|
||||
val tracker = api.server.getTrackerById(req.trackerId().unpack()) ?: return
|
||||
|
||||
val pos = getByBodyPart(req.bodyPosition())
|
||||
val previousTracker = if (pos != null
|
||||
) {
|
||||
val previousTracker = if (pos != null) {
|
||||
getTrackerForSkeleton(api.server.allTrackers, pos)
|
||||
} else {
|
||||
null
|
||||
|
||||
@@ -9,25 +9,24 @@ object RPCSettingsBuilderKotlin {
|
||||
fun createStayAlignedSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
config: StayAlignedConfig,
|
||||
): Int =
|
||||
StayAlignedSettings
|
||||
.createStayAlignedSettings(
|
||||
fbb,
|
||||
config.enabled,
|
||||
false, // deprecated
|
||||
config.hideYawCorrection,
|
||||
config.standingRelaxedPose.enabled,
|
||||
config.standingRelaxedPose.upperLegAngleInDeg,
|
||||
config.standingRelaxedPose.lowerLegAngleInDeg,
|
||||
config.standingRelaxedPose.footAngleInDeg,
|
||||
config.sittingRelaxedPose.enabled,
|
||||
config.sittingRelaxedPose.upperLegAngleInDeg,
|
||||
config.sittingRelaxedPose.lowerLegAngleInDeg,
|
||||
config.sittingRelaxedPose.footAngleInDeg,
|
||||
config.flatRelaxedPose.enabled,
|
||||
config.flatRelaxedPose.upperLegAngleInDeg,
|
||||
config.flatRelaxedPose.lowerLegAngleInDeg,
|
||||
config.flatRelaxedPose.footAngleInDeg,
|
||||
config.setupComplete,
|
||||
)
|
||||
): Int = StayAlignedSettings
|
||||
.createStayAlignedSettings(
|
||||
fbb,
|
||||
config.enabled,
|
||||
false, // deprecated
|
||||
config.hideYawCorrection,
|
||||
config.standingRelaxedPose.enabled,
|
||||
config.standingRelaxedPose.upperLegAngleInDeg,
|
||||
config.standingRelaxedPose.lowerLegAngleInDeg,
|
||||
config.standingRelaxedPose.footAngleInDeg,
|
||||
config.sittingRelaxedPose.enabled,
|
||||
config.sittingRelaxedPose.upperLegAngleInDeg,
|
||||
config.sittingRelaxedPose.lowerLegAngleInDeg,
|
||||
config.sittingRelaxedPose.footAngleInDeg,
|
||||
config.flatRelaxedPose.enabled,
|
||||
config.flatRelaxedPose.upperLegAngleInDeg,
|
||||
config.flatRelaxedPose.lowerLegAngleInDeg,
|
||||
config.flatRelaxedPose.footAngleInDeg,
|
||||
config.setupComplete,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -45,8 +45,7 @@ abstract class SerialHandler {
|
||||
// VNC2 with FT232Slave
|
||||
Pair(0x0403, 0x6001),
|
||||
)
|
||||
fun isKnownBoard(port: SerialPort): Boolean =
|
||||
supportedSerial.contains(Pair(port.vendorId, port.productId))
|
||||
fun isKnownBoard(port: SerialPort): Boolean = supportedSerial.contains(Pair(port.vendorId, port.productId))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,13 +84,12 @@ class Constraint(
|
||||
COMPLETE,
|
||||
}
|
||||
|
||||
private fun constraintTypeToFunc(type: ConstraintType) =
|
||||
when (type) {
|
||||
ConstraintType.COMPLETE -> completeConstraint
|
||||
ConstraintType.TWIST_SWING -> twistSwingConstraint
|
||||
ConstraintType.HINGE -> hingeConstraint
|
||||
ConstraintType.LOOSE_HINGE -> looseHingeConstraint
|
||||
}
|
||||
private fun constraintTypeToFunc(type: ConstraintType) = when (type) {
|
||||
ConstraintType.COMPLETE -> completeConstraint
|
||||
ConstraintType.TWIST_SWING -> twistSwingConstraint
|
||||
ConstraintType.HINGE -> hingeConstraint
|
||||
ConstraintType.LOOSE_HINGE -> looseHingeConstraint
|
||||
}
|
||||
|
||||
private fun getLocalRotation(rotation: Quaternion, thisBone: Bone, parent: Bone): Quaternion {
|
||||
val localRotationOffset = parent.rotationOffset.inv() * thisBone.rotationOffset
|
||||
|
||||
@@ -340,6 +340,7 @@ class HumanPoseManager(val server: VRServer?) {
|
||||
|
||||
// #endregion
|
||||
// #region config methods
|
||||
|
||||
/**
|
||||
* @param key the offset from which to get the corresponding value
|
||||
* @return the offset in config corresponding to the key
|
||||
@@ -526,7 +527,8 @@ class HumanPoseManager(val server: VRServer?) {
|
||||
if ((
|
||||
tracker.isImu() &&
|
||||
tracker.needsReset
|
||||
) && tracker.resetsHandler.lastResetQuaternion != null
|
||||
) &&
|
||||
tracker.resetsHandler.lastResetQuaternion != null
|
||||
) {
|
||||
if (trackersDriftText.isNotEmpty()) {
|
||||
trackersDriftText.append(" | ")
|
||||
@@ -534,7 +536,8 @@ class HumanPoseManager(val server: VRServer?) {
|
||||
|
||||
// Get the difference between last reset and now
|
||||
val difference = tracker
|
||||
.getRotationNoResetSmooth() * tracker.resetsHandler.lastResetQuaternion!!.inv()
|
||||
.getRotationNoResetSmooth() *
|
||||
tracker.resetsHandler.lastResetQuaternion!!.inv()
|
||||
// Get the pure yaw
|
||||
var trackerDriftAngle = abs(
|
||||
(
|
||||
|
||||
@@ -437,16 +437,36 @@ class HumanSkeleton(
|
||||
hasKneeTrackers = leftUpperLegTracker != null && rightUpperLegTracker != null
|
||||
hasLeftArmTracker = leftLowerArmTracker != null || leftUpperArmTracker != null
|
||||
hasRightArmTracker = rightLowerArmTracker != null || rightUpperArmTracker != null
|
||||
hasLeftFingerTracker = leftThumbMetacarpalTracker != null || leftThumbProximalTracker != null || leftThumbDistalTracker != null ||
|
||||
leftIndexProximalTracker != null || leftIndexIntermediateTracker != null || leftIndexDistalTracker != null ||
|
||||
leftMiddleProximalTracker != null || leftMiddleIntermediateTracker != null || leftMiddleDistalTracker != null ||
|
||||
leftRingProximalTracker != null || leftRingIntermediateTracker != null || leftRingDistalTracker != null ||
|
||||
leftLittleProximalTracker != null || leftLittleIntermediateTracker != null || leftLittleDistalTracker != null
|
||||
hasRightFingerTracker = rightThumbMetacarpalTracker != null || rightThumbProximalTracker != null || rightThumbDistalTracker != null ||
|
||||
rightIndexProximalTracker != null || rightIndexIntermediateTracker != null || rightIndexDistalTracker != null ||
|
||||
rightMiddleProximalTracker != null || rightMiddleIntermediateTracker != null || rightMiddleDistalTracker != null ||
|
||||
rightRingProximalTracker != null || rightRingIntermediateTracker != null || rightRingDistalTracker != null ||
|
||||
rightLittleProximalTracker != null || rightLittleIntermediateTracker != null || rightLittleDistalTracker != null
|
||||
hasLeftFingerTracker = leftThumbMetacarpalTracker != null ||
|
||||
leftThumbProximalTracker != null ||
|
||||
leftThumbDistalTracker != null ||
|
||||
leftIndexProximalTracker != null ||
|
||||
leftIndexIntermediateTracker != null ||
|
||||
leftIndexDistalTracker != null ||
|
||||
leftMiddleProximalTracker != null ||
|
||||
leftMiddleIntermediateTracker != null ||
|
||||
leftMiddleDistalTracker != null ||
|
||||
leftRingProximalTracker != null ||
|
||||
leftRingIntermediateTracker != null ||
|
||||
leftRingDistalTracker != null ||
|
||||
leftLittleProximalTracker != null ||
|
||||
leftLittleIntermediateTracker != null ||
|
||||
leftLittleDistalTracker != null
|
||||
hasRightFingerTracker = rightThumbMetacarpalTracker != null ||
|
||||
rightThumbProximalTracker != null ||
|
||||
rightThumbDistalTracker != null ||
|
||||
rightIndexProximalTracker != null ||
|
||||
rightIndexIntermediateTracker != null ||
|
||||
rightIndexDistalTracker != null ||
|
||||
rightMiddleProximalTracker != null ||
|
||||
rightMiddleIntermediateTracker != null ||
|
||||
rightMiddleDistalTracker != null ||
|
||||
rightRingProximalTracker != null ||
|
||||
rightRingIntermediateTracker != null ||
|
||||
rightRingDistalTracker != null ||
|
||||
rightLittleProximalTracker != null ||
|
||||
rightLittleIntermediateTracker != null ||
|
||||
rightLittleDistalTracker != null
|
||||
|
||||
// Rebuilds the arm skeleton nodes attachments
|
||||
assembleSkeletonArms(true)
|
||||
@@ -1208,7 +1228,8 @@ class HumanSkeleton(
|
||||
}
|
||||
// If trackingArmFromController, reverse
|
||||
if (((boneType == BoneType.LEFT_LOWER_ARM || boneType == BoneType.LEFT_HAND) && isTrackingLeftArmFromController) ||
|
||||
(boneType == BoneType.RIGHT_LOWER_ARM || boneType == BoneType.RIGHT_HAND) && isTrackingRightArmFromController
|
||||
(boneType == BoneType.RIGHT_LOWER_ARM || boneType == BoneType.RIGHT_HAND) &&
|
||||
isTrackingRightArmFromController
|
||||
) {
|
||||
transOffset = -transOffset
|
||||
}
|
||||
|
||||
@@ -9,8 +9,7 @@ class IKConstraint(val tracker: Tracker) {
|
||||
private var offset = Vector3.NULL
|
||||
private var rotationOffset = Quaternion.IDENTITY
|
||||
|
||||
fun getPosition(): Vector3 =
|
||||
tracker.position + (tracker.getRotation() * rotationOffset).sandwich(offset)
|
||||
fun getPosition(): Vector3 = tracker.position + (tracker.getRotation() * rotationOffset).sandwich(offset)
|
||||
|
||||
fun reset(nodePosition: Vector3) {
|
||||
val bodyPartsToSkip = setOf(BodyPart.LEFT_HAND, BodyPart.RIGHT_HAND)
|
||||
|
||||
@@ -369,11 +369,15 @@ class LegTweaks(private val skeleton: HumanSkeleton) {
|
||||
|
||||
// update the buffer
|
||||
val leftFloorLevel: Float = (
|
||||
floorLevel + footLength * getFootOffset(leftFootRotation) -
|
||||
floorLevel +
|
||||
footLength *
|
||||
getFootOffset(leftFootRotation) -
|
||||
currentDisengagementOffset
|
||||
)
|
||||
val rightFloorLevel: Float = (
|
||||
floorLevel + footLength * getFootOffset(rightFootRotation) -
|
||||
floorLevel +
|
||||
footLength *
|
||||
getFootOffset(rightFootRotation) -
|
||||
currentDisengagementOffset
|
||||
)
|
||||
val leftFootAccel =
|
||||
@@ -427,12 +431,17 @@ class LegTweaks(private val skeleton: HumanSkeleton) {
|
||||
|
||||
// move the feet to their new positions
|
||||
if (leftFootPosition.y
|
||||
< floorLevel + footLength * leftOffset -
|
||||
< floorLevel +
|
||||
footLength *
|
||||
leftOffset -
|
||||
currentDisengagementOffset
|
||||
) {
|
||||
val displacement = abs(
|
||||
(
|
||||
floorLevel + footLength * leftOffset - leftFootPosition.y -
|
||||
floorLevel +
|
||||
footLength *
|
||||
leftOffset -
|
||||
leftFootPosition.y -
|
||||
currentDisengagementOffset
|
||||
),
|
||||
)
|
||||
@@ -450,12 +459,17 @@ class LegTweaks(private val skeleton: HumanSkeleton) {
|
||||
}
|
||||
|
||||
if (rightFootPosition.y
|
||||
< floorLevel + footLength * rightOffset -
|
||||
< floorLevel +
|
||||
footLength *
|
||||
rightOffset -
|
||||
currentDisengagementOffset
|
||||
) {
|
||||
val displacement = abs(
|
||||
(
|
||||
floorLevel + footLength * rightOffset - rightFootPosition.y -
|
||||
floorLevel +
|
||||
footLength *
|
||||
rightOffset -
|
||||
rightFootPosition.y -
|
||||
currentDisengagementOffset
|
||||
),
|
||||
)
|
||||
@@ -551,38 +565,46 @@ class LegTweaks(private val skeleton: HumanSkeleton) {
|
||||
|
||||
if (x * footDif.x > 0) {
|
||||
newX += (
|
||||
x * weight +
|
||||
x *
|
||||
weight +
|
||||
(
|
||||
constantCorrection
|
||||
* (if (x > 0) 1 else -1) /
|
||||
*
|
||||
(if (x > 0) 1 else -1) /
|
||||
bufferHead.getTimeDelta()
|
||||
)
|
||||
)
|
||||
} else if (x * footDif.x < 0) {
|
||||
newX -= (
|
||||
x * weight +
|
||||
x *
|
||||
weight +
|
||||
(
|
||||
constantCorrection
|
||||
* (if (x > 0) 1 else -1) /
|
||||
*
|
||||
(if (x > 0) 1 else -1) /
|
||||
bufferHead.getTimeDelta()
|
||||
)
|
||||
)
|
||||
}
|
||||
if (z * footDif.z > 0) {
|
||||
newZ += (
|
||||
z * weight +
|
||||
z *
|
||||
weight +
|
||||
(
|
||||
constantCorrection
|
||||
* (if (z > 0) 1 else -1) /
|
||||
*
|
||||
(if (z > 0) 1 else -1) /
|
||||
bufferHead.getTimeDelta()
|
||||
)
|
||||
)
|
||||
} else if (z * footDif.z < 0) {
|
||||
newZ -= (
|
||||
z * weight +
|
||||
z *
|
||||
weight +
|
||||
(
|
||||
constantCorrection
|
||||
* (if (z > 0) 1 else -1) /
|
||||
*
|
||||
(if (z > 0) 1 else -1) /
|
||||
bufferHead.getTimeDelta()
|
||||
)
|
||||
)
|
||||
|
||||
@@ -501,7 +501,8 @@ class LegTweaksBuffer @Suppress("ktlint") constructor() {
|
||||
leftFootSensitivityVel = (
|
||||
(
|
||||
leftFootScalarAccel +
|
||||
leftFootScalarVel / 2.0f
|
||||
leftFootScalarVel /
|
||||
2.0f
|
||||
) *
|
||||
FastMath.clamp(
|
||||
pressureScalars[0] * 2.0f,
|
||||
@@ -512,7 +513,8 @@ class LegTweaksBuffer @Suppress("ktlint") constructor() {
|
||||
rightFootSensitivityVel = (
|
||||
(
|
||||
rightFootScalarAccel +
|
||||
rightFootScalarVel / 2.0f
|
||||
rightFootScalarVel /
|
||||
2.0f
|
||||
) *
|
||||
FastMath.clamp(
|
||||
pressureScalars[1] * 2.0f,
|
||||
@@ -535,7 +537,8 @@ class LegTweaksBuffer @Suppress("ktlint") constructor() {
|
||||
} else if (accelMagnitude > MIN_SCALAR_ACCEL) {
|
||||
return (
|
||||
PARAM_SCALAR_MAX
|
||||
* (accelMagnitude - MIN_SCALAR_ACCEL) /
|
||||
*
|
||||
(accelMagnitude - MIN_SCALAR_ACCEL) /
|
||||
(MAX_SCALAR_ACCEL - MIN_SCALAR_ACCEL)
|
||||
)
|
||||
}
|
||||
@@ -562,7 +565,8 @@ class LegTweaksBuffer @Suppress("ktlint") constructor() {
|
||||
} else if (velocityDiffMagnitude > MIN_SCALAR_DORMANT) {
|
||||
return (
|
||||
PARAM_SCALAR_MAX
|
||||
* (velocityDiffMagnitude - MIN_SCALAR_DORMANT) /
|
||||
*
|
||||
(velocityDiffMagnitude - MIN_SCALAR_DORMANT) /
|
||||
(MAX_SCALAR_DORMANT - MIN_SCALAR_DORMANT)
|
||||
)
|
||||
}
|
||||
@@ -579,7 +583,8 @@ class LegTweaksBuffer @Suppress("ktlint") constructor() {
|
||||
}
|
||||
return (
|
||||
PARAM_SCALAR_MAX
|
||||
* (velocityDiffAbs - MIN_SCALAR_ACTIVE) /
|
||||
*
|
||||
(velocityDiffAbs - MIN_SCALAR_ACTIVE) /
|
||||
(MAX_SCALAR_ACTIVE - MIN_SCALAR_ACTIVE) -
|
||||
PARAM_SCALAR_MID
|
||||
)
|
||||
@@ -602,7 +607,8 @@ class LegTweaksBuffer @Suppress("ktlint") constructor() {
|
||||
GRAVITY_MAGNITUDE * leftFootVector.y / leftFootVector.len()
|
||||
val rightFootMagnitude: Float = (
|
||||
GRAVITY_MAGNITUDE
|
||||
* rightFootVector.y /
|
||||
*
|
||||
rightFootVector.y /
|
||||
rightFootVector.len()
|
||||
)
|
||||
|
||||
|
||||
@@ -155,8 +155,7 @@ class TapDetection {
|
||||
) {
|
||||
if (skeleton.chestTracker!!.getAcceleration().lenSq() > ALLOWED_BODY_ACCEL_SQUARED) num++
|
||||
}
|
||||
if (skeleton.hipTracker != null && skeleton.hipTracker != trackerToExclude
|
||||
) {
|
||||
if (skeleton.hipTracker != null && skeleton.hipTracker != trackerToExclude) {
|
||||
if (skeleton.hipTracker!!.getAcceleration().lenSq() > ALLOWED_BODY_ACCEL_SQUARED) num++
|
||||
}
|
||||
if (skeleton.waistTracker != null &&
|
||||
@@ -185,8 +184,7 @@ class TapDetection {
|
||||
if (skeleton.leftFootTracker != null &&
|
||||
skeleton.leftFootTracker != trackerToExclude
|
||||
) {
|
||||
if (skeleton.leftFootTracker!!.getAcceleration().lenSq() > ALLOWED_BODY_ACCEL_SQUARED
|
||||
) {
|
||||
if (skeleton.leftFootTracker!!.getAcceleration().lenSq() > ALLOWED_BODY_ACCEL_SQUARED) {
|
||||
num++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,11 @@ import kotlin.time.Duration.Companion.seconds
|
||||
object StayAlignedDefaults {
|
||||
|
||||
// Rest detector for detecting when trackers are at rest
|
||||
fun makeRestDetector() =
|
||||
RestDetector(
|
||||
maxRotation = Angle.ofDeg(2.0f),
|
||||
enterRestTime = 1.seconds,
|
||||
enterMovingTime = 3.seconds,
|
||||
)
|
||||
fun makeRestDetector() = RestDetector(
|
||||
maxRotation = Angle.ofDeg(2.0f),
|
||||
enterRestTime = 1.seconds,
|
||||
enterMovingTime = 3.seconds,
|
||||
)
|
||||
|
||||
// Relaxed pose for kneeling. This isn't that common, so we don't want to ask
|
||||
// players to provide this relaxed pose during setup.
|
||||
|
||||
@@ -176,8 +176,10 @@ object AdjustTrackerYaw {
|
||||
* Calculates the gradient between two errors. A negative gradient means that there
|
||||
* is less error in that direction.
|
||||
*/
|
||||
private fun gradient(errors: YawErrors, base: YawErrors) =
|
||||
(errors.lockedError.toL2Norm() - base.lockedError.toL2Norm()) * YAW_ERRORS_LOCKED_ERROR_WEIGHT +
|
||||
(errors.centerError.toL2Norm() - base.centerError.toL2Norm()) * YAW_ERRORS_CENTER_ERROR_WEIGHT +
|
||||
(errors.neighborError.toL2Norm() - base.neighborError.toL2Norm()) * YAW_ERRORS_NEIGHBOR_ERROR_WEIGHT
|
||||
private fun gradient(errors: YawErrors, base: YawErrors) = (errors.lockedError.toL2Norm() - base.lockedError.toL2Norm()) *
|
||||
YAW_ERRORS_LOCKED_ERROR_WEIGHT +
|
||||
(errors.centerError.toL2Norm() - base.centerError.toL2Norm()) *
|
||||
YAW_ERRORS_CENTER_ERROR_WEIGHT +
|
||||
(errors.neighborError.toL2Norm() - base.neighborError.toL2Norm()) *
|
||||
YAW_ERRORS_NEIGHBOR_ERROR_WEIGHT
|
||||
}
|
||||
|
||||
@@ -88,8 +88,7 @@ class LockedErrorVisitor(
|
||||
errors.add(error(tracker))
|
||||
}
|
||||
|
||||
private fun error(tracker: Tracker): Angle =
|
||||
yawDifference(tracker.getAdjustedRotationForceStayAligned(), lockedRotation)
|
||||
private fun error(tracker: Tracker): Angle = yawDifference(tracker.getAdjustedRotationForceStayAligned(), lockedRotation)
|
||||
|
||||
companion object {
|
||||
|
||||
|
||||
@@ -21,11 +21,10 @@ object TrackerYaw {
|
||||
/**
|
||||
* Whether we can get the yaw of a tracker.
|
||||
*/
|
||||
fun hasTrackerYaw(tracker: Tracker) =
|
||||
Angle.absBetween(
|
||||
tracker.getAdjustedRotationForceStayAligned().sandwichUnitX(),
|
||||
Vector3.POS_Y,
|
||||
) > MIN_ON_SIDE_ANGLE
|
||||
fun hasTrackerYaw(tracker: Tracker) = Angle.absBetween(
|
||||
tracker.getAdjustedRotationForceStayAligned().sandwichUnitX(),
|
||||
Vector3.POS_Y,
|
||||
) > MIN_ON_SIDE_ANGLE
|
||||
|
||||
/**
|
||||
* Gets the yaw of the tracker, for trackers that are not on its side.
|
||||
@@ -39,21 +38,19 @@ object TrackerYaw {
|
||||
* singularity for this rotation to get "some" yaw, but this yaw will be very
|
||||
* different from the from YZX. DO NOT ATTEMPT!
|
||||
*/
|
||||
fun trackerYaw(tracker: Tracker) =
|
||||
Angle.ofRad(
|
||||
tracker.getAdjustedRotationForceStayAligned()
|
||||
.toEulerAngles(EulerOrder.YZX)
|
||||
.y,
|
||||
)
|
||||
fun trackerYaw(tracker: Tracker) = Angle.ofRad(
|
||||
tracker.getAdjustedRotationForceStayAligned()
|
||||
.toEulerAngles(EulerOrder.YZX)
|
||||
.y,
|
||||
)
|
||||
|
||||
/**
|
||||
* Applies an extra yaw in the specified direction.
|
||||
*/
|
||||
fun extraYaw(direction: Side, angle: Angle) =
|
||||
when (direction) {
|
||||
Side.LEFT -> angle
|
||||
Side.RIGHT -> -angle
|
||||
}
|
||||
fun extraYaw(direction: Side, angle: Angle) = when (direction) {
|
||||
Side.LEFT -> angle
|
||||
Side.RIGHT -> -angle
|
||||
}
|
||||
|
||||
private val MIN_ON_SIDE_ANGLE = Angle.ofDeg(30.0f)
|
||||
}
|
||||
|
||||
@@ -51,42 +51,39 @@ enum class PlayerPose {
|
||||
val rightLowerLeg: TrackerPose,
|
||||
)
|
||||
|
||||
private fun isStanding(pose: TrackerPoses) =
|
||||
pose.upperBody.all { it == TrackerPose.TOP_FACING_UP } &&
|
||||
pose.leftUpperLeg == TrackerPose.TOP_FACING_UP &&
|
||||
pose.rightUpperLeg == TrackerPose.TOP_FACING_UP &&
|
||||
pose.leftLowerLeg == TrackerPose.TOP_FACING_UP &&
|
||||
pose.rightLowerLeg == TrackerPose.TOP_FACING_UP
|
||||
private fun isStanding(pose: TrackerPoses) = pose.upperBody.all { it == TrackerPose.TOP_FACING_UP } &&
|
||||
pose.leftUpperLeg == TrackerPose.TOP_FACING_UP &&
|
||||
pose.rightUpperLeg == TrackerPose.TOP_FACING_UP &&
|
||||
pose.leftLowerLeg == TrackerPose.TOP_FACING_UP &&
|
||||
pose.rightLowerLeg == TrackerPose.TOP_FACING_UP
|
||||
|
||||
private fun isSittingInChair(pose: TrackerPoses) =
|
||||
pose.upperBody.isNotEmpty() && pose.upperBody[0] == TrackerPose.TOP_FACING_UP &&
|
||||
pose.upperBody.all { it == TrackerPose.TOP_FACING_UP || it == TrackerPose.FRONT_FACING_UP } &&
|
||||
pose.leftUpperLeg == TrackerPose.FRONT_FACING_UP &&
|
||||
pose.rightUpperLeg == TrackerPose.FRONT_FACING_UP &&
|
||||
pose.leftLowerLeg == TrackerPose.TOP_FACING_UP &&
|
||||
pose.rightLowerLeg == TrackerPose.TOP_FACING_UP
|
||||
private fun isSittingInChair(pose: TrackerPoses) = pose.upperBody.isNotEmpty() &&
|
||||
pose.upperBody[0] == TrackerPose.TOP_FACING_UP &&
|
||||
pose.upperBody.all { it == TrackerPose.TOP_FACING_UP || it == TrackerPose.FRONT_FACING_UP } &&
|
||||
pose.leftUpperLeg == TrackerPose.FRONT_FACING_UP &&
|
||||
pose.rightUpperLeg == TrackerPose.FRONT_FACING_UP &&
|
||||
pose.leftLowerLeg == TrackerPose.TOP_FACING_UP &&
|
||||
pose.rightLowerLeg == TrackerPose.TOP_FACING_UP
|
||||
|
||||
private fun isSittingOnGround(pose: TrackerPoses) =
|
||||
pose.upperBody.isNotEmpty() && pose.upperBody[0] == TrackerPose.TOP_FACING_UP &&
|
||||
pose.upperBody.all { it == TrackerPose.TOP_FACING_UP || it == TrackerPose.FRONT_FACING_UP } &&
|
||||
// Allow legs to be flat on ground, or knees-up
|
||||
pose.leftUpperLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_DOWN } &&
|
||||
pose.rightUpperLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_DOWN } &&
|
||||
pose.leftLowerLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_UP } &&
|
||||
pose.rightLowerLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_UP }
|
||||
private fun isSittingOnGround(pose: TrackerPoses) = pose.upperBody.isNotEmpty() &&
|
||||
pose.upperBody[0] == TrackerPose.TOP_FACING_UP &&
|
||||
pose.upperBody.all { it == TrackerPose.TOP_FACING_UP || it == TrackerPose.FRONT_FACING_UP } &&
|
||||
// Allow legs to be flat on ground, or knees-up
|
||||
pose.leftUpperLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_DOWN } &&
|
||||
pose.rightUpperLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_DOWN } &&
|
||||
pose.leftLowerLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_UP } &&
|
||||
pose.rightLowerLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_UP }
|
||||
|
||||
private fun isLyingOnBack(pose: TrackerPoses) =
|
||||
pose.upperBody.all { it == TrackerPose.FRONT_FACING_UP } &&
|
||||
// Allow legs to be flat on ground, or knees-up
|
||||
pose.leftUpperLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_DOWN } &&
|
||||
pose.rightUpperLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_DOWN } &&
|
||||
pose.leftLowerLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_UP } &&
|
||||
pose.rightLowerLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_UP }
|
||||
private fun isLyingOnBack(pose: TrackerPoses) = pose.upperBody.all { it == TrackerPose.FRONT_FACING_UP } &&
|
||||
// Allow legs to be flat on ground, or knees-up
|
||||
pose.leftUpperLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_DOWN } &&
|
||||
pose.rightUpperLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_DOWN } &&
|
||||
pose.leftLowerLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_UP } &&
|
||||
pose.rightLowerLeg.let { it == TrackerPose.FRONT_FACING_UP || it == TrackerPose.TOP_FACING_UP }
|
||||
|
||||
private fun isKneeling(pose: TrackerPoses) =
|
||||
pose.leftUpperLeg.let { it == TrackerPose.TOP_FACING_UP || it == TrackerPose.FRONT_FACING_UP } &&
|
||||
pose.rightUpperLeg.let { it == TrackerPose.TOP_FACING_UP || it == TrackerPose.FRONT_FACING_UP } &&
|
||||
pose.leftLowerLeg == TrackerPose.FRONT_FACING_DOWN &&
|
||||
pose.rightLowerLeg == TrackerPose.FRONT_FACING_DOWN
|
||||
private fun isKneeling(pose: TrackerPoses) = pose.leftUpperLeg.let { it == TrackerPose.TOP_FACING_UP || it == TrackerPose.FRONT_FACING_UP } &&
|
||||
pose.rightUpperLeg.let { it == TrackerPose.TOP_FACING_UP || it == TrackerPose.FRONT_FACING_UP } &&
|
||||
pose.leftLowerLeg == TrackerPose.FRONT_FACING_DOWN &&
|
||||
pose.rightLowerLeg == TrackerPose.FRONT_FACING_DOWN
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ class RelaxedPose(
|
||||
val lowerLeg: Angle,
|
||||
val foot: Angle,
|
||||
) {
|
||||
override fun toString(): String =
|
||||
"upperLeg=$upperLeg lowerLeg=$lowerLeg foot=$foot"
|
||||
override fun toString(): String = "upperLeg=$upperLeg lowerLeg=$lowerLeg foot=$foot"
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -26,56 +25,55 @@ class RelaxedPose(
|
||||
fun forPose(
|
||||
playerPose: PlayerPose,
|
||||
config: StayAlignedConfig,
|
||||
) =
|
||||
when (playerPose) {
|
||||
PlayerPose.STANDING -> {
|
||||
val poseConfig = config.standingRelaxedPose
|
||||
if (poseConfig.enabled) {
|
||||
RelaxedPose(
|
||||
Angle.ofDeg(poseConfig.upperLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.lowerLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.footAngleInDeg),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
PlayerPose.SITTING_IN_CHAIR -> {
|
||||
val poseConfig = config.sittingRelaxedPose
|
||||
if (poseConfig.enabled) {
|
||||
RelaxedPose(
|
||||
Angle.ofDeg(poseConfig.upperLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.lowerLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.footAngleInDeg),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
PlayerPose.SITTING_ON_GROUND,
|
||||
PlayerPose.LYING_ON_BACK,
|
||||
-> {
|
||||
val poseConfig = config.flatRelaxedPose
|
||||
if (poseConfig.enabled) {
|
||||
RelaxedPose(
|
||||
Angle.ofDeg(poseConfig.upperLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.lowerLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.footAngleInDeg),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
PlayerPose.KNEELING ->
|
||||
StayAlignedDefaults.RELAXED_POSE_KNEELING
|
||||
|
||||
else ->
|
||||
) = when (playerPose) {
|
||||
PlayerPose.STANDING -> {
|
||||
val poseConfig = config.standingRelaxedPose
|
||||
if (poseConfig.enabled) {
|
||||
RelaxedPose(
|
||||
Angle.ofDeg(poseConfig.upperLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.lowerLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.footAngleInDeg),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
PlayerPose.SITTING_IN_CHAIR -> {
|
||||
val poseConfig = config.sittingRelaxedPose
|
||||
if (poseConfig.enabled) {
|
||||
RelaxedPose(
|
||||
Angle.ofDeg(poseConfig.upperLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.lowerLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.footAngleInDeg),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
PlayerPose.SITTING_ON_GROUND,
|
||||
PlayerPose.LYING_ON_BACK,
|
||||
-> {
|
||||
val poseConfig = config.flatRelaxedPose
|
||||
if (poseConfig.enabled) {
|
||||
RelaxedPose(
|
||||
Angle.ofDeg(poseConfig.upperLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.lowerLegAngleInDeg),
|
||||
Angle.ofDeg(poseConfig.footAngleInDeg),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
PlayerPose.KNEELING ->
|
||||
StayAlignedDefaults.RELAXED_POSE_KNEELING
|
||||
|
||||
else ->
|
||||
null
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relaxed angles from the trackers.
|
||||
*/
|
||||
|
||||
@@ -178,8 +178,11 @@ class Tracker @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
fun checkReportRequireReset() {
|
||||
if (needsReset && trackerPosition != null && lastResetStatus == 0u &&
|
||||
!status.reset && (isImu() || !statusResetRecently && trackerDataType != TrackerDataType.FLEX_ANGLE)
|
||||
if (needsReset &&
|
||||
trackerPosition != null &&
|
||||
lastResetStatus == 0u &&
|
||||
!status.reset &&
|
||||
(isImu() || !statusResetRecently && trackerDataType != TrackerDataType.FLEX_ANGLE)
|
||||
) {
|
||||
reportRequireReset()
|
||||
} else if (lastResetStatus != 0u && (trackerPosition == null || status.reset)) {
|
||||
|
||||
@@ -55,6 +55,7 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
}
|
||||
|
||||
// Reference adjustment quats
|
||||
|
||||
/**
|
||||
* Gyro fix is set by full reset. This sets the current y rotation to 0, correcting
|
||||
* for initial yaw rotation and the rotation incurred by mounting orientation. This
|
||||
|
||||
@@ -233,7 +233,8 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
|
||||
}
|
||||
}
|
||||
} else if (magStatus == MagnetometerStatus.DISABLED &&
|
||||
VRServer.instance.configManager.vrConfig.server.useMagnetometerOnAllTrackers && imuTracker.config.shouldHaveMagEnabled == true
|
||||
VRServer.instance.configManager.vrConfig.server.useMagnetometerOnAllTrackers &&
|
||||
imuTracker.config.shouldHaveMagEnabled == true
|
||||
) {
|
||||
mainScope.launch {
|
||||
withTimeoutOrNull(MAG_TIMEOUT) {
|
||||
|
||||
@@ -140,7 +140,9 @@ object FloatMath {
|
||||
targetEnd: Float,
|
||||
): Float = (
|
||||
targetStart +
|
||||
(value - sourceStart) * (targetEnd - targetStart) / (sourceEnd - sourceStart)
|
||||
(value - sourceStart) *
|
||||
(targetEnd - targetStart) /
|
||||
(sourceEnd - sourceStart)
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
@@ -104,8 +104,7 @@ class FileLogHandler @JvmOverloads constructor(
|
||||
|
||||
// Log name should have at least two separators, one integer, and at
|
||||
// least one char for the datetime (4 chars)
|
||||
if (!name.startsWith(logTag) || !name.endsWith(logSuffix) || name.length < (logTag.length + logSuffix.length + 4)
|
||||
) {
|
||||
if (!name.startsWith(logTag) || !name.endsWith(logSuffix) || name.length < (logTag.length + logSuffix.length + 4)) {
|
||||
// Ignore non-matching files
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ value class EulerAngles(val order: EulerOrder, val x: Float, val y: Float, val z
|
||||
|
||||
// temp, replace with direct conversion later
|
||||
// fun toMatrix(): Matrix3 = this.toQuaternion().toMatrix()
|
||||
|
||||
/**
|
||||
* creates a matrix which represents the same rotation as this eulerAngles
|
||||
* @return the matrix
|
||||
|
||||
@@ -41,8 +41,7 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* @param vz the rotation vector's z component
|
||||
* @return the new quaternion
|
||||
**/
|
||||
fun fromRotationVector(vx: Float, vy: Float, vz: Float): Quaternion =
|
||||
fromRotationVector(Vector3(vx, vy, vz))
|
||||
fun fromRotationVector(vx: Float, vy: Float, vz: Float): Quaternion = fromRotationVector(Vector3(vx, vy, vz))
|
||||
|
||||
/**
|
||||
* finds Q, the smallest-angled quaternion whose local u direction aligns with
|
||||
@@ -65,8 +64,7 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* Derived from the axis-angle representation in
|
||||
* https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation#Unit_quaternions
|
||||
*/
|
||||
fun rotationAroundXAxis(angle: Float): Quaternion =
|
||||
Quaternion(cos(angle / 2.0f), sin(angle / 2.0f), 0.0f, 0.0f)
|
||||
fun rotationAroundXAxis(angle: Float): Quaternion = Quaternion(cos(angle / 2.0f), sin(angle / 2.0f), 0.0f, 0.0f)
|
||||
|
||||
/**
|
||||
* Rotation around Y-axis
|
||||
@@ -74,8 +72,7 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* Derived from the axis-angle representation in
|
||||
* https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation#Unit_quaternions
|
||||
*/
|
||||
fun rotationAroundYAxis(angle: Float): Quaternion =
|
||||
Quaternion(cos(angle / 2.0f), 0.0f, sin(angle / 2.0f), 0.0f)
|
||||
fun rotationAroundYAxis(angle: Float): Quaternion = Quaternion(cos(angle / 2.0f), 0.0f, sin(angle / 2.0f), 0.0f)
|
||||
|
||||
/**
|
||||
* Rotation around Z-axis
|
||||
@@ -83,8 +80,7 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* Derived from the axis-angle representation in
|
||||
* https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation#Unit_quaternions
|
||||
*/
|
||||
fun rotationAroundZAxis(angle: Float): Quaternion =
|
||||
Quaternion(cos(angle / 2.0f), 0.0f, 0.0f, sin(angle / 2.0f))
|
||||
fun rotationAroundZAxis(angle: Float): Quaternion = Quaternion(cos(angle / 2.0f), 0.0f, 0.0f, sin(angle / 2.0f))
|
||||
|
||||
/**
|
||||
* SlimeVR-specific constants and utils
|
||||
@@ -130,8 +126,7 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
this.z + that.z,
|
||||
)
|
||||
|
||||
operator fun plus(that: Float): Quaternion =
|
||||
Quaternion(this.w + that, this.x, this.y, this.z)
|
||||
operator fun plus(that: Float): Quaternion = Quaternion(this.w + that, this.x, this.y, this.z)
|
||||
|
||||
operator fun minus(that: Quaternion): Quaternion = Quaternion(
|
||||
this.w - that.w,
|
||||
@@ -140,16 +135,14 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
this.z - that.z,
|
||||
)
|
||||
|
||||
operator fun minus(that: Float): Quaternion =
|
||||
Quaternion(this.w - that, this.x, this.y, this.z)
|
||||
operator fun minus(that: Float): Quaternion = Quaternion(this.w - that, this.x, this.y, this.z)
|
||||
|
||||
/**
|
||||
* computes the dot product of this quaternion with that quaternion
|
||||
* @param that the quaternion with which to be dotted
|
||||
* @return the dot product between quaternions
|
||||
**/
|
||||
fun dot(that: Quaternion): Float =
|
||||
this.w * that.w + this.x * that.x + this.y * that.y + this.z * that.z
|
||||
fun dot(that: Quaternion): Float = this.w * that.w + this.x * that.x + this.y * that.y + this.z * that.z
|
||||
|
||||
/**
|
||||
* computes the square of the length of this quaternion
|
||||
@@ -262,16 +255,14 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* @param that the quaternion to be nearest to
|
||||
* @return nearest quaternion
|
||||
**/
|
||||
fun twinNearest(that: Quaternion): Quaternion =
|
||||
if (this.dot(that) < 0f) -this else this
|
||||
fun twinNearest(that: Quaternion): Quaternion = if (this.dot(that) < 0f) -this else this
|
||||
|
||||
/**
|
||||
* between this and -this, picks the one furthest from that quaternion
|
||||
* @param that the quaternion to be furthest from
|
||||
* @return furthest quaternion
|
||||
**/
|
||||
fun twinFurthest(that: Quaternion): Quaternion =
|
||||
if (this.dot(that) < 0f) this else -this
|
||||
fun twinFurthest(that: Quaternion): Quaternion = if (this.dot(that) < 0f) this else -this
|
||||
|
||||
/**
|
||||
* Similar to [twinNearest], but offset so the lower back quadrant is the furthest
|
||||
@@ -297,16 +288,15 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* @param t the amount to interpolate
|
||||
* @return interpolated quaternion
|
||||
**/
|
||||
fun interpQ(that: Quaternion, t: Float) =
|
||||
if (t == 0f) {
|
||||
this
|
||||
} else if (t == 1f) {
|
||||
that
|
||||
} else if (t < 0.5f) {
|
||||
(that / this).pow(t) * this
|
||||
} else {
|
||||
(this / that).pow(1f - t) * that
|
||||
}
|
||||
fun interpQ(that: Quaternion, t: Float) = if (t == 0f) {
|
||||
this
|
||||
} else if (t == 1f) {
|
||||
that
|
||||
} else if (t < 0.5f) {
|
||||
(that / this).pow(t) * this
|
||||
} else {
|
||||
(this / that).pow(1f - t) * that
|
||||
}
|
||||
|
||||
/**
|
||||
* interpolates from this quaternion to that quaternion by t in rotation space
|
||||
@@ -440,12 +430,11 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* First column of rotation matrix in
|
||||
* https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Conversion_to_and_from_the_matrix_representation
|
||||
*/
|
||||
fun sandwichUnitX(): Vector3 =
|
||||
Vector3(
|
||||
w * w + x * x - y * y - z * z,
|
||||
2.0f * (x * y + w * z),
|
||||
2.0f * (x * z - w * y),
|
||||
)
|
||||
fun sandwichUnitX(): Vector3 = Vector3(
|
||||
w * w + x * x - y * y - z * z,
|
||||
2.0f * (x * y + w * z),
|
||||
2.0f * (x * z - w * y),
|
||||
)
|
||||
|
||||
/**
|
||||
* Sandwiches the unit Y vector
|
||||
@@ -453,12 +442,11 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* Second column of rotation matrix in
|
||||
* https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Conversion_to_and_from_the_matrix_representation
|
||||
*/
|
||||
fun sandwichUnitY(): Vector3 =
|
||||
Vector3(
|
||||
2.0f * (x * y - w * z),
|
||||
w * w - x * x + y * y - z * z,
|
||||
2.0f * (y * z + w * x),
|
||||
)
|
||||
fun sandwichUnitY(): Vector3 = Vector3(
|
||||
2.0f * (x * y - w * z),
|
||||
w * w - x * x + y * y - z * z,
|
||||
2.0f * (y * z + w * x),
|
||||
)
|
||||
|
||||
/**
|
||||
* Sandwiches the unit Z vector
|
||||
@@ -466,12 +454,11 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* Third column of rotation matrix in
|
||||
* https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Conversion_to_and_from_the_matrix_representation
|
||||
*/
|
||||
fun sandwichUnitZ(): Vector3 =
|
||||
Vector3(
|
||||
2.0f * (x * z + w * y),
|
||||
2.0f * (y * z - w * x),
|
||||
w * w - x * x - y * y + z * z,
|
||||
)
|
||||
fun sandwichUnitZ(): Vector3 = Vector3(
|
||||
2.0f * (x * z + w * y),
|
||||
2.0f * (y * z - w * x),
|
||||
w * w - x * x - y * y + z * z,
|
||||
)
|
||||
|
||||
/**
|
||||
* computes this quaternion's unit length rotation axis
|
||||
@@ -503,8 +490,7 @@ value class Quaternion(val w: Float, val x: Float, val y: Float, val z: Float) {
|
||||
* @param order the order in which to decompose this quaternion into euler angles
|
||||
* @return euler angles
|
||||
**/
|
||||
fun toEulerAngles(order: EulerOrder): EulerAngles =
|
||||
this.toMatrix().toEulerAnglesAssumingOrthonormal(order)
|
||||
fun toEulerAngles(order: EulerOrder): EulerAngles = this.toMatrix().toEulerAnglesAssumingOrthonormal(order)
|
||||
|
||||
fun toObject() = ObjectQuaternion(w, x, y, z)
|
||||
}
|
||||
|
||||
@@ -100,8 +100,7 @@ value class Vector3(val x: Float, val y: Float, val z: Float) {
|
||||
**/
|
||||
fun angleTo(that: Vector3): Float = atan2(this.cross(that).len(), this.dot(that))
|
||||
|
||||
fun isNear(other: Vector3, maxError: Float = 1e-6f) =
|
||||
abs(x - other.x) <= maxError && abs(y - other.y) <= maxError && abs(z - other.z) <= maxError
|
||||
fun isNear(other: Vector3, maxError: Float = 1e-6f) = abs(x - other.x) <= maxError && abs(y - other.y) <= maxError && abs(z - other.z) <= maxError
|
||||
}
|
||||
|
||||
operator fun Float.times(that: Vector3): Vector3 = that * this
|
||||
|
||||
@@ -76,14 +76,12 @@ object TrackerTestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
fun quatApproxEqual(q1: Quaternion, q2: Quaternion, tolerance: Float = FastMath.ZERO_TOLERANCE): Boolean =
|
||||
FastMath.isApproxEqual(q1.w, q2.w, tolerance) &&
|
||||
FastMath.isApproxEqual(q1.x, q2.x, tolerance) &&
|
||||
FastMath.isApproxEqual(q1.y, q2.y, tolerance) &&
|
||||
FastMath.isApproxEqual(q1.z, q2.z, tolerance)
|
||||
fun quatApproxEqual(q1: Quaternion, q2: Quaternion, tolerance: Float = FastMath.ZERO_TOLERANCE): Boolean = FastMath.isApproxEqual(q1.w, q2.w, tolerance) &&
|
||||
FastMath.isApproxEqual(q1.x, q2.x, tolerance) &&
|
||||
FastMath.isApproxEqual(q1.y, q2.y, tolerance) &&
|
||||
FastMath.isApproxEqual(q1.z, q2.z, tolerance)
|
||||
|
||||
fun vectorApproxEqual(v1: Vector3, v2: Vector3, tolerance: Float = FastMath.ZERO_TOLERANCE): Boolean =
|
||||
FastMath.isApproxEqual(v1.x, v2.x, tolerance) &&
|
||||
FastMath.isApproxEqual(v1.y, v2.y, tolerance) &&
|
||||
FastMath.isApproxEqual(v1.z, v2.z, tolerance)
|
||||
fun vectorApproxEqual(v1: Vector3, v2: Vector3, tolerance: Float = FastMath.ZERO_TOLERANCE): Boolean = FastMath.isApproxEqual(v1.x, v2.x, tolerance) &&
|
||||
FastMath.isApproxEqual(v1.y, v2.y, tolerance) &&
|
||||
FastMath.isApproxEqual(v1.z, v2.z, tolerance)
|
||||
}
|
||||
|
||||
@@ -59,12 +59,11 @@ enum class ConnectivityFlags(val value: Int) {
|
||||
;
|
||||
|
||||
companion object {
|
||||
fun fromInt(value: Int): Set<ConnectivityFlags> =
|
||||
if (value == 0) {
|
||||
setOf(DISCONNECTED)
|
||||
} else {
|
||||
values().filter { it != DISCONNECTED && (value and it.value) != 0 }.toSet()
|
||||
}
|
||||
fun fromInt(value: Int): Set<ConnectivityFlags> = if (value == 0) {
|
||||
setOf(DISCONNECTED)
|
||||
} else {
|
||||
values().filter { it != DISCONNECTED && (value and it.value) != 0 }.toSet()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ class DesktopVRCConfigHandler : VRCConfigHandler() {
|
||||
get() = (
|
||||
OperatingSystem.currentPlatform == OperatingSystem.WINDOWS ||
|
||||
OperatingSystem.currentPlatform == OperatingSystem.LINUX
|
||||
) && vrcConfigKeys.isNotEmpty()
|
||||
) &&
|
||||
vrcConfigKeys.isNotEmpty()
|
||||
|
||||
override fun initHandler(onChange: (config: VRCConfigValues) -> Unit) {
|
||||
this.onChange = onChange
|
||||
|
||||
@@ -389,7 +389,8 @@ abstract class SteamVRBridge(
|
||||
// readings.
|
||||
if (((lowestLevel >= 200) || (lowestLevel < 0)) ||
|
||||
(
|
||||
(trackerVoltage < 3.2) && (lowestLevel <= 0) ||
|
||||
(trackerVoltage < 3.2) &&
|
||||
(lowestLevel <= 0) ||
|
||||
((trackerVoltage >= 5) && (lowestLevel > 150))
|
||||
)
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user