Compare commits

...

3 Commits
main ... tpose

Author SHA1 Message Date
Louka
b73e147d17 Merge branch 'main' into tpose 2023-01-26 20:43:24 -05:00
Louka
4dae31a138 math wip 2023-01-26 20:42:55 -05:00
Louka
32d0674aad add tpose and ipose toggle 2023-01-23 21:33:01 -05:00
28 changed files with 234 additions and 101 deletions

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = skawting coww
settings-general-fk_settings-arm_fk = awm fk
settings-general-fk_settings-arm_fk-description = chawnge teh way teh awms awe twacked.
settings-general-fk_settings-arm_fk-force_arms = fowce awms fwom hmd
settings-general-fk_settings-arm_fk-i_pose = uwse i powse insted of t powse
settings-general-fk_settings-skeleton_settings = skeweton sewttings
settings-general-fk_settings-skeleton_settings-description = toggwe skeweton sewttings on owow off. is wowcommended to weawve these on~
settings-general-fk_settings-skeleton_settings-extended_spine = ewtended spine

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = Skating corre
settings-general-fk_settings-arm_fk = Arm tracking
settings-general-fk_settings-arm_fk-description = Change the way the arms are tracked.
settings-general-fk_settings-arm_fk-force_arms = Force arms from HMD
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = Skeleton settings
settings-general-fk_settings-skeleton_settings-description = Toggle skeleton settings on or off. It is recommended to leave these on.
settings-general-fk_settings-skeleton_settings-extended_spine = Extended spine

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = Agresividad d
settings-general-fk_settings-arm_fk = Trackeo de brazos
settings-general-fk_settings-arm_fk-description = Cambia cómo el movimiento de los brazos es detectado.
settings-general-fk_settings-arm_fk-force_arms = Forzar brazos desde el HMD
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = Ajustes de esqueleto
settings-general-fk_settings-skeleton_settings-description = Habilita o deshabilita los ajustes de esqueleto. Es recomendado dejar estos ajustes habilitados.
settings-general-fk_settings-skeleton_settings-extended_spine = Extención de columna

View File

@@ -256,6 +256,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = Libisemise ko
settings-general-fk_settings-arm_fk = Käe jälgimine
settings-general-fk_settings-arm_fk-description = Muuda viisi kuidas käsi jälgitakse.
settings-general-fk_settings-arm_fk-force_arms = Sunni käed HMD-st
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = Skeletti seaded
settings-general-fk_settings-skeleton_settings-description = Lülita skeletti seaded sisse või välja. Soovitatud on see sisse jätta.
settings-general-fk_settings-skeleton_settings-extended_spine = Selgroo laiendamine

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = Force de la c
settings-general-fk_settings-arm_fk = Capture des bras
settings-general-fk_settings-arm_fk-description = Changez la façon dont les bras sont captés.
settings-general-fk_settings-arm_fk-force_arms = Forcer les bras en provenance du casque VR
settings-general-fk_settings-arm_fk-i_pose = Utiliser la i-pose au lieu de la t-pose
settings-general-fk_settings-skeleton_settings = Paramètres du squelette
settings-general-fk_settings-skeleton_settings-description = Activez ou désactivez des paramètres avancés de capture.
settings-general-fk_settings-skeleton_settings-extended_spine = Colone vertébrale avancée

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = Forza fattore
settings-general-fk_settings-arm_fk = FK Braccia
settings-general-fk_settings-arm_fk-description = Cambia la modalità di tracciamento delle braccia.
settings-general-fk_settings-arm_fk-force_arms = Forza il calcolo della posizione delle braccia a utilizzare il HMD
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = Impostazioni scheletro
settings-general-fk_settings-skeleton_settings-description = Abilita o disabilita le impostazioni dello scheletro. É raccomandato lasciare queste impostazioni attive.
settings-general-fk_settings-skeleton_settings-extended_spine = Estensione colonna vertebrale

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = スケーテ
settings-general-fk_settings-arm_fk = アームトラッキング
settings-general-fk_settings-arm_fk-description = 腕の追従方法を変更する。
settings-general-fk_settings-arm_fk-force_arms = Force arms from HMD
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = スケルトン設定
settings-general-fk_settings-skeleton_settings-description = スケルトン設定のオン/オフを切り替えます。これらはオンのままにしておくことをお勧めします。
settings-general-fk_settings-skeleton_settings-extended_spine = Extended spine

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = 스케이팅
settings-general-fk_settings-arm_fk = 팔 운동학
settings-general-fk_settings-arm_fk-description = 팔이 추적되는 방식을 변경할 수 있어요.
settings-general-fk_settings-arm_fk-force_arms = 팔을 HMD에서만 받아오기
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = 골격 설정
settings-general-fk_settings-skeleton_settings-description = 골격 설정을 설정하거나 해제해요. 이것들은 켜두는 게 좋아요.
settings-general-fk_settings-skeleton_settings-extended_spine = 척추 확장

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = Skating-corre
settings-general-fk_settings-arm_fk = Arm tracking
settings-general-fk_settings-arm_fk-description = Verander de manier waarop de armen worden getrackt.
settings-general-fk_settings-arm_fk-force_arms = Dwing armen vanuit HMD
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = Skeleton instellingen
settings-general-fk_settings-skeleton_settings-description = Schakel skeleton instellingen in of uit. Het is aanbevolen om deze aan te laten.
settings-general-fk_settings-skeleton_settings-extended_spine = Uitgebreide rug

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = Skating corre
settings-general-fk_settings-arm_fk = Arm tracking
settings-general-fk_settings-arm_fk-description = Change the way the arms are tracked.
settings-general-fk_settings-arm_fk-force_arms = Force arms from HMD
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = Skeleton settings
settings-general-fk_settings-skeleton_settings-description = Toggle skeleton settings on or off. It is recommended to leave these on.
settings-general-fk_settings-skeleton_settings-extended_spine = Extended spine

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = Força da cor
settings-general-fk_settings-arm_fk = Opções do Braço
settings-general-fk_settings-arm_fk-description = Muda o jeito que os braços são rastreados.
settings-general-fk_settings-arm_fk-force_arms = Forçar braços do HMD
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = Opções do esqueleto
settings-general-fk_settings-skeleton_settings-description = Ligar ou desligar opções do esqueleto. É recomendado deixar eles ligados.
settings-general-fk_settings-skeleton_settings-extended_spine = Estender coluna

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = Mức độ s
settings-general-fk_settings-arm_fk = Track cánh tay
settings-general-fk_settings-arm_fk-description = Thay đổi cách cánh tay được track
settings-general-fk_settings-arm_fk-force_arms = Lấy dữ liệu cánh tay từ kính
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = Cài đặt khung cơ thể
settings-general-fk_settings-skeleton_settings-description = Bật hoặc tắt các cài đặt về khung cơ thể. Các lựa chọn này nên được giữ bật
settings-general-fk_settings-skeleton_settings-extended_spine = Xương sống kéo dài

