CActorArm _oActorArm; // The arm connected to us. Null if we're not active #endregion Fields #region Methods public static CHandTarget FindOrCreateRightSideHandTarget(CHandTarget oHandTargetL) { // Find or create a 'right side mirrored copy' of design-time-defined left-side hand target. Bone structure only has hand targets defined for the left body side to prevent duplication. Mirror the left node into a mirrored right node for processing of the right body side // Create a right side node that will store the mirrored copy of the source left-side node. string sNameHandTargetRight = oHandTargetL.gameObject.name + "-Right"; // Right-side hand targets are generated & mirrored as needed. Their name is suffixed with '-Right' CHandTarget oHandTargetR = CUtility.FindOrCreateNode(oHandTargetL.transform.parent, sNameHandTargetRight, typeof(CHandTarget)) as CHandTarget; oHandTargetR.transform.parent = oHandTargetL.transform.parent; // Right side gets same parent as left side //=== Calculate the mirrored position of right side === Vector3 vecTarget = oHandTargetL.transform.localPosition; vecTarget.x = -vecTarget.x; oHandTargetR.transform.localPosition = vecTarget; //=== Adjust hand target rotation to requested body side === Vector3 vecRotTarget = oHandTargetL.transform.localRotation.eulerAngles; vecRotTarget.y = Mathf.PI - vecRotTarget.y; vecRotTarget.z = -vecRotTarget.z; oHandTargetR.transform.localRotation = Quaternion.Euler(vecRotTarget); //=== Create a copy of the anim area subnode if it exists === //Transform oAnimAreaLT = oHandTargetL.transform.FindChild("AnimArea"); //if (oAnimAreaLT != null) { // BoxCollider oBoxColR = CUtility.FindOrCreateNode(oHandTargetR.transform, oAnimAreaLT.name, typeof(BoxCollider)) as BoxCollider; // oBoxColR.enabled = false; // oBoxColR.isTrigger = true; // oBoxColR.transform.localScale = oAnimAreaLT.localScale; // oBoxColR.transform.localPosition = Vector3.zero; // oBoxColR.transform.localRotation = Quaternion.identity; //} return oHandTargetR; }
public void ArmRaycastPin_End() { // Check at end of raycast procedure to unpin if nothing was found //_bPinByClosestVert = true; // Go to vert-pinning mode now to finalize the pin (much less acurate but survives body movement) if (_oBodyArmPin == null) { //###CHECK!! Correct cancellation?? _oHandTarget.ConnectHandToHandTarget(null); // Destroy arm from pin at end of raycast search if we're not connected to anything _oHandTarget = null; //??? _oObj.PropSet(EActorArm.Pinned, 0); // Unpin?? //_oConfJoint_Extremity.angularXMotion = _oConfJoint_Extremity.angularYMotion = _oConfJoint_Extremity.angularZMotion = ConfigurableJointMotion.Limited; // If raycasting results in no pin to raycast vert we re-enable angular constraint??? ###TODO!!!! ###DESIGN!! } }
//--------------------------------------------------------------------------- CREATE / DESTROY public override void OnStart_DefineLimb() { _nDrivePos = 0.1f * C_DrivePos; // Weaken the hand drive so hand doesn't fly from pin to pin //###TUNE //_memVecRayHitInfo = new CMemAlloc<Vector3>(2); //=== Init Bones and Joints === CJointDriver oJointChestUpper = _oBody._oActor_Chest._oJointExtremity; _aJoints.Add(_oJointCollar = CJointDriver.Create(this, oJointChestUpper, _sSidePrefixL+"Collar", 30, 2.5f, -010, 050, 030, 021, 1)); // X = Collar Up/Down OK, Z has 17 back and 25 forward (avg looks ok) _aJoints.Add(_oJointShoulderBend = CJointDriver.Create(this, _oJointCollar, _sSidePrefixL+"ShldrBend", 15, 2.0f, -085, 035, 000, 110, 1)); // X = Shoulder Up/Down OK, Z = Back goes to -40, Forward to 110!!! (###IMPROVE: Another joint?) _aJoints.Add(_oJointShoulderTwist = CJointDriver.Create(this, _oJointShoulderBend, _sSidePrefixL+"ShldrTwist", 20, 1.5f, -000, 000, 080, 000, 1)); // Y = Shoulder twist goes from -95 to 80 so max. ###PROBLEM: Shimmer in high rotation! _aJoints.Add(_oJointForearmBend = CJointDriver.Create(this, _oJointShoulderTwist, _sSidePrefixL+"ForearmBend", 10, 1.5f, -020, 135, 000, 000, 1)); // X = Elbow bend from -20 to 135. ok. _aJoints.Add(_oJointForearmTwist = CJointDriver.Create(this, _oJointForearmBend, _sSidePrefixL+"ForearmTwist", 20, 1.0f, -000, 000, 080, 000, 1)); // Y = Forearm twist from -90 to 80 so max. ###IMPROVE: Could rotate the axes on the twists so we use XL/XH _aJoints.Add(_oJointExtremity = CJointDriver.Create(this, _oJointForearmTwist, _sSidePrefixL+"Hand", 10, 0.5f, -070, 080, 010, 029, 1)); // X = Hand -down(-70) / +up (+80), Y = Hand twist +/-10, Z = Hand side-to-side -28 to +30 //ConfigFingerRoot(1, "Index"); // Thumb is handled below ###DESIGN!!! Fingers in Unity PhysX is just a no-go because of extremely poor latency... what to do????? //ConfigFingerRoot(2, "Mid"); //ConfigFingerRoot(3, "Ring"); //??? ###HACK!! Disabled man's carpal1&2 in 3dsMax so we can use same code as women's! //ConfigFingerRoot(4, "Pinky"); //CJointDriver oJointFingerBoneParent = _oJointExtremity; //oJointFingerBoneParent = ConfigFingerBone(oJointFingerBoneParent, 0, 0, "Thumb", 005f, -030f, 005f, 025f); //oJointFingerBoneParent = ConfigFingerBone(oJointFingerBoneParent, 0, 1, "Thumb", 010f, -015f, 000f, 000f); //oJointFingerBoneParent = ConfigFingerBone(oJointFingerBoneParent, 0, 2, "Thumb", 010f, -015f, 000f, 000f); //=== Init Hotspot === if (_eBodySide == 0) _oHotSpot = CHotSpot.CreateHotspot(this, _oBody._oBodyBase.FindBone("chestUpper/lCollar/lShldrBend/lShldrTwist/lForearmBend/lForearmTwist/lHand"), "Left Hand", true, new Vector3(0, 0, 0)); else _oHotSpot = CHotSpot.CreateHotspot(this, _oBody._oBodyBase.FindBone("chestUpper/rCollar/rShldrBend/rShldrTwist/rForearmBend/rForearmTwist/rHand"), "Right Hand", true, new Vector3(0, 0, 0)); //=== Init CObject === _oObj = new CObject(this, _oBody._oBodyBase._nBodyID, typeof(EActorArm), "Arm", "Arm" + _sSidePrefixU); _oObj.PropGroupBegin("", "", true); AddBaseActorProperties(); // The first properties of every CActor subclass are Pinned, pos & rot //_oObj.PropAdd(EActorArm.HandTarget, "HandTarget", typeof(EHandTargets), (int)EHandTargets.ManualPosition, ""); _oObj.PropAdd(EActorArm.Hand_UpDown, "Hand-UpDown", 0, -100, 100, ""); _oObj.PropAdd(EActorArm.Hand_LeftRight, "Hand-LeftRight", 0, -100, 100, ""); _oObj.PropAdd(EActorArm.Hand_Twist, "Hand-Twist", 0, -100, 100, ""); //_oObj.PropAdd(EActorArm.Fingers_Close, "Fingers-Close", 0, -100, 100, "", CProp.Hide); //###BROKEN //_oObj.PropAdd(EActorArm.Fingers_Spread, "Fingers-Spread", 0, -100, 100, "", CProp.Hide); //_oObj.PropAdd(EActorArm.Fingers_ThumbPose, "Fingers-ThumbPose", typeof(EThumbPose), (int)EThumbPose.AlongsideFingers, "", CProp.Hide); //_oObj.PropAdd(EActorArm.UserControl, "User Control", 0, 0, 1, ""); _oObj.FinishInitialization(); _oHandTarget_RaycastPin = CActorArm.FindHandTarget(_oBody, EHandTargets.RaycastPin, _eBodySide == EBodySide.Right); // Find the raycast pin hand target as we use it heavily and it is reparented }
//--------------------------------------------------------------------------- ARM RAYCAST PINNING: User selecting where to place the closest arm of the selected body on a body surface through raycasting public void ArmRaycastPin_Begin() { _oHandTarget = _oHandTarget_RaycastPin; _oHandTarget.ConnectHandToHandTarget(this); _oHandTarget.transform.position = _oJointExtremity.transform.position; // Manually set the hand target position to the hand position so slerp in Update doesn't start from some old stale position ###MOVE? _oBodyArmPin = null; //_nArmPinBodyColVert = -1; //_nTimeStartPinSet = 0; // Reset our start-of-slerp time to zero so it's initialize at first real pin position //_bPinByClosestVert = false; // We start pinning by ray position as it's much more accurate. When user releases pinning key we go to vert pinning which will handle changes in body orientation ###IMPROVE: Always have 'ray precision' pinning by storing offset and rotating to closest vert normal? _oConfJoint_Extremity.angularXMotion = _oConfJoint_Extremity.angularYMotion = _oConfJoint_Extremity.angularZMotion = ConfigurableJointMotion.Free; // We free rotation constraint so hand is just attraced by position (and repelled by colliders) Greatly simplifies hand raycasting!! }