1 using System.Collections;
2 using System.Collections.Generic;
11 namespace AVR.Avatar {
21 public Vector3 lookAtPos =>
23 !IsOwner ? m_ReplicatedState.Value.
lookAtPos :
25 eyeTransform.localPosition + transform.InverseTransformDirection(eyeTransform.forward);
30 public Quaternion leftHandRot =>
32 !IsOwner ? m_ReplicatedState.Value.leftHandRot :
34 leftHandTarget.rotation;
39 public Quaternion rightHandRot =>
41 !IsOwner ? m_ReplicatedState.Value.rightHandRot :
43 rightHandTarget.rotation;
48 public Vector3 leftFootPos =>
50 !IsOwner ? m_ReplicatedState.Value.leftFootPos :
52 leftFootTarget.localPosition;
57 public Quaternion leftFootRot =>
59 !IsOwner ? m_ReplicatedState.Value.leftFootRot :
61 leftFootTarget.rotation;
66 public Vector3 rightFootPos =>
68 !IsOwner ? m_ReplicatedState.Value.rightFootPos :
70 rightFootTarget.localPosition;
75 public Quaternion rightFootRot =>
77 !IsOwner ? m_ReplicatedState.Value.rightFootRot :
79 rightFootTarget.rotation;
84 public Vector3 pivotPos =>
86 !IsOwner ? m_ReplicatedState.Value.pivotPos :
88 pivotTransform.localPosition;
93 public Quaternion pivotRot =>
95 !IsOwner ? m_ReplicatedState.Value.pivotRot :
97 pivotTransform.rotation;
102 public Vector3 bodyPos =>
104 !IsOwner ? m_ReplicatedState.Value.bodyPos :
106 bodyTransform.localPosition;
111 public Quaternion bodyRot =>
113 !IsOwner ? m_ReplicatedState.Value.bodyRot :
115 bodyTransform.rotation;
120 public Vector3 eyePos =>
122 !IsOwner ? m_ReplicatedState.Value.eyePos :
124 eyeTransform.localPosition;
129 public Quaternion eyeRot =>
131 !IsOwner ? m_ReplicatedState.Value.eyeRot :
133 eyeTransform.rotation;
138 public Vector3 leftHandPos {
144 return m_ReplicatedState.Value.leftHandPos;
148 if (leftHandFilter)
return transform.InverseTransformPoint(leftHandFilter.naturalize_point(leftHandTarget.position));
149 return transform.InverseTransformPoint(leftHandTarget.position);
156 public Vector3 rightHandPos {
162 return m_ReplicatedState.Value.rightHandPos;
166 if (rightHandFilter)
return transform.InverseTransformPoint(rightHandFilter.naturalize_point(rightHandTarget.position));
167 return transform.InverseTransformPoint(rightHandTarget.position);
183 protected Transform leftHandTarget => playerRig.leftHandController ? playerRig.leftHandController.transform : pivotTransform;
184 protected Transform rightHandTarget => playerRig.rightHandController ? playerRig.rightHandController.transform : pivotTransform;
194 [Range(0.0001f, 1.0f)]
195 public float body_inertia = 0.3f;
201 public float lean_blend_speed = 3.5f;
207 public float max_head_yaw = 30f;
213 public float max_head_pitch = 30f;
219 public float max_head_roll = 30f;
225 public float default_body_height = 0.9f;
231 public float max_body_height = 1.0f;
237 public float min_body_height = 0.5f;
243 public Vector3 local_eye_to_neck_offset =
new Vector3(0.0f, -0.1f, -0.05f);
249 public float neck_body_distance = 0.4f;
255 public Vector3 foot_offset_from_pivot =
new Vector3(0.2f, 0.05f, 0.0f);
261 public float foot_follow_speed = 3.0f;
268 private float lean_factor = 0.0f;
269 private float lean_conf = 0.0f;
270 private float last_yaw = 0.0f;
275 leftFootTarget = AVR.Core.Utils.Misc.CreateEmptyGameObject(
"leftFootTarget", transform);
276 rightFootTarget = AVR.Core.Utils.Misc.CreateEmptyGameObject(
"rightFootTarget", transform);
277 pivotTransform = AVR.Core.Utils.Misc.CreateEmptyGameObject(
"pivotTarget", transform);
278 bodyTransform = AVR.Core.Utils.Misc.CreateEmptyGameObject(
"bodyTarget", transform);
279 eyeTransform = AVR.Core.Utils.Misc.CreateEmptyGameObject(
"eyeTransform", transform);
283 float dist = Vector3.Distance(current, target);
284 float move_mult = Mathf.SmoothStep(0f, 1f, dist / body_inertia);
285 return Vector3.MoveTowards(current, target, dist*move_mult);
292 if (playerRig.isLeaningForwardsConfidence() > 0.5f)
294 lean_factor = Mathf.Lerp(lean_factor, 1.0f, Time.deltaTime * lean_blend_speed);
298 lean_factor = Mathf.Lerp(lean_factor, 0.0f, Time.deltaTime * lean_blend_speed);
300 lean_conf = lean_factor * playerRig.isLeaningForwardsConfidence();
304 eyeTransform.position = ApplyInertia(eyeTransform.position, playerRig.MainCamera.transform.position);
308 Quaternion r = playerRig.MainCamera.transform.localRotation;
309 r = AVR.Core.Utils.Geom.ClampQuaternionRotation(r,
new Vector3(max_head_pitch, 360, max_head_roll));
310 eyeTransform.localRotation = r;
316 bodyTransform.up = Vector3.up;
319 GetStandingTransform(out Quaternion stout, out Vector3 stpos);
321 GetLeanTransform(out Quaternion bdout, out Vector3 bdpos);
324 Vector3 unsafe_pos = Vector3.Lerp(stpos, bdpos, lean_conf);
325 Quaternion unsafe_rot = Quaternion.Lerp(stout, bdout, lean_conf);
331 float sh = stpos.y - pivotTransform.position.y;
332 float uh = unsafe_pos.y - pivotTransform.position.y;
334 float lamb = Mathf.Clamp((default_body_height - sh) / (uh - sh), 0.0f, 1.0f);
336 unsafe_pos = Vector3.Lerp(stpos, unsafe_pos, lamb);
337 unsafe_rot = Quaternion.Lerp(stout, unsafe_rot, lamb);
341 bodyTransform.position = unsafe_pos;
342 bodyTransform.rotation = unsafe_rot;
348 bodyTransform.position =
new Vector3(
349 bodyTransform.position.x,
350 pivotTransform.position.y + Mathf.Clamp(bodyTransform.position.y - pivotTransform.position.y, min_body_height, max_body_height),
351 bodyTransform.position.z
358 if(synchronizePose) sync();
364 last_yaw = Mathf.MoveTowardsAngle(last_yaw, bodyTransform.rotation.eulerAngles.y, 9999.0f);
372 Vector3 NeckPos = eyeTransform.position + eyeTransform.TransformVector(local_eye_to_neck_offset);
374 pos = NeckPos + neck_body_distance * -Vector3.up;
376 rot = CorrectBodyYawAngle(Quaternion.LookRotation(bodyTransform.forward, Vector3.up));
381 Vector3 NeckPos = eyeTransform.position + eyeTransform.TransformVector(local_eye_to_neck_offset);
383 pos = NeckPos + neck_body_distance * -playerRig.MainCamera.transform.up;
385 rot = CorrectBodyYawAngle(Quaternion.LookRotation(eyeTransform.forward, NeckPos - pos));
389 if(Application.isPlaying) {
391 if (!IsOwner)
return;
394 Gizmos.color = Color.green;
395 Gizmos.DrawSphere(eyeTransform.position, 0.1f);
397 Gizmos.DrawRay(eyeTransform.position, eyeTransform.forward);
399 Gizmos.color = Color.white;
401 Vector3 local_eye_to_neck_offset =
new Vector3(0.0f, -0.1f, -0.1f);
402 Vector3 NeckPos = eyeTransform.position + eyeTransform.TransformVector(local_eye_to_neck_offset);
403 Gizmos.DrawLine(eyeTransform.position, NeckPos);
404 Gizmos.DrawCube(NeckPos,
new Vector3(0.05f, 0.05f, 0.05f));
406 Gizmos.DrawLine(NeckPos, bodyTransform.position);
407 Gizmos.DrawCube(bodyTransform.position,
new Vector3(0.05f, 0.05f, 0.05f));
409 Gizmos.DrawCube(bodyTransform.position,
new Vector3(0.2f, 0.2f, 0.2f));
410 Gizmos.DrawCube(pivotTransform.position,
new Vector3(0.05f, 0.05f, 0.05f));
411 Gizmos.DrawRay(pivotTransform.position, pivotTransform.forward);
413 Gizmos.color = Color.red;
414 Gizmos.DrawLine(bodyTransform.position, leftFootTarget.position);
415 Gizmos.DrawCube(leftFootTarget.position,
new Vector3(0.05f, 0.05f, 0.05f));
416 Gizmos.DrawLine(bodyTransform.position, rightFootTarget.position);
417 Gizmos.DrawCube(rightFootTarget.position,
new Vector3(0.05f, 0.05f, 0.05f));
419 Gizmos.color = Color.yellow;
420 Gizmos.DrawLine(NeckPos, leftHandPos);
421 Gizmos.DrawLine(NeckPos, rightHandPos);
426 float head_yaw = eyeTransform.localRotation.eulerAngles.y;
427 float body_yaw = last_yaw;
430 float yaw_diff = Mathf.DeltaAngle(head_yaw, body_yaw);
433 yaw_diff = Mathf.Sign(yaw_diff) * Mathf.Max(0, Mathf.Abs(yaw_diff) - max_head_yaw);
436 float yaw_adapt_speed = Mathf.Abs(yaw_diff) * Time.deltaTime * 2.0f;
439 return Quaternion.Euler(
440 bodyTransform.localRotation.eulerAngles.x,
441 Mathf.MoveTowardsAngle(body_yaw, head_yaw, yaw_adapt_speed),
442 bodyTransform.localRotation.eulerAngles.z
447 Vector3 thPos = pivotTransform.position +
new Vector3(-foot_offset_from_pivot.x, foot_offset_from_pivot.y, foot_offset_from_pivot.z);
449 leftFootTarget.forward = Vector3.Lerp(leftFootTarget.forward, pivotTransform.forward - 0.5f * pivotTransform.right, foot_follow_speed * Time.deltaTime);
451 leftFootTarget.position = Vector3.Lerp(leftFootTarget.position, thPos, foot_follow_speed * Time.deltaTime);
455 Vector3 thPos = pivotTransform.position + foot_offset_from_pivot;
457 rightFootTarget.forward = Vector3.Lerp(rightFootTarget.forward, pivotTransform.forward + 0.5f * pivotTransform.right, foot_follow_speed * Time.deltaTime);
459 rightFootTarget.position = Vector3.Lerp(rightFootTarget.position, thPos, foot_follow_speed * Time.deltaTime);
463 Vector3 r_origin = bodyTransform.position;
465 if (Physics.Raycast(r_origin, Vector3.down, out RaycastHit hit, 2.0f, groundCollisionMask))
467 pivotTransform.position = hit.point;
470 pivotTransform.forward = playerRig.XZPlaneFacingDirection;
476 public bool synchronizePose =
false;
478 [ServerRpc(RequireOwnership =
false)]
479 private void syncServerRpc(InternalState state)
481 m_ReplicatedState.Value = state;
488 InternalState state =
new InternalState();
489 state.FromReference(
this);
493 m_ReplicatedState.Value.ApplyState(
this);
497 private readonly NetworkVariable<InternalState> m_ReplicatedState =
new NetworkVariable<InternalState>(NetworkVariableReadPermission.Everyone,
new InternalState());
499 private struct InternalState : IInternalState<AVR_PoseProvider>
501 public Vector3 lookAtPos;
502 public Quaternion leftHandRot;
503 public Quaternion rightHandRot;
504 public Vector3 leftFootPos;
505 public Quaternion leftFootRot;
506 public Vector3 rightFootPos;
507 public Quaternion rightFootRot;
508 public Vector3 pivotPos;
509 public Quaternion pivotRot;
510 public Vector3 bodyPos;
511 public Quaternion bodyRot;
512 public Vector3 eyePos;
513 public Quaternion eyeRot;
514 public Vector3 leftHandPos;
515 public Vector3 rightHandPos;
517 public void FromReference(AVR_PoseProvider reference)
519 this.lookAtPos = reference.lookAtPos;
520 this.leftHandRot = reference.leftHandRot;
521 this.rightHandRot = reference.rightHandRot;
522 this.leftFootPos = reference.leftFootPos;
523 this.leftFootRot = reference.leftFootRot;
524 this.rightFootPos = reference.rightFootPos;
525 this.rightFootRot = reference.rightFootRot;
526 this.pivotPos = reference.pivotPos;
527 this.pivotRot = reference.pivotRot;
528 this.bodyPos = reference.bodyPos;
529 this.bodyRot = reference.bodyRot;
530 this.eyePos = reference.eyePos;
531 this.eyeRot = reference.eyeRot;
532 this.leftHandPos = reference.leftHandPos;
533 this.rightHandPos = reference.rightHandPos;
536 public void ApplyState(AVR_PoseProvider reference)
541 public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
543 serializer.SerializeValue(ref lookAtPos);
544 serializer.SerializeValue(ref leftHandRot);
545 serializer.SerializeValue(ref rightHandRot);
546 serializer.SerializeValue(ref leftFootPos);
547 serializer.SerializeValue(ref leftFootRot);
548 serializer.SerializeValue(ref rightFootPos);
549 serializer.SerializeValue(ref rightFootRot);
550 serializer.SerializeValue(ref pivotPos);
551 serializer.SerializeValue(ref pivotRot);
552 serializer.SerializeValue(ref bodyPos);
553 serializer.SerializeValue(ref bodyRot);
554 serializer.SerializeValue(ref eyePos);
555 serializer.SerializeValue(ref eyeRot);
556 serializer.SerializeValue(ref leftHandPos);
557 serializer.SerializeValue(ref rightHandPos);
Estimates the pose of a player from the locations of VR controllers and HMD
Vector3 lookAtPos
Endpoint of the players view vector
A PoseNaturalizationFilter "naturalizes" a pose. For instance, when a player places the controllers o...
Makes a property of an object only show in the Network-behaviour window. Also works for private/prote...
Quaternion CorrectBodyYawAngle(Quaternion rot)
Sets the documentation html file inside of Packages/com.avr.core/Documentation/html of a given class...
void GetLeanTransform(out Quaternion rot, out Vector3 pos)
Vector3 ApplyInertia(Vector3 current, Vector3 target)
Assigns given attributes to a foldout group in the inspector. The way these are drawn is determined b...
LayerMask groundCollisionMask
Collision mask of the ground
void GetStandingTransform(out Quaternion rot, out Vector3 pos)
Transform rightFootTarget