View File

@@ -275,6 +275,7 @@ settings-general-fk_settings-leg_tweak-skating_correction-amount = 脚滑矫正
settings-general-fk_settings-arm_fk = 手臂 FK
settings-general-fk_settings-arm_fk-description = 更改手臂的追踪方式。
settings-general-fk_settings-arm_fk-force_arms = 强制从头显获得数据
settings-general-fk_settings-arm_fk-i_pose = Use i-pose instead of t-pose
settings-general-fk_settings-skeleton_settings = 骨架设置
settings-general-fk_settings-skeleton_settings-description = 打开或关闭骨架设置。建议保持这些设置不变。
settings-general-fk_settings-skeleton_settings-extended_spine = 脊柱延伸

View File

@@ -54,6 +54,7 @@ interface SettingsForm {
floorClip: boolean;
skatingCorrection: boolean;
viveEmulation: boolean;
iPose: boolean;
};
tapDetection: {
tapMountingResetEnabled: boolean;
@@ -92,6 +93,7 @@ const defaultValues = {
floorClip: false,
skatingCorrection: false,
viveEmulation: false,
iPose: false,
},
filtering: { amount: 0.1, type: FilteringType.NONE },
driftCompensation: {
@@ -149,6 +151,7 @@ export function GeneralSettings() {
toggles.extendedSpine = values.toggles.extendedSpine;
toggles.forceArmsFromHmd = values.toggles.forceArmsFromHmd;
toggles.viveEmulation = values.toggles.viveEmulation;
toggles.iPose = values.toggles.iPose;
legTweaks.correctionStrength = values.legTweaks.correctionStrength;
modelSettings.toggles = toggles;
@@ -553,6 +556,17 @@ export function GeneralSettings() {
)}
/>
</div>
<div className="grid sm:grid-cols-2 pb-5">
<CheckBox
variant="toggle"
outlined
control={control}
name="toggles.iPose"
label={l10n.getString(
'settings-general-fk_settings-arm_fk-i_pose'
)}
/>
</div>
{config?.debug && (
<>
<Typography bold>

View File

@@ -45,9 +45,9 @@ import java.util.logging.Logger;
* hypercomplex numbers. Quaternions extends a rotation in three dimensions to a
* rotation in four dimensions. This avoids "gimbal lock" and allows for smooth
* continuous rotation.
*
*
* <code>Quaternion</code> is defined by four floating point numbers: {x y z w}.
*
*
* @author Mark Powell
* @author Joshua Slack
*/
@@ -239,10 +239,10 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
* angles (x,y,z) aka (pitch, yaw, rall)). Note that we are applying in
* order: (y, z, x) aka (yaw, roll, pitch) but we've ordered them in x, y,
* and z for convenience.
*
*
* @see <a href=
* "http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm">http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm</a>
*
*
* @param xAngle the Euler pitch of rotation (in radians). (aka Attitude,
* often rot around x)
* @param yAngle the Euler yaw of rotation (in radians). (aka Heading, often
@@ -283,10 +283,10 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
* angles (pitch, yaw, roll).<br/>
* Note that the result is not always 100% accurate due to the implications
* of euler angles.
*
*
* @see <a href=
* "http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm">http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm</a>
*
*
* @param angles the float[] in which the angles should be stored, or null
* if you want a new float[] to be created
* @return the float[] in which the angles are stored (pitch, yaw, roll).
@@ -327,7 +327,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
/**
* Returns Euler rotation angle around x axis (pitch).
*
*
* @return
* @see #toAngles(float[])
*/
@@ -377,7 +377,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
/**
* Returns Euler rotation angle around z axis (roll).
*
*
* @return
* @see #toAngles(float[])
*/
@@ -399,10 +399,10 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
}
/**
*
*
* <code>fromRotationMatrix</code> generates a quaternion from a supplied
* matrix. This matrix is assumed to be a rotational matrix.
*
*
* @param matrix the matrix that defines the rotation.
*/
public Quaternion fromRotationMatrix(Matrix3f matrix) {
@@ -501,7 +501,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
* <code>toRotationMatrix</code> converts this quaternion to a rotational
* matrix. Note: the result is created from a normalized version of this
* quat.
*
*
* @return the rotation matrix representation of this quaternion.
*/
public Matrix3f toRotationMatrix() {
@@ -512,7 +512,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
/**
* <code>toRotationMatrix</code> converts this quaternion to a rotational
* matrix. The result is stored in result.
*
*
* @param result The Matrix3f to store the result in.
* @return the rotation matrix representation of this quaternion.
*/
@@ -557,7 +557,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
* matrix. The result is stored in result. 4th row and 4th column values are
* untouched. Note: the result is created from a normalized version of this
* quat.
*
*
* @param result The Matrix4f to store the result in.
* @return the rotation matrix representation of this quaternion.
*/
@@ -802,6 +802,38 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
return angle;
}
public Quaternion align(Vector3f v1, Vector3f v2) {
float aLenSq = v1.x * v1.x + v1.y * v1.y + v2.z * v2.z;
float bLenSq = v2.x * v2.x + v2.y * v2.y + v2.z * v2.z;
float aLenSqInv = 1f / aLenSq;
float Rw = aLenSqInv * (x * v1.x + y * v1.y + z * v2.z);
float Rx = aLenSqInv * (z * v1.y - w * v1.x - y * v2.z);
float Ry = aLenSqInv * (x * v2.z - w * v1.y - z * v1.x);
float Rz = aLenSqInv * (y * v1.x - w * v2.z - x * v1.y);
float Sw = -v2.x * Rx - v2.y * Ry - v2.z * Rz;
float Sx = v2.x * Rw - v2.z * Ry + v2.y * Rz;
float Sy = v2.y * Rw + v2.z * Rx - v2.x * Rz;
float Sz = v2.z * Rw - v2.y * Rx + v2.x * Ry;
float mul = (float) Math.sqrt(aLenSqInv * bLenSq);
// (b*Q*a^-1 + len(b*a^-1)*Q)/2,
// a and b are treated as pure imaginary Quaternions
w = 0.5f * (Sw + mul * w);
x = 0.5f * (Sx + mul * x);
y = 0.5f * (Sy + mul * y);
z = 0.5f * (Sz + mul * z);
return this;
}
public Vector3f toAxis() {
return new Vector3f(x, y, z);
}
public float angleBetween(Quaternion q2) {
float w = this.w * q2.w + this.x * q2.x + this.y * q2.y + this.z * q2.z;
float x = this.w * q2.x - this.x * q2.w - this.y * q2.z + this.z * q2.y;
@@ -903,7 +935,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
/**
* Sets the values of this quaternion to the nlerp from itself to q2 by
* blend.
*
*
* @param q2
* @param blend
*/
@@ -1251,7 +1283,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
/**
* <code>mult</code> multiplies this quaternion by a parameter vector. The
* result is returned as a new vector.
*
*
* @param v the vector to multiply this quaternion by.
* @param store the vector to store the result in. It IS safe for v and
* store to be the same object.
@@ -1374,7 +1406,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
/**
* <code>mult</code> multiplies this quaternion by a parameter vector. The
* result is returned as a new vector.
*
*
* @param vx
* @param vy
* @param vz the vector to multiply this quaternion by.
@@ -1614,11 +1646,11 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
}
/**
*
*
* <code>hashCode</code> returns the hash code value as an integer and is
* supported for the benefit of hashing based collection classes such as
* Hashtable, HashMap, HashSet etc.
*
*
* @return the hashcode for this instance of Quaternion.
* @see java.lang.Object#hashCode()
*/
@@ -1637,7 +1669,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
* <code>readExternal</code> builds a quaternion from an
* <code>ObjectInput</code> object. <br>
* NOTE: Used with serialization. Not to be called manually.
*
*
* @param in the ObjectInput value to read from.
* @throws IOException if the ObjectInput value has problems reading a
* float.
@@ -1654,7 +1686,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
* <code>writeExternal</code> writes this quaternion out to a
* <code>ObjectOutput</code> object. NOTE: Used with serialization. Not to
* be called manually.
*
*
* @param out the object to write to.
* @throws IOException if writing to the ObjectOutput fails.
* @see java.io.Externalizable
@@ -1696,7 +1728,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
/**
* FIXME: This seems to have singularity type issues with angle == 0,
* possibly others such as PI.
*
*
* @param store A Quaternion to store our result in. If null, a new one is
* created.
* @return The store quaternion (or a new Quaterion, if store is null) that
@@ -1737,7 +1769,7 @@ public final class Quaternion implements Cloneable, java.io.Serializable {
* <p>
* Based on implementation from here:
* https://github.com/toji/gl-matrix/blob/f0583ef53e94bc7e78b78c8a24f09ed5e2f7a20c/src/gl-matrix/quat.js#L54
*
*
* @param vec1
* @param vec2
* @return this quaternion

View File

@@ -210,7 +210,7 @@ public class PoseFrameTracker implements Tracker, Iterable<TrackerFrame> {
}
@Override
public void resetFull(Quaternion reference) {
public void resetFull(Quaternion reference, boolean tPose) {
throw new UnsupportedOperationException("PoseFrameTracker does not implement calibration");
}
@@ -220,7 +220,7 @@ public class PoseFrameTracker implements Tracker, Iterable<TrackerFrame> {
}
@Override
public void resetMounting(boolean reverseYaw) {
public void resetMounting(boolean reverseYaw, boolean tPose) {
throw new UnsupportedOperationException("PoseFrameTracker does not implement calibration");
}

View File

@@ -148,7 +148,7 @@ public final class TrackerFrame implements Tracker {
}
@Override
public void resetFull(Quaternion reference) {
public void resetFull(Quaternion reference, boolean tPose) {
throw new UnsupportedOperationException("TrackerFrame does not implement calibration");
}
@@ -158,7 +158,7 @@ public final class TrackerFrame implements Tracker {
}
@Override
public void resetMounting(boolean reverseYaw) {
public void resetMounting(boolean reverseYaw, boolean tPose) {
throw new UnsupportedOperationException("TrackerFrame does not implement calibration");
}

View File

@@ -153,7 +153,8 @@ public class RPCSettingsBuilder {
config.getToggle(SkeletonConfigToggles.FORCE_ARMS_FROM_HMD),
config.getToggle(SkeletonConfigToggles.FLOOR_CLIP),
config.getToggle(SkeletonConfigToggles.SKATING_CORRECTION),
config.getToggle(SkeletonConfigToggles.VIVE_EMULATION)
config.getToggle(SkeletonConfigToggles.VIVE_EMULATION),
config.getToggle(SkeletonConfigToggles.I_POSE)
);
int ratiosOffset = ModelRatios
.createModelRatios(

View File

@@ -273,6 +273,7 @@ public record RPCSettingsHandler(RPCHandler rpcHandler, ProtocolAPI api) {
toggles.skatingCorrection()
);
cfg.setToggle(SkeletonConfigToggles.VIVE_EMULATION, toggles.viveEmulation());
cfg.setToggle(SkeletonConfigToggles.I_POSE, toggles.iPose());
}
if (ratios != null) {

View File

@@ -123,6 +123,7 @@ public class HumanSkeleton extends Skeleton implements SkeletonConfigCallback {
protected boolean extendedPelvisModel;
protected boolean extendedKneeModel;
protected boolean forceArmsFromHMD;
protected boolean iPose;
// Values
protected float waistFromChestHipAveraging;
protected float waistFromChestLegsAveraging;
@@ -1370,6 +1371,7 @@ public class HumanSkeleton extends Skeleton implements SkeletonConfigCallback {
case SKATING_CORRECTION -> legTweaks.setSkatingReductionEnabled(newValue);
case FLOOR_CLIP -> legTweaks.setFloorclipEnabled(newValue);
case VIVE_EMULATION -> viveEmulation.setEnabled(newValue);
case I_POSE -> iPose = newValue;
}
}
@@ -1742,7 +1744,7 @@ public class HumanSkeleton extends Skeleton implements SkeletonConfigCallback {
for (Tracker tracker : trackersToReset) {
if (tracker != null) {
tracker.resetFull(referenceRotation);
tracker.resetFull(referenceRotation, !iPose);
}
}
@@ -1764,6 +1766,8 @@ public class HumanSkeleton extends Skeleton implements SkeletonConfigCallback {
return position != null
&& (position == TrackerPosition.LEFT_UPPER_LEG
|| position == TrackerPosition.RIGHT_UPPER_LEG
|| position == TrackerPosition.LEFT_UPPER_ARM
|| position == TrackerPosition.RIGHT_UPPER_ARM
|| position == TrackerPosition.LEFT_LOWER_ARM
|| position == TrackerPosition.RIGHT_LOWER_ARM
|| position == TrackerPosition.LEFT_HAND
@@ -1778,7 +1782,7 @@ public class HumanSkeleton extends Skeleton implements SkeletonConfigCallback {
for (Tracker tracker : trackersToReset) {
if (tracker != null && shouldResetMounting(tracker.getBodyPosition())) {
tracker.resetMounting(shouldReverseYaw(tracker.getBodyPosition()));
tracker.resetMounting(shouldReverseYaw(tracker.getBodyPosition()), !iPose);
}
}
this.legTweaks.resetBuffer();

View File

@@ -305,18 +305,22 @@ public class SkeletonConfig {
-getOffset(SkeletonConfigOffsets.SHOULDERS_DISTANCE),
0
);
case LEFT_UPPER_ARM, RIGHT_UPPER_ARM -> setNodeOffset(
nodeOffset,
0,
-getOffset(SkeletonConfigOffsets.UPPER_ARM),
0
);
case LEFT_LOWER_ARM, RIGHT_LOWER_ARM -> setNodeOffset(
nodeOffset,
0,
getOffset(SkeletonConfigOffsets.LOWER_ARM),
0
);
case LEFT_UPPER_ARM, RIGHT_UPPER_ARM -> {
setNodeOffset(
nodeOffset,
0,
-getOffset(SkeletonConfigOffsets.UPPER_ARM),
0
);
}
case LEFT_LOWER_ARM, RIGHT_LOWER_ARM -> {
setNodeOffset(
nodeOffset,
0,
-getOffset(SkeletonConfigOffsets.LOWER_ARM),
0
);
}
case LEFT_HAND, RIGHT_HAND -> setNodeOffset(
nodeOffset,
0,
@@ -329,12 +333,14 @@ public class SkeletonConfig {
getOffset(SkeletonConfigOffsets.CONTROLLER_Y),
getOffset(SkeletonConfigOffsets.CONTROLLER_Z)
);
case LEFT_ELBOW_TRACKER, RIGHT_ELBOW_TRACKER -> setNodeOffset(
nodeOffset,
0,
getOffset(SkeletonConfigOffsets.ELBOW_OFFSET),
0
);
case LEFT_ELBOW_TRACKER, RIGHT_ELBOW_TRACKER -> {
setNodeOffset(
nodeOffset,
0,
-getOffset(SkeletonConfigOffsets.ELBOW_OFFSET),
0
);
}
}
}

View File

@@ -6,43 +6,36 @@ import java.util.Map;
public enum SkeletonConfigToggles {
EXTENDED_SPINE_MODEL(1, "Extended spine model", "extendedSpine", true),
EXTENDED_PELVIS_MODEL(2, "Extended pelvis model", "extendedPelvis", true),
EXTENDED_KNEE_MODEL(3, "Extended knee model", "extendedKnee", true),
FORCE_ARMS_FROM_HMD(4, "Force arms from HMD", "forceArmsFromHMD", true),
FLOOR_CLIP(5, "Floor clip", "floorClip", true),
SKATING_CORRECTION(6, "Skating correction", "skatingCorrection", true),
VIVE_EMULATION(7, "Vive emulation", "viveEmulation", false),;
EXTENDED_SPINE_MODEL(1, "extendedSpine", true),
EXTENDED_PELVIS_MODEL(2, "extendedPelvis", true),
EXTENDED_KNEE_MODEL(3, "extendedKnee", true),
FORCE_ARMS_FROM_HMD(4, "forceArmsFromHMD", true),
FLOOR_CLIP(5, "floorClip", true),
SKATING_CORRECTION(6, "skatingCorrection", true),
VIVE_EMULATION(7, "viveEmulation", false),
I_POSE(8, "iPose", false),;
public static final SkeletonConfigToggles[] values = values();
private static final Map<String, SkeletonConfigToggles> byStringVal = new HashMap<>();
private static final Map<Number, SkeletonConfigToggles> byIdVal = new HashMap<>();
static {
for (SkeletonConfigToggles configVal : values()) {
byIdVal.put(configVal.id, configVal);
byStringVal.put(configVal.stringVal.toLowerCase(), configVal);
}
}
public final int id;
public final String stringVal;
public final String configKey;
public final boolean defaultValue;
SkeletonConfigToggles(int id, String stringVal, String configKey, boolean defaultValue) {
SkeletonConfigToggles(int id, String configKey, boolean defaultValue) {
this.id = id;
this.stringVal = stringVal;
this.configKey = configKey;
this.defaultValue = defaultValue;
}
public static SkeletonConfigToggles getByStringValue(String stringVal) {
return stringVal == null ? null : byStringVal.get(stringVal.toLowerCase());
}
public static SkeletonConfigToggles getById(int id) {
return byIdVal.get(id);
}

View File

@@ -107,7 +107,7 @@ public class ComputedTracker implements Tracker, TrackerWithTPS {
}
@Override
public void resetFull(Quaternion reference) {
public void resetFull(Quaternion reference, boolean tPose) {
}
@Override
@@ -115,7 +115,7 @@ public class ComputedTracker implements Tracker, TrackerWithTPS {
}
@Override
public void resetMounting(boolean reverseYaw) {
public void resetMounting(boolean reverseYaw, boolean tPose) {
}
@Override

View File

@@ -22,6 +22,10 @@ public class IMUTracker
TrackerWithFiltering {
public static final float MAX_MAG_CORRECTION_ACCURACY = 5 * FastMath.RAD_TO_DEG;
private static final Quaternion LEFT_TPOSE_OFFSET = new Quaternion()
.fromAngles(0, 0, FastMath.HALF_PI);
private static final Quaternion RIGHT_TPOSE_OFFSET = new Quaternion()
.fromAngles(0, 0, -FastMath.HALF_PI);
// public final Vector3f gyroVector = new Vector3f();
public final Vector3f accelVector = new Vector3f();
@@ -36,7 +40,7 @@ public class IMUTracker
// Reference adjustment quats
private final Quaternion gyroFix = new Quaternion();
private final Quaternion attachmentFix = new Quaternion();
private final Quaternion mountRotFix = new Quaternion();
private final Quaternion yawMountRotFix = new Quaternion();
private final Quaternion yawFix = new Quaternion();
// Zero-reference adjustment quats for IMU debugging
@@ -258,7 +262,7 @@ public class IMUTracker
*/
@Override
public boolean getRotation(Quaternion store) {
this.getFilteredRotation(store);
getFilteredRotation(store);
// correction.mult(store, store); // Correction is not used now to
// prevent accidental errors while debugging other things
store.multLocal(mountAdjust);
@@ -287,7 +291,7 @@ public class IMUTracker
* @param store Where to store the calculation result.
*/
public boolean getIdentityAdjustedRotation(Quaternion store) {
this.getFilteredRotation(store);
getFilteredRotation(store);
adjustToIdentity(store);
return true;
}
@@ -401,12 +405,13 @@ public class IMUTracker
* 0). This allows the tracker to be strapped to body at any pitch and roll.
*/
@Override
public void resetFull(Quaternion reference) {
public void resetFull(Quaternion reference, boolean tPose) {
Quaternion rot = getAdjustedRawRotation();
fixGyroscope(getMountedAdjustedRotation());
fixAttachment(getMountedAdjustedRotation());
fixGyroscope(getMountedAdjustedRotation(), tPose);
fixAttachment(getMountedAdjustedRotation(), tPose);
makeIdentityAdjustmentQuatsFull();
fixYaw(getMountedAdjustedRotation(), reference);
makeIdentityAdjustmentQuatsYaw();
calibrateMag();
calculateDrift(rot);
}
@@ -430,22 +435,22 @@ public class IMUTracker
/**
* Converts raw or filtered rotation into reference- and
* mounting-reset-adjusted by applying quaternions produced after
* {@link #resetFull(Quaternion)}, {@link #resetYaw(Quaternion)} and
* {@link #resetMounting(boolean)}.
* {@link #resetFull(Quaternion, boolean)}, {@link #resetYaw(Quaternion)}
* and {@link #resetMounting(boolean, boolean)}.
*
* @param store Raw or filtered rotation to mutate.
*/
protected void adjustToReference(Quaternion store) {
gyroFix.mult(store, store);
store.multLocal(attachmentFix);
store.multLocal(mountRotFix);
store.multLocal(yawMountRotFix);
yawFix.mult(store, store);
}
/**
* Converts raw or filtered rotation into zero-reference-adjusted by
* applying quaternions produced after {@link #resetFull(Quaternion)},
* {@link #resetYaw(Quaternion)}.
* applying quaternions produced after
* {@link #resetFull(Quaternion, boolean)}, {@link #resetYaw(Quaternion)}.
*
* @param store Raw or filtered rotation to mutate.
*/
@@ -455,41 +460,59 @@ public class IMUTracker
yawFixZeroReference.mult(store, store);
}
private void fixGyroscope(Quaternion sensorRotation) {
private void fixGyroscope(Quaternion sensorRotation, boolean tPose) {
sensorRotation = sensorRotation.clone();
if (tPose)
fixForTPose(sensorRotation);
sensorRotation.fromAngles(0, sensorRotation.getYaw(), 0);
gyroFix.set(sensorRotation.inverseLocal());
}
private void fixAttachment(Quaternion sensorRotation) {
private void fixAttachment(Quaternion sensorRotation, boolean tPose) {
sensorRotation = sensorRotation.clone();
gyroFix.mult(sensorRotation, sensorRotation);
if (tPose)
fixForTPose(sensorRotation);
attachmentFix.set(sensorRotation.inverseLocal());
}
@Override
public void resetMounting(boolean reverseYaw) {
public void resetMounting(boolean reverseYaw, boolean tPose) {
// Get the current calibrated rotation
Quaternion buffer = getMountedAdjustedDriftRotation();
gyroFix.mult(buffer, buffer);
buffer.multLocal(attachmentFix);
float yawAngle;
// Reset the vector for the rotation to point straight up
rotVector.set(0f, 1f, 0f);
// Rotate the vector by the quat, then flatten and normalize the vector
buffer.multLocal(rotVector).setY(0f).normalizeLocal();
// Calculate the yaw angle using tan
// Just use an angle offset of zero for unsolvable circumstances
float yawAngle = FastMath.isApproxZero(rotVector.x) && FastMath.isApproxZero(rotVector.z)
? 0f
: FastMath.atan2(rotVector.x, rotVector.z);
if (tPose && (isOnLeftArm() || isOnRightArm())) {
// Find the global axis the tracker thinks it rotated about (should
// be z), then projected on to the xz plane
rotVector
.set(
((isOnLeftArm() ? LEFT_TPOSE_OFFSET : RIGHT_TPOSE_OFFSET)
.mult(buffer)).toAxis()
);
yawAngle = FastMath
.atan2(
rotVector.cross(Vector3f.NEGATIVE_UNIT_Z).dot(Vector3f.UNIT_Y),
rotVector.dot(Vector3f.NEGATIVE_UNIT_Z)
);
// TODO find out what what is causing arms to not work (yawFix?)
} else {
// Find the global axis the tracker thinks it rotated about (should
// be z), then projected on to the xz plane
rotVector.set(buffer.inverseLocal().toAxis());
yawAngle = new Quaternion(0f, 0f, 0f, 1f)
.align(rotVector, Vector3f.UNIT_X)
.normalizeLocal()
.getYaw();
}
// Make an adjustment quaternion from the angle
buffer.fromAngles(0f, reverseYaw ? yawAngle : yawAngle - FastMath.PI, 0f);
Quaternion lastRotAdjust = mountRotFix.clone();
mountRotFix.set(buffer);
Quaternion lastRotAdjust = yawMountRotFix.clone();
yawMountRotFix.set(buffer);
// Get the difference from the last adjustment
buffer.multLocal(lastRotAdjust.inverseLocal());
@@ -505,7 +528,7 @@ public class IMUTracker
sensorRotation = sensorRotation.clone();
gyroFix.mult(sensorRotation, sensorRotation);
sensorRotation.multLocal(attachmentFix);
sensorRotation.multLocal(mountRotFix);
sensorRotation.multLocal(yawMountRotFix);
sensorRotation.fromAngles(0, sensorRotation.getYaw(), 0);
@@ -673,6 +696,26 @@ public class IMUTracker
// TODO Print "jump" length when correcting if it's more than 1 degree
}
private void fixForTPose(Quaternion store) {
if (isOnLeftArm()) {
store.set(LEFT_TPOSE_OFFSET.mult(store));
} else if (isOnRightArm()) {
store.set(RIGHT_TPOSE_OFFSET.mult(store));
}
}
private boolean isOnLeftArm() {
return bodyPosition == TrackerPosition.LEFT_UPPER_ARM
|| bodyPosition == TrackerPosition.LEFT_LOWER_ARM
|| bodyPosition == TrackerPosition.LEFT_HAND;
}
private boolean isOnRightArm() {
return bodyPosition == TrackerPosition.RIGHT_UPPER_ARM
|| bodyPosition == TrackerPosition.RIGHT_LOWER_ARM
|| bodyPosition == TrackerPosition.RIGHT_HAND;
}
@Override
public TrackerPosition getBodyPosition() {
return bodyPosition;

View File

@@ -34,11 +34,11 @@ public interface Tracker {
float getConfidenceLevel();
void resetFull(Quaternion reference);
void resetFull(Quaternion reference, boolean tPose);
void resetYaw(Quaternion reference);
void resetMounting(boolean reverseYaw);
void resetMounting(boolean reverseYaw, boolean tPose);
void tick();

View File

@@ -1,5 +1,6 @@
package dev.slimevr.vr.trackers;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import dev.slimevr.vr.Device;
import io.eiren.util.BufferedTimer;
@@ -7,6 +8,10 @@ import io.eiren.util.BufferedTimer;
public class VRTracker extends ComputedTracker {
private static final Quaternion LEFT_TPOSE_OFFSET = new Quaternion()
.fromAngles(0, 0, FastMath.HALF_PI);
private static final Quaternion RIGHT_TPOSE_OFFSET = new Quaternion()
.fromAngles(0, 0, -FastMath.HALF_PI);
protected BufferedTimer timer = new BufferedTimer(1f);
public final Quaternion mountFix = new Quaternion();
public final Quaternion attachmentFix = new Quaternion();
@@ -45,8 +50,8 @@ public class VRTracker extends ComputedTracker {
}
@Override
public void resetFull(Quaternion reference) {
fixAttachment(rotation, reference);
public void resetFull(Quaternion reference, boolean tPose) {
fixAttachment(rotation, reference, tPose);
fixYaw(rotation, reference);
}
@@ -55,9 +60,10 @@ public class VRTracker extends ComputedTracker {
fixYaw(rotation, reference);
}
private void fixAttachment(Quaternion sensorRotation, Quaternion reference) {
private void fixAttachment(Quaternion sensorRotation, Quaternion reference, boolean tPose) {
mountFix.fromAngles(0, reference.getYaw(), 0);
if (tPose)
fixForTPose(sensorRotation);
attachmentFix.set(sensorRotation.inverse());
}
@@ -75,6 +81,26 @@ public class VRTracker extends ComputedTracker {
yawFix.set(sensorRotation).inverseLocal().multLocal(reference);
}
private void fixForTPose(Quaternion store) {
if (isOnLeftArm()) {
store.set(LEFT_TPOSE_OFFSET.mult(store));
} else if (isOnRightArm()) {
store.set(RIGHT_TPOSE_OFFSET.mult(store));
}
}
private boolean isOnLeftArm() {
return bodyPosition == TrackerPosition.LEFT_UPPER_ARM
|| bodyPosition == TrackerPosition.LEFT_LOWER_ARM
|| bodyPosition == TrackerPosition.LEFT_HAND;
}
private boolean isOnRightArm() {
return bodyPosition == TrackerPosition.RIGHT_UPPER_ARM
|| bodyPosition == TrackerPosition.RIGHT_LOWER_ARM
|| bodyPosition == TrackerPosition.RIGHT_HAND;
}
@Override
public float getTPS() {
return timer.getAverageFPS();

View File

@@ -186,7 +186,7 @@ public class ReferenceAdjustmentsTests {
null
);
tracker.rotQuaternion.set(trackerQuat);
tracker.resetFull(referenceQuat);
tracker.resetFull(referenceQuat, false);
Quaternion read = new Quaternion();
assertTrue(tracker.getRotation(read), "Adjusted tracker didn't return rotation");
@@ -257,7 +257,7 @@ public class ReferenceAdjustmentsTests {
null
);
tracker.rotQuaternion.set(trackerQuat);
tracker.resetFull(referenceQuat);
tracker.resetFull(referenceQuat, false);
// Use only yaw HMD rotation
Quaternion targetTrackerRotation = new Quaternion(referenceQuat);