Beispiel #1
0
        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;
                        events.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:
                events.OnDragUpdate?.Invoke(activeInteractionPoints.ToArray(), _position, _rotation, scaleDelta);
            }
        }
Beispiel #2
0
        public void GrabEnd(InteractionPoint interactionPoint)
        {
            //avoid issues with an actual physical release if StopGrab was used prior:
            if (activeInteractionPoints.Count == 0)
            {
                return;
            }

            //sound:
            if (releasedSound != null)
            {
                _audioSource.PlayOneShot(releasedSound, 1);
            }

            //colorize:
            foreach (var item in GetComponentsInChildren <Renderer>())
            {
                if (item.material.HasProperty("_Color"))
                {
                    item.material.SetColor("_Color", idleColor);
                }
            }

            Grabbed = false;

            //clear up bimanual manipulation:
            if (activeInteractionPoints.Count == 2)
            {
                activeInteractionPoints.Clear();
                _initialInteractionPoses.Clear();
            }

            //remove:
            _initialInteractionPoses.Remove(interactionPoint);
            activeInteractionPoints.Remove(interactionPoint);

            if (Dragging && activeInteractionPoints.Count == 0)
            {
                if (_rigidBody != null)
                {
                    if (throwable && activeInteractionPoints.Count == 0)
                    {
                        //gavity?
                        if (enableGravityOnRelease)
                        {
                            _rigidBody.useGravity = true;
                        }

                        //calculate an average velocity:
                        Vector3 velocity = Vector3.zero;
                        int     start    = _averageVelocity.Count - _averageVelocityCount;
                        start = Mathf.Clamp(start, _averageVelocityEndTrim, start);
                        int count = 0;
                        for (int i = start; i < _averageVelocity.Count; i++)
                        {
                            velocity += _averageVelocity[i];
                            count++;
                        }
                        velocity           /= count;
                        _rigidBody.velocity = velocity;

                        //calculate an average angular velocity:
                        velocity = Vector3.zero;
                        start    = _averageAngularVelocity.Count - _averageVelocityCount;
                        start    = Mathf.Clamp(start, _averageVelocityEndTrim, start);
                        count    = 0;
                        for (int i = start; i < _averageAngularVelocity.Count; i++)
                        {
                            velocity += _averageAngularVelocity[i];
                            count++;
                        }
                        velocity /= count;
                        _rigidBody.angularVelocity = velocity;

                        //clear:
                        _averageVelocity.Clear();
                        _averageAngularVelocity.Clear();
                    }
                    else
                    {
                        _rigidBody.velocity        = Vector3.zero;
                        _rigidBody.angularVelocity = Vector3.zero;
                    }

                    _rigidBody.isKinematic = false;
                }

                Dragging = false;
                events.OnDragEnd?.Invoke(interactionPoint);
                Lines.SetVisibility(_handConnectionLine, false);
            }

            events.OnGrabEnd?.Invoke(interactionPoint);
        }
Beispiel #3
0
 private void HandleDragEnd(InteractionPoint interactionPoint)
 {
     Lines.SetVisibility(_lineID, false);
     events.OnReleased?.Invoke();
 }
Beispiel #4
0
 private void HandleDragBegin(InteractionPoint interactionPoint)
 {
     Lines.SetVisibility(_lineID, true);
 }
        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);
            }
        }
 private void RemoveDebugLines()
 {
     Lines.DestroyAllLines();
 }
 private void OnDisable()
 {
     Lines.SetVisibility($"Forward{GetInstanceID()}", false);
     Lines.SetVisibility($"Right_{GetInstanceID()}", false);
     Lines.SetVisibility($"Up_{GetInstanceID()}", false);
 }
 //Update:
 private void Update()
 {
     Lines.DrawRay($"Forward{GetInstanceID()}", Color.blue, Color.black, transform.position, transform.forward * length, width);
     Lines.DrawRay($"Right_{GetInstanceID()}", Color.red, Color.black, transform.position, transform.right * length, width);
     Lines.DrawRay($"Up_{GetInstanceID()}", Color.green, Color.black, transform.position, transform.up * length, width);
 }
Beispiel #9
0
 //Event Handlers:
 private void HandleFingerVisibilityChanged(ManagedFinger finger, bool visible)
 {
     Lines.SetVisibility(Name(finger), visible);
 }