private void PreviewArea() { //visualize: Vector3[] playspacePerimeterOnFloor = new Vector3[_playspaceCorners.Count]; Vector3[] playspacePerimeterOnCeiling = new Vector3[_playspaceCorners.Count]; //populate floor and ceiling corner loops: for (int i = 0; i < _playspaceCorners.Count; i++) { //cache floor and ceiling locations: Vector3 floor = TransformUtilities.WorldPosition(pcfAnchor.Position, pcfAnchor.Rotation, _playspaceCorners[i]); Vector3 ceiling = floor + new Vector3(0, Height); playspacePerimeterOnFloor[i] = floor; playspacePerimeterOnCeiling[i] = ceiling; //draw corner supports: LineRenderer cornerSupportsOutline = Lines.DrawLine($"PlayspaceCornerSupport{i}", Color.green, Color.green, .005f, floor, ceiling); cornerSupportsOutline.material = perimeterOutlineMaterial; } //draw ceiling and floor perimeter: LineRenderer ceilingOutline = Lines.DrawLine($"PlayspaceCeilingOutline", Color.green, Color.green, .005f, playspacePerimeterOnCeiling); LineRenderer floorOutline = Lines.DrawLine($"PlayspaceFloorOutline", Color.green, Color.green, .005f, playspacePerimeterOnFloor); ceilingOutline.material = perimeterOutlineMaterial; floorOutline.material = perimeterOutlineMaterial; }
//Loops: private void Update() { if (!HandInput.Ready) { return; } //place: transform.SetPositionAndRotation(_managedHand.Skeleton.Position, _managedHand.Skeleton.Rotation); //hide axis if inside clip plane: _axisVisualizer.enabled = !_managedHand.Skeleton.InsideClipPlane; //wrist: Lines.DrawLine(Name("wrist"), GetColor(_managedHand.Skeleton.WristCenter.InsideClipPlane), GetColor(_managedHand.Skeleton.InsideClipPlane), .0005f, _managedHand.Skeleton.WristCenter.positionFiltered, _managedHand.Skeleton.Position); //fingers: DrawDigit("thumb", _managedHand.Skeleton.Thumb, GetColor(_managedHand.Skeleton.Thumb.Knuckle.InsideClipPlane), GetColor(_managedHand.Skeleton.Thumb.Tip.InsideClipPlane)); DrawDigit("index", _managedHand.Skeleton.Index, GetColor(_managedHand.Skeleton.Index.Knuckle.InsideClipPlane), GetColor(_managedHand.Skeleton.Index.Tip.InsideClipPlane)); DrawDigit("middle", _managedHand.Skeleton.Middle, GetColor(_managedHand.Skeleton.Middle.Knuckle.InsideClipPlane), GetColor(_managedHand.Skeleton.Middle.Tip.InsideClipPlane)); DrawDigit("ring", _managedHand.Skeleton.Ring, GetColor(_managedHand.Skeleton.Ring.Knuckle.InsideClipPlane), GetColor(_managedHand.Skeleton.Ring.Tip.InsideClipPlane)); DrawDigit("pinky", _managedHand.Skeleton.Pinky, GetColor(_managedHand.Skeleton.Pinky.Knuckle.InsideClipPlane), GetColor(_managedHand.Skeleton.Pinky.Tip.InsideClipPlane)); //finger connections: DrawBone("thumbConnection", _managedHand.Skeleton.Position, _managedHand.Skeleton.Thumb.Knuckle, GetColor(_managedHand.Skeleton.InsideClipPlane), GetColor(_managedHand.Skeleton.Thumb.Knuckle.InsideClipPlane)); DrawBone("indexConnection", _managedHand.Skeleton.Position, _managedHand.Skeleton.Index.Knuckle, GetColor(_managedHand.Skeleton.InsideClipPlane), GetColor(_managedHand.Skeleton.Index.Knuckle.InsideClipPlane)); DrawBone("middleConnection", _managedHand.Skeleton.Position, _managedHand.Skeleton.Middle.Knuckle, GetColor(_managedHand.Skeleton.InsideClipPlane), GetColor(_managedHand.Skeleton.Middle.Knuckle.InsideClipPlane)); DrawBone("ringConnection", _managedHand.Skeleton.Position, _managedHand.Skeleton.Ring.Knuckle, GetColor(_managedHand.Skeleton.InsideClipPlane), GetColor(_managedHand.Skeleton.Ring.Knuckle.InsideClipPlane)); DrawBone("pinkyConnection", _managedHand.Skeleton.Position, _managedHand.Skeleton.Pinky.Knuckle, GetColor(_managedHand.Skeleton.InsideClipPlane), GetColor(_managedHand.Skeleton.Pinky.Knuckle.InsideClipPlane)); }
private void DrawDigit(string fingerName, ManagedFinger finger, Color colorA, Color colorB) { fingerName = Name(fingerName); Lines.DrawLine(fingerName, colorA, colorB, .0005f, finger.PointLocationsFiltered); if (_managedHand.Visible && finger.IsVisible) { Lines.SetVisibility(fingerName, true); } else { Lines.SetVisibility(fingerName, false); } }
private void DrawBone(string fingerName, Vector3 from, ManagedKeypoint to, Color colorA, Color colorB) { fingerName = Name(fingerName); Lines.DrawLine(fingerName, colorA, colorB, .0005f, from, to.positionFiltered); if (_managedHand.Visible && to.Visible) { Lines.SetVisibility(fingerName, true); } else { Lines.SetVisibility(fingerName, false); } }
private void HandleDragUpdate(InteractionPoint[] interactionPoint, Vector3 position, Quaternion rotation, float scale) { float percentage = MathUtilities.TraveledPercentage(startPosition.position, endPosition.position, position); handle.transform.position = Vector3.Lerp(startPosition.position, endPosition.position, Mathf.Clamp01(percentage)); _value = Mathf.Lerp(minValue, maxValue, percentage); if (wholeNumbers) { _value = Mathf.Round(_value); } OnChanged?.Invoke(Value); //draw connection line: Lines.DrawLine(_lineID, Color.green, Color.green, .0025f, interactionPoint[0].position, handle.transform.position); //dragged too far? if (Vector3.Distance(interactionPoint[0].position, handle.transform.position) > dragBreakDistance) { handle.StopGrab(); } }
public void GrabUpdate(InteractionPoint interactionPoint) { //dragging started? if (!Dragging) { foreach (var item in _initialInteractionPoses) { if (Vector3.Distance(item.Key.position, item.Value.position) > _dragThreshold) { //halt physics: if (_rigidBody != null) { _rigidBody.velocity = Vector3.zero; _rigidBody.angularVelocity = Vector3.zero; _rigidBody.isKinematic = true; } //find offset: Matrix4x4 matrix = Matrix4x4.TRS(item.Key.position, item.Key.rotation, Vector3.one); Vector3 positionOffset = matrix.inverse.MultiplyPoint3x4(transform.position); Quaternion rotationOffset = Quaternion.Inverse(item.Key.rotation) * transform.rotation; _offset = new Pose(positionOffset, rotationOffset); //resets: _position = Vector3.zero; _rotation = Quaternion.identity; //status: Dragging = true; OnDragBegin?.Invoke(item.Key); break; } } } //dragging? if (Dragging) { //find center of interaction points involved with this drag: Bounds dragBounds = new Bounds(activeInteractionPoints[0].position, Vector3.zero); for (int i = 1; i < activeInteractionPoints.Count; i++) { dragBounds.Encapsulate(activeInteractionPoints[i].position); } //discover drag distance and percentage; float biManualDistance = dragBounds.size.magnitude; //holders: Vector3 dragLocation = Vector3.zero; Quaternion dragOrientation = Quaternion.identity; Vector3 forward = Vector3.zero; float scaleDelta = 0; //rotation: if (activeInteractionPoints.Count == 2) { //get rotated amount: forward = activeInteractionPoints[0].position - activeInteractionPoints[1].position; Vector3 forwardNormalized = forward.normalized; Vector3 previousForward = _bimanualBaseRotation * Vector3.forward; Vector3 up = Vector3.Cross(forwardNormalized, previousForward).normalized; float angle = Vector3.SignedAngle(previousForward, forwardNormalized, up); //update rotation: Quaternion rotationDelta = Quaternion.AngleAxis(angle, up); _bimanualBaseRotation = rotationDelta * _bimanualBaseRotation; dragOrientation = _bimanualBaseRotation * _offset.rotation; } else { dragOrientation = activeInteractionPoints[0].rotation * _offset.rotation; } //position: if (activeInteractionPoints.Count == 2) { Matrix4x4 matrix = Matrix4x4.TRS(dragBounds.center, _bimanualBaseRotation, Vector3.one); dragLocation = matrix.MultiplyPoint3x4(_offset.position); } else { Matrix4x4 matrix = Matrix4x4.TRS(activeInteractionPoints[0].position, activeInteractionPoints[0].rotation, Vector3.one); dragLocation = matrix.MultiplyPoint3x4(_offset.position); } //scale: if (activeInteractionPoints.Count == 2) { scaleDelta = biManualDistance - _scaleInitialDistance; } //set smoothing origins: if (_position == Vector3.zero || _rotation == Quaternion.identity) { _position = dragLocation; _rotation = dragOrientation; } //application: if (draggable) { _position = Vector3.SmoothDamp(_position, dragLocation, ref _positionVelocity, positionSmoothTime); if (_rigidBody != null) { _rigidBody.MovePosition(_position); _averageVelocity.Add(_rigidBody.velocity); _averageAngularVelocity.Add(_rigidBody.angularVelocity); } else { transform.position = _position; } } if (rotatable) { _rotation = MotionUtilities.SmoothDamp(_rotation, dragOrientation, ref _rotationVelocity, rotationSmoothTime); if (_rigidBody != null) { _rigidBody.MoveRotation(_rotation); } else { transform.rotation = _rotation; } } if (scalable && activeInteractionPoints.Count == 2) { Vector3 proposedScale = _scaleBase + (Vector3.one * scaleDelta); //constrain scale and do not not assume uniform initial scale: if (Mathf.Max(proposedScale.x, proposedScale.y, proposedScale.z) <= maxScale && Mathf.Min(proposedScale.x, proposedScale.y, proposedScale.z) >= minScale) { transform.localScale = _scaleBase + (Vector3.one * scaleDelta); } } //visuals: if (activeInteractionPoints.Count == 2) { Lines.SetVisibility(_handConnectionLine, true); Lines.DrawLine(_handConnectionLine, Color.cyan, Color.cyan, .0005f, activeInteractionPoints[0].position, activeInteractionPoints[1].position); } //status: OnDragUpdate?.Invoke(activeInteractionPoints.ToArray(), _position, _rotation, scaleDelta); } }
private void DrawPerimeter_HandleTriggerDown(byte controllerId, float triggerValue) { //cache room details (to avoid tilt if room analyzation updates): if (_plottedCorners.Count == 0) { _roomVerticalCenter = SurfaceDetails.VerticalCenter; _roomCeilingHeight = SurfaceDetails.CeilingHeight; _roomFloorHeight = SurfaceDetails.FloorHeight; Height = SurfaceDetails.RoomHeight; } //corner details: Vector3 controlPosition = MLInput.GetController(controllerId).Position; Vector3 cornerLocation = new Vector3(controlPosition.x, _roomVerticalCenter, controlPosition.z); //invalid placement if this proposed segment would overlap any previous ones: if (_plottedCorners.Count >= 3) { //proposed line segment: Vector2 proposedStart = new Vector2(_plottedCorners[_plottedCorners.Count - 1].position.x, _plottedCorners[_plottedCorners.Count - 1].position.z); Vector2 proposedEnd = new Vector2(cornerLocation.x, cornerLocation.z); //look for any intersections (in 2d): for (int i = 1; i < _plottedCorners.Count; i++) { //get a pervious segment: Vector2 startA = new Vector2(_plottedCorners[i - 1].position.x, _plottedCorners[i - 1].position.z); Vector2 endA = new Vector2(_plottedCorners[i].position.x, _plottedCorners[i].position.z); //is there an intersection with something previous? Vector2 previousIntersection = Vector2.zero; if (MathUtilities.LineSegmentsIntersecting(startA, endA, proposedStart, proposedEnd, false)) { //ignore this proposed corner since it would create an overlapped wall: return; } } } //bounds: if (_plottedCorners.Count == 0) { _plottedBounds = new Bounds(cornerLocation, Vector3.zero); } else { _plottedBounds.Encapsulate(cornerLocation); } //loop complete? bool loopComplete = false; if (_plottedCorners.Count > 3) { //close to first? close to last? close the loop: if (Vector3.Distance(cornerLocation, _plottedCorners[0].position) <= _loopClosureDistance || Vector3.Distance(cornerLocation, _plottedCorners[_plottedCorners.Count - 1].position) <= _loopClosureDistance) { _plottedCorners.Add(_plottedCorners[0]); loopComplete = true; } } if (!loopComplete) { //visualize corner: GameObject corner = GameObject.CreatePrimitive(PrimitiveType.Cylinder); corner.GetComponent <Renderer>().material = cornerMaterial; corner.name = $"(Corner{_plottedCorners.Count})"; corner.transform.position = cornerLocation; corner.transform.localScale = new Vector3(0.0508f, Height * .5f, 0.0508f); _plottedCorners.Add(corner.transform); //visualize boundry: Lines.DrawLine("Boundry", Color.white, Color.white, .01f, _plottedCorners.ToArray()); } else { //visualize boundry: Lines.DrawLine("Boundry", Color.white, Color.white, .01f, _plottedCorners.ToArray()); ChangeState(State.FindWalls); } }