Пример #1
0
        public static void ImportImage(string path)
        {
            path = Path.Combine(App.MediaLibraryPath(), "Images", path);
            var image = new ReferenceImage(path);

            image.RequestLoad(allowMainThread: true);
            var tr = new TrTransform();

            tr.translation = ApiManager.Instance.BrushPosition;
            tr.rotation    = ApiManager.Instance.BrushRotation;
            CreateWidgetCommand createCommand = new CreateWidgetCommand(
                WidgetManager.m_Instance.ImageWidgetPrefab, tr);

            SketchMemoryScript.m_Instance.PerformAndRecordCommand(createCommand);
            ImageWidget imageWidget = createCommand.Widget as ImageWidget;

            imageWidget.ReferenceImage = image;
            imageWidget.Show(true);
            createCommand.SetWidgetCost(imageWidget.GetTiltMeterCost());

            WidgetManager.m_Instance.WidgetsDormant = false;
            SketchControlsScript.m_Instance.EatGazeObjectInput();
            SelectionManager.m_Instance.RemoveFromSelection(false);
        }
Пример #2
0
        /// Pass a Canvas parent, and a transform in that canvas's space.
        /// If overrideDesc passed, use that for the visuals -- m_CurrentBrush does not change.
        public void CreateNewLine(CanvasScript canvas, TrTransform xf_CS,
                                  ParametricStrokeCreator creator, BrushDescriptor overrideDesc = null)
        {
            // If straightedge is enabled, we may have a minimum size requirement.
            // Initialize parametric stroke creator for our type of straightedge.
            // Maybe change the brush to a proxy brush.
            BrushDescriptor desc = overrideDesc != null ? overrideDesc : m_CurrentBrush;

            m_CurrentCreator = creator;

            // Parametric creators want control over the brush size.
            if (m_CurrentCreator != null)
            {
                m_ParametricCreatorBackupStrokeSize = m_CurrentBrushSize;
                m_CurrentBrushSize = m_CurrentCreator.ProcessBrushSize(m_CurrentBrushSize);
            }

            m_LastUsedBrushSize_CS = (1 / Coords.CanvasPose.scale) * BrushSizeAbsolute;
            m_LineLength_CS        = 0.0f;

            m_CurrentLine = BaseBrushScript.Create(
                canvas.transform, xf_CS,
                desc, m_CurrentColor, m_CurrentBrushSize);
        }
Пример #3
0
        /// Copies and pastes the current selection to the current canvas.
        public void DuplicateSelection(bool offsetDuplicate = false)
        {
            TrTransform xf = SelectionManager.m_Instance.SelectionTransform;

            if (offsetDuplicate)
            {
                // Scoot all the strokes and widgets.
                // TODO: Make this relative to the user's facing.
                Vector3 offset = m_DuplicateOffset / App.Scene.Pose.scale * 0.5f;
                xf.translation += offset;
            }

            // Lil' jiggle.
            var controller = InputManager.ControllerName.Brush;

            if (SketchControlsScript.m_Instance.OneHandGrabController != InputManager.ControllerName.None)
            {
                controller = SketchControlsScript.m_Instance.OneHandGrabController;
            }
            InputManager.m_Instance.TriggerHapticsPulse(controller, 3, 0.15f, 0.07f);
            AudioManager.m_Instance.PlayDuplicateSound(InputManager.m_Instance.GetControllerPosition(controller));

            SketchMemoryScript.m_Instance.PerformAndRecordCommand(new DuplicateSelectionCommand(xf));
        }
Пример #4
0
        // A simplified version of TwoPointObjectTransformation. The following properties are true:
        //   1. The object-local-space direction between the left and right hands remains constant.
        //   2. The object-local-space position of LerpUnclamped(left, right, constraintPositionT) remains
        //      constant.
        //   3. obj1 has the same scale as obj0.
        //   4. (Corollary of 1-3) The object-local-space positions of left and right remain constant, if
        //      the distance between them does not change.
        public static TrTransform TwoPointObjectTransformationNoScale(
            TrTransform gripL0, TrTransform gripR0,
            TrTransform gripL1, TrTransform gripR1,
            TrTransform obj0, float constraintPositionT)
        {
            // Vectors from left-hand to right-hand
            Vector3 vLR0 = (gripR0.translation - gripL0.translation);
            Vector3 vLR1 = (gripR1.translation - gripL1.translation);

            Vector3     pivot0;
            TrTransform xfDelta;
            {
                pivot0 = Vector3.LerpUnclamped(gripL0.translation, gripR0.translation, constraintPositionT);
                var pivot1 = Vector3.LerpUnclamped(gripL1.translation, gripR1.translation, constraintPositionT);
                xfDelta.translation = pivot1 - pivot0;

                xfDelta.translation = Vector3.LerpUnclamped(
                    gripL1.translation - gripL0.translation,
                    gripR1.translation - gripR0.translation,
                    constraintPositionT);
                // TODO: check edge cases:
                // - |vLR0| or |vLR1| == 0 (ie, from and/or to are undefined)
                // - vLR1 == vLR0 * -1 (ie, infinite number of axes of rotation)
                xfDelta.rotation = Quaternion.FromToRotation(vLR0, vLR1);
                xfDelta.scale    = 1;
            }

            Quaternion deltaL = ConstrainRotationDelta(gripL0.rotation, gripL1.rotation, vLR0);
            Quaternion deltaR = ConstrainRotationDelta(gripR0.rotation, gripR1.rotation, vLR0);

            xfDelta = TrTransform.R(Quaternion.Slerp(deltaL, deltaR, 0.5f)) * xfDelta;

            // Set pivot point
            xfDelta = xfDelta.TransformBy(TrTransform.T(pivot0));
            return(xfDelta * obj0);
        }
Пример #5
0
        public void Deserialize()
        {
            m_Scene.Read(m_xformName, m_UsdCamera);

            var basisMat = Matrix4x4.identity;

            if (m_UnitsInMeters)
            {
                basisMat[0, 0] *= App.METERS_TO_UNITS;
                basisMat[1, 1] *= App.METERS_TO_UNITS;
                basisMat[2, 2] *= -1 * App.METERS_TO_UNITS;
            }
            m_UsdCamera.transform = ExportUtils.ChangeBasis(m_UsdCamera.transform, basisMat, basisMat.inverse);

            TrTransform xf_WS  = UsdXformToWorldSpaceXform(m_UsdCamera);
            TrTransform old_WS = TrTransform.FromTransform(transform);
            TrTransform new_WS = TrTransform.Lerp(old_WS, xf_WS, 1 - m_Smoothing);

            new_WS.scale = m_UsdCameraInfo.eyeScale != 0 ? m_UsdCameraInfo.eyeScale : 1;
            new_WS.ToTransform(transform);

            // Pre-M23.3, .usd files won't have fov defined, so this value will be negative.
            if (m_UsdCamera.fov > 0)
            {
                // A bit brute force, but we're running through all cameras in the scene to make
                // sure the preview shows the modified fov.
                for (int i = 0; i < m_PlaybackCameras.Length; ++i)
                {
                    if (m_PlaybackCameras[i].gameObject.activeInHierarchy &&
                        m_PlaybackCameras[i].isActiveAndEnabled)
                    {
                        m_PlaybackCameras[i].fieldOfView = m_UsdCamera.fov;
                    }
                }
            }
        }
Пример #6
0
        public void TestTransformVector4AsZDistance()
        {
            TrTransform randomXf      = RandomTr();
            int         listSize      = 10;
            var         list          = RandomVector4List(listSize);
            var         listDuplicate = new List <Vector4>(list);
            int         iVert         = 3;
            int         iVertEnd      = 8;

            // Do the original version.
            for (int i = iVert; i < iVertEnd; i++)
            {
                list[i] = new Vector4(list[i].x, list[i].y, randomXf.scale * list[i].z, list[i].w);
            }

            // Do the math utils version.
            MathUtils.TransformVector4AsZDistance(randomXf.scale, iVert, iVertEnd, listDuplicate.GetBackingArray());

            // Check results.
            for (int i = 0; i < listSize; i++)
            {
                AssertAlmostEqual(list[i], listDuplicate[i]);
            }
        }
Пример #7
0
        public override Bounds GetBounds_SelectionCanvasSpace()
        {
            if (m_Capsule != null)
            {
                TrTransform colliderToCanvasXf = App.Scene.SelectionCanvas.Pose.inverse *
                                                 TrTransform.FromTransform(m_Capsule.transform);
                Bounds bounds = new Bounds(colliderToCanvasXf * m_Capsule.center, Vector3.zero);

                // Transform the corners of the widget bounds into canvas space and extend the total bounds
                // to encapsulate them.
                Vector3 capsuleSize = new Vector3(2 * m_Capsule.radius, m_Capsule.height, 2 * m_Capsule.radius);
                for (int i = 0; i < 8; i++)
                {
                    bounds.Encapsulate(colliderToCanvasXf * (m_Capsule.center + Vector3.Scale(
                                                                 capsuleSize,
                                                                 new Vector3((i & 1) == 0 ? -0.5f : 0.5f,
                                                                             (i & 2) == 0 ? -0.5f : 0.5f,
                                                                             (i & 4) == 0 ? -0.5f : 0.5f))));
                }

                return(bounds);
            }
            return(base.GetBounds_SelectionCanvasSpace());
        }
Пример #8
0
        /// Changes the coordinate system of an active transformation.
        ///
        /// 'this' should be an active transformation, like "rotate 10 degrees about up".
        /// Its input and output coordinate systems should be the same.
        ///
        /// 'rhs' should be a passive transformation -- like a WorldFromObject
        /// coordinate change (aka a pose). Its input coordinate system should
        /// be the same as the coordinate system of 'this'.
        ///
        /// Returns a transform that performs the same action as 'this', but that operates
        /// in a different coordinate system: the output coordinate system of 'rhs'.
        ///
        /// See also https://en.wikipedia.org/wiki/Active_and_passive_transformation
        public TrTransform TransformBy(TrTransform rhs)
        {
            // Solving "X * rhs == rhs * this" for X, we get
            //
            //      X = rhs * this * inv(rhs)
            //
            // However, this naive calculation is inaccurate; manually expanding and
            // simplifying allows an unnecessary multiply+divide by rhs.scale to be
            // removed.
            //
            // This increases accuracy of .translation and .scale, and avoids problems
            // when rhs is non-invertible as a result of zero scale.
            Quaternion similar  = (rhs.rotation * this.rotation * rhs.rotation.TrueInverse());
            Vector3    retTrans = similar * (-this.scale * rhs.translation)
                                  + rhs.rotation * (rhs.scale * this.translation)
                                  + rhs.translation;

            return(new TrTransform
            {
                translation = retTrans,
                rotation = similar,
                scale = this.scale
            });
        }
Пример #9
0
        public override Bounds GetBounds_SelectionCanvasSpace()
        {
            if (m_Collider != null)
            {
                SphereCollider sphere             = m_Collider as SphereCollider;
                TrTransform    colliderToCanvasXf = App.Scene.SelectionCanvas.Pose.inverse *
                                                    TrTransform.FromTransform(m_Collider.transform);
                Bounds bounds = new Bounds(colliderToCanvasXf * sphere.center, Vector3.zero);

                // Transform the corners of the widget bounds into canvas space and extend the total bounds
                // to encapsulate them.
                for (int i = 0; i < 8; i++)
                {
                    bounds.Encapsulate(colliderToCanvasXf * (sphere.center +
                                                             sphere.radius *
                                                             new Vector3((i & 1) == 0 ? -1.0f : 1.0f,
                                                                         (i & 2) == 0 ? -1.0f : 1.0f,
                                                                         (i & 4) == 0 ? -1.0f : 1.0f)));
                }

                return(bounds);
            }
            return(base.GetBounds_SelectionCanvasSpace());
        }
Пример #10
0
 override public void ResetBrushForPreview(TrTransform localPointerXf)
 {
     base.ResetBrushForPreview(localPointerXf);
     m_UpdateTangentRequest.Clear();
 }
Пример #11
0
 protected override void InitBrush(BrushDescriptor desc,
                                   TrTransform localPointerXf)
 {
     base.InitBrush(desc, localPointerXf);
     m_UpdateTangentRequest.Clear();
 }
Пример #12
0
 public TrTransform this[Transform t] {
     get { return(TrTransform.FromTransform(t)); }
     set { value.ToTransform(t); }
 }
Пример #13
0
 public void SetLossyTransform(TrTransform transform)
 {
     vRigPosition = transform.translation;
     qRigRotation = transform.rotation;
     qAutoOrientJointLocalRotation = Quaternion.identity;
 }
Пример #14
0
        /// Like TwoPointNonUniformScale, but instead of scaling, adds size to an axis
        public static TrTransform TwoPointObjectTransformationAxisResize(
            Vector3 vScaleAxis0, float sizeAlongAxis,
            TrTransform gripL0, TrTransform gripR0, // prev
            TrTransform gripL1, TrTransform gripR1, // next
            TrTransform obj0,
            out float deltaScale,
            float deltaScaleMin = 0,
            float deltaScaleMax = float.PositiveInfinity)
        {
            // The vectors from left -> right hand can be decomposed into
            // "along scale axis" and "across scale axis".
            // The length of "along scale axis" varies; the change is the amount of scaling.
            // The length of "across scale axis" remains constant, because it doesn't scale.

            bool    shrinkageSideIsLeft;
            float   allowedShrinkage;
            float   along0;
            Vector3 vAcross; {
                Vector3 vLR0 = (gripR0.translation - gripL0.translation);
                along0 = Vector3.Dot(vLR0, vScaleAxis0);

                // Prevent negative scale by ensuring Sign(along0) == Sign(along1).
                // This causes the scale to turn into rotation. Note that Sign(along1) always == 1.
                // It also simplifies the following along0 and shrinkage checks.
                float sign = Mathf.Sign(along0);
                along0      *= sign;
                vScaleAxis0 *= sign;

                vAcross = vLR0 - along0 * vScaleAxis0;

                Vector3 center     = obj0.translation;
                float   halfExtent = sizeAlongAxis / 2;
                // Allow the right edge to be pushed all the way to the left hand, but no farther;
                // and vice versa for the left edge + right hand.
                float leftShrinkage  = halfExtent - Vector3.Dot(vScaleAxis0, gripL0.translation - center);
                float rightShrinkage = halfExtent - Vector3.Dot(vScaleAxis0, center - gripR0.translation);
                if (leftShrinkage < rightShrinkage)
                {
                    allowedShrinkage    = leftShrinkage;
                    shrinkageSideIsLeft = true;
                }
                else
                {
                    allowedShrinkage    = rightShrinkage;
                    shrinkageSideIsLeft = false;
                }

                // Might be < 0 if both hands are outside the extents (which won't normally happen)
                allowedShrinkage = Mathf.Max(0, allowedShrinkage);
            }

            float along1; {
                // Calculate |vAlong1| using the identity:
                // |vLR|^2 = |vAlong|^2 + |vAcross|^2
                Vector3 vLR1          = (gripR1.translation - gripL1.translation);
                float   along1Squared = vLR1.sqrMagnitude - vAcross.sqrMagnitude;
                if (along1Squared < 0)
                {
                    // Impossible to satisfy the constraint. We can refuse to scale (along1 = along0),
                    // or clamp the scale to the nearest valid value (along1 = 0).
                    along1 = 0;
                }
                else
                {
                    along1 = Mathf.Sqrt(along1Squared);
                }
            }

            // Calculate and apply constraints to deltaScale
            {
                float sizeAlongAxis1 = sizeAlongAxis + Mathf.Max(-allowedShrinkage, along1 - along0);
                deltaScale = sizeAlongAxis1 / sizeAlongAxis;

                // If hands switch, treat that as rotation rather than inverting the object
                deltaScale = Mathf.Abs(deltaScale);
                deltaScale = Mathf.Clamp(deltaScale, deltaScaleMin, deltaScaleMax);

                // Find new hand positions. Unlike TwoPointNonUniformScale, this isn't a
                // simple scale of the positions. The invariant is that each hand is
                // a constant distance from the left/right end of the object.
                //
                // The easiest way of doing this is computing the change in position of
                // the left/right object endpoints and applying that to the left/right hand.
                // Since the object is assumed to be symmetric about the object's origin,
                // the left and right object endpoints move the same amount of deltaSize/2
                float   deltaSize = sizeAlongAxis * (deltaScale - 1);
                Vector3 offset    = vScaleAxis0 * deltaSize;
                // The t values of -.5f and .5f reflect the symmetry of the object;
                // if it were asymmetric they would be calculated.
                gripL0.translation += -.5f * offset;
                gripR0.translation += .5f * offset;
            }

            // Reuse TwoPoint to compute T and R.
            return(TwoPointObjectTransformationNoScale(
                       gripL0, gripR0, gripL1, gripR1, obj0,
                       shrinkageSideIsLeft ? 0f : 1f));
        }
Пример #15
0
        // Construct transform obj1 such that:
        // - inv(obj0) * L0.pos == inv(obj1) * L1.pos
        // - inv(obj0) * R0.pos == inv(obj1) * L1.pos
        //
        // In other words, the left and right grip points on the old object
        // are the same as the left and right grip points on the new object.
        // (Note that the optional constraints may then change the result.)
        //
        // Note that if abs(R0-L0) != abs(R1-L1), then a scaling is necessary.
        // This methods applies scale about the passed axis only.
        //
        // Given 2 position deltas, there are 6 DOFs available:
        //  = 3DOF (movement of average position)
        //  + 2DOF (change of direction of vector between L and R)
        //  + 1DOF (scaling, change of length of LR projected onto the scale axis)
        //
        // We need one more DOF to fully specify the rotation. We can get this
        // from L and R's rotations about the L-R vector (either old or
        // new, doesn't really matter).
        //
        // Pass:
        //   scaleAxis -
        //     Must be unit-length. Scaling is applied along this axis only.
        //   gripL0, L1, R0, R1 -
        //     The left and right grip points, in their old (0) and new (1) positions.
        //     The scale portion of the TrTransform is ignored.
        //   obj0 -
        //     Transform of the object being manipulated.
        //   out deltaScale -
        //     Returns the difference in scale along the given axis.
        //   finalScaleMin -
        //     Ignore scaling when gripL0 and gripR0 are closer together along scaleAxis than this.
        //     TODO: rename to finalScaleMin is a bad name for this parameter.
        //   deltaScale{Min,Max} -
        //     Constrains the range of deltaScale.
        //     Negative means do not constrain that endpoint.
        //     Note that it is very easy for zero deltaScale to be returned
        //
        // Returns:
        //   result.position, result.rotation -
        //                  new position and rotation
        //   result.scale - undefined; do not use
        //   deltaScale   - change in scale along vScaleAxis0, as a multiplier
        public static TrTransform TwoPointObjectTransformationNonUniformScale(
            Vector3 vScaleAxis0,
            TrTransform gripL0, TrTransform gripR0, // prev
            TrTransform gripL1, TrTransform gripR1, // next
            TrTransform obj0,
            out float deltaScale,
            float finalScaleMin = -1.0f,
            float deltaScaleMin = -1.0f, float deltaScaleMax = -1.0f
            )
        {
            // The vectors from left -> right hand can be decomposed into
            // "along scale axis" and "across scale axis".
            // The length of "along scale axis" varies; the change is the amount of scaling.
            // The length of "across scale axis" remains constant, because it doesn't scale.

            float   constraintPositionT = 0.5f;
            float   along0;
            Vector3 vAcross;
            Vector3 vLR0;
            {
                vLR0   = (gripR0.translation - gripL0.translation);
                along0 = Vector3.Dot(vLR0, vScaleAxis0);

                // Prevent negative scale by ensuring Sign(along0) == Sign(along1).
                // This causes the scale to turn into rotation. Note that Sign(along1) always == 1.
                // It also simplifies the following along0 checks.
                float sign = Mathf.Sign(along0);
                along0      *= sign;
                vScaleAxis0 *= sign;

                vAcross = vLR0 - along0 * vScaleAxis0;

                // Ignore scaling along the axis when the controllers are too close together.
                // Also ignore in unstable cases.
                if (along0 < finalScaleMin || along0 < 1e-5f)
                {
                    deltaScale = 1;
                    return(TwoPointObjectTransformationNoScale(gripL0, gripR0, gripL1, gripR1, obj0, constraintPositionT));
                }
            }

            float   along1;
            Vector3 vLR1; {
                // Calculate |vAlong1| using the identity:
                // |vLR|^2 = |vAlong|^2 + |vAcross|^2
                vLR1 = (gripR1.translation - gripL1.translation);
                float along1Squared = vLR1.sqrMagnitude - vAcross.sqrMagnitude;
                if (along1Squared < 0)
                {
                    // Impossible to satisfy the constraint. We can refuse to scale (along1 = along0),
                    // or clamp the scale to the nearest valid value (along1 = 0).
                    along1 = 0;
                }
                else
                {
                    along1 = Mathf.Sqrt(along1Squared);
                }
            }

            deltaScale = along1 / along0;

            // For min scale clamping, constrain to the object center if it's between the controllers or to
            // the controller closest to the object center.
            if (deltaScaleMin > 0 && deltaScale < deltaScaleMin)
            {
                deltaScale = deltaScaleMin;
                // Calculate a ratio such that (ratio * gripR0 + (1 - ratio) * gripL0) lies on the plane that
                // is perpendicular to the non-uniform scale axis and goes through the object center. This is
                // used as the pivot for the transformation.
                float factorL   = Vector3.Dot(vScaleAxis0, gripL0.translation);
                float factorR   = Vector3.Dot(vScaleAxis0, gripR0.translation);
                float factorObj = Vector3.Dot(vScaleAxis0, obj0.translation);
                constraintPositionT = (factorObj - factorL) / (factorR - factorL);
                constraintPositionT = Mathf.Clamp01(constraintPositionT);
            }

            // For max scale clamping, constrain to the position between the two controllers.
            if (deltaScaleMax > 0 && deltaScale > deltaScaleMax)
            {
                deltaScale          = deltaScaleMax;
                constraintPositionT = 0.5f;
            }

            // TwoPointNoScale can be used to compute T and R since those calculations are independent of S.
            // In the case where deltaScale == along1 / along0 (ie., where the scale has not been clamped),
            // using ScalePosition here will ensure |LR0| = |LR1|, so TwoPointNoScale can be used safely.
            // When scale is clamped, ScalePosition will compensate the initial positions as far as they
            // will go until the clamp and then TwoPointNoScale will compute T and R while keeping the
            // passed in constraint position fixed.
            gripL0.translation = ScalePosition(
                gripL0.translation, deltaScale, obj0.translation, vScaleAxis0);
            gripR0.translation = ScalePosition(
                gripR0.translation, deltaScale, obj0.translation, vScaleAxis0);

            return(TwoPointObjectTransformationNoScale(gripL0, gripR0, gripL1, gripR1, obj0, constraintPositionT));
        }
Пример #16
0
        // Continue drawing stroke for this frame.
        public void Update()
        {
            if (m_isDone)
            {
                return;
            }

            var rPointerScript = m_pointer;
            var rPointerObject = m_pointer.gameObject;

            bool needMeshUpdate    = false;
            bool needPointerUpdate = false;
            bool strokeFinished    = false;
            var  lastCp            = new PointerManager.ControlPoint();

            OverlayManager.m_Instance.UpdateProgress(SketchMemoryScript.m_Instance.GetDrawnPercent());

            RdpStrokeSimplifier simplifier = QualityControls.m_Instance.StrokeSimplifier;

            if (simplifier.Level > 0.0f)
            {
                simplifier.CalculatePointsToDrop(m_stroke, m_pointer.CurrentBrushScript);
            }

            while (true)
            {
                if (m_nextControlPoint >= m_stroke.m_ControlPoints.Length)
                {
                    needMeshUpdate = true; // Is this really necessary?
                    strokeFinished = true;
                    break;
                }
                var cp = m_stroke.m_ControlPoints[m_nextControlPoint];
                if (!IsControlPointReady(cp))
                {
                    break;
                }

                if (!m_stroke.m_ControlPointsToDrop[m_nextControlPoint])
                {
                    rPointerScript.UpdateLineFromControlPoint(cp);
                    needMeshUpdate    = true;
                    lastCp            = cp;
                    needPointerUpdate = true;
                }
                ++m_nextControlPoint;
            }

            if (needMeshUpdate)
            {
                rPointerScript.UpdateLineVisuals();
            }
            if (needPointerUpdate)
            {
                // This is only really done for visual reasons
                var xf_GS = Coords.CanvasPose * TrTransform.TR(lastCp.m_Pos, lastCp.m_Orient);
                xf_GS.scale = rPointerObject.transform.GetUniformScale();
                Coords.AsGlobal[rPointerObject.transform] = xf_GS;
                rPointerScript.SetPressure(lastCp.m_Pressure);
            }

            if (strokeFinished)
            {
                rPointerScript.EndLineFromMemory(m_stroke);
                m_isDone = true;
            }
        }
Пример #17
0
        /// The command takes additional ownership over the objects passed, copying its
        /// objects into a new array that is never mutated.
        ///
        /// Initial pose is the pose of the selection from before the selection/deselection
        /// takes place. It's needed because if the action is to deselect the very last objects,
        /// the SelectionManager will automatically reset the selection transform to identity. And
        /// then if we want to undo that selection, we need to restore its initial transform so that
        /// the selection widget is appropriately rotated.
        ///
        /// Preserving the orientation of the selection widget is important for two reasons:
        /// 1: Aesthetics. If a user deselects a rotated selection then immediately undoes that
        ///    deselection, it would be jarring if the selection bounds rotated.
        /// 2: To preserve undoing transformations of the selection widget. When the user grabs and moves
        ///    the selection, the selection widget maintains its own movewidget commands on the stack, so
        ///    it'd expect the widget not to have been moved by an outside party between redoing a move
        ///    and then undoing it.
        public SelectCommand(
            ICollection <Stroke> strokes,
            ICollection <GrabWidget> widgets,
            TrTransform initialTransform,
            bool deselect        = false, bool initial = false, bool checkForClearedSelection = false,
            bool isGrabbingGroup = false, bool isEndGrabbingGroup = false,
            BaseCommand parent   = null)
            : base(parent)
        {
            var selectedGroups = new HashSet <SketchGroupTag>();

            var strokesNotGrouped = new HashSet <Stroke>();

            if (strokes != null)
            {
                // Get strokes that are not grouped and groups among selected strokes.
                foreach (var stroke in strokes)
                {
                    if (stroke.Group == SketchGroupTag.None)
                    {
                        strokesNotGrouped.Add(stroke);
                    }
                    else
                    {
                        selectedGroups.Add(stroke.Group);
                    }
                }
            }

            var widgetsNotGrouped = new HashSet <GrabWidget>();

            if (widgets != null)
            {
                // Get widgets that are not grouped and groups among selected widgets.
                foreach (var widget in widgets)
                {
                    if (widget.Group == SketchGroupTag.None)
                    {
                        widgetsNotGrouped.Add(widget);
                    }
                    else
                    {
                        selectedGroups.Add(widget.Group);
                    }
                }
            }

            // Get the grouped strokes.
            var strokesGrouped = new HashSet <Stroke>();

            foreach (var group in selectedGroups)
            {
                strokesGrouped.UnionWith(SelectionManager.m_Instance.StrokesInGroup(group));
            }

            // Get the grouped widgets.
            var widgetsGrouped = new HashSet <GrabWidget>();

            foreach (var group in selectedGroups)
            {
                widgetsGrouped.UnionWith(SelectionManager.m_Instance.WidgetsInGroup(group));
            }

            m_Strokes = new List <Stroke>();
            m_Strokes.AddRange(strokesGrouped);
            m_Strokes.AddRange(strokesNotGrouped);

            m_Widgets = new List <GrabWidget>();
            m_Widgets.AddRange(widgetsGrouped);
            m_Widgets.AddRange(widgetsNotGrouped);

            m_InitialTransform         = initialTransform;
            m_Deselect                 = deselect;
            m_Initial                  = initial;
            m_CheckForClearedSelection = checkForClearedSelection;
            m_IsGrabbingGroup          = isGrabbingGroup;
            m_IsEndGrabbingGroup       = isEndGrabbingGroup;
        }
Пример #18
0
 void OnPoseChanged(TrTransform prev, TrTransform current) {
   m_CameraComponent.nearClipPlane = m_CameraClipPlanesBase.x * current.scale;
   m_CameraComponent.farClipPlane = m_CameraClipPlanesBase.y * current.scale;
 }
Пример #19
0
        // -------------------------------------------------------------------------------------------- //
        // Tracking Methods
        // -------------------------------------------------------------------------------------------- //

        /// Clears the callbacks that get called when a new pose is received. The callbacks are saved
        /// So that they can be restored later with RestorePoseTracking.
        public void DisablePoseTracking()
        {
            m_TrackingBackupXf        = TrTransform.FromTransform(GetVrCamera().transform);
            m_OldOnPoseApplied        = NewControllerPosesApplied.GetInvocationList().Cast <Action>().ToArray();
            NewControllerPosesApplied = null;
        }
Пример #20
0
 private void OnScenePoseChanged(TrTransform prev, TrTransform current)
 {
     UpdateBoxCollider();
 }
Пример #21
0
 protected override void InitBrush(BrushDescriptor desc, TrTransform localPointerXf)
 {
     base.InitBrush(desc, localPointerXf);
     CommonInit(localPointerXf);
 }
Пример #22
0
        void ApplyLazyInput(ref Vector3 pos, ref Quaternion rot)
        {
            if (!m_PaintingActive || !m_LazyInputActive || m_GridSnapActive)
            {
                if (m_GridSnapActive)
                {
                    ApplyGridSnap(ref pos, ref rot);
                }

                m_btCursorPos   = pos;
                m_btCursorRot   = rot;
                m_lazyInputRate = 0;

                EndLazyInputVisuals();
                return;
            }

            UpdateLazyInputRate();

            //Vector3 beeline = pos - m_btCursorPos;
            //
            //// Vector3 beelineDelta = Vector3.Lerp(Vector3.zero, beeline, m_lazyInputRate);
            //
            //Vector3 oldCursorNormal = m_btCursorRot * Vector3.forward;
            //Vector3 newCursorNormal = rot * Vector3.forward;
            //
            //Vector3 forwardDelta = Vector3.ProjectOnPlane(beeline, oldCursorNormal);
            //Vector3 midPointDelta = Vector3.Project(Vector3.ProjectOnPlane(beeline, newCursorNormal), forwardDelta.normalized);
            //
            //float midPointLerp = Mathf.InverseLerp(0, beeline.magnitude, Vector3.Project(midPointDelta, beeline.normalized).magnitude);
            //
            //m_btCursorRot = Quaternion.Slerp(m_btCursorRot, rot, Mathf.Lerp(midPointLerp, 1, Mathf.Abs(Vector3.Dot(beeline.normalized, newCursorNormal))) * m_lazyInputRate);
            //
            //Vector3 posDelta = Vector3.Lerp(Vector3.zero, Vector3.Lerp(midPointDelta, beeline, midPointLerp), m_lazyInputRate);
            //m_btCursorPos = m_btCursorPos + posDelta;
            //
            //// if (beelineDelta.magnitude > 0) {
            ////   m_btCursorPos = m_btCursorPos + beelineDelta;
            ////
            ////   m_btCursorRot = Quaternion.Slerp(m_btCursorRot, rot, m_lazyInputRate);
            //// }


            TrTransform result = LazyLerp(TrTransform.TRS(m_btCursorPos, m_btCursorRot, PointerManager.m_Instance.MainPointer.BrushSizeAbsolute), TrTransform.TRS(pos, rot, PointerManager.m_Instance.MainPointer.BrushSizeAbsolute), m_lazyInputRate, m_LazyInputTangentMode);

            m_btCursorPos = result.translation;
            m_btCursorRot = result.rotation;

            pos = m_btCursorPos;
            rot = m_btCursorRot;

            UpdateLazyInputVisuals();
        }
Пример #23
0
        //
        // GeometryBrush API
        //

        protected override void InitBrush(BrushDescriptor desc,
                                          TrTransform localPointerXf)
        {
            base.InitBrush(desc, localPointerXf);
            m_geometry.Layout = GetVertexLayout(desc);
        }
Пример #24
0
 override protected void OnButtonPressed()
 {
     if (WidgetManager.m_Instance.StencilsDisabled)
     {
         WidgetManager.m_Instance.StencilsDisabled = false;
     }
     SketchMemoryScript.m_Instance.PerformAndRecordCommand(new CreateWidgetCommand(
                                                               WidgetManager.m_Instance.GetStencilPrefab(m_Type), TrTransform.FromTransform(transform)));
     SketchControlsScript.m_Instance.EatGazeObjectInput();
     SelectionManager.m_Instance.RemoveFromSelection(false);
 }
Пример #25
0
 private void OnSelectionTransformed(TrTransform xf_SS)
 {
     SelectionTransform = xf_SS;
 }
Пример #26
0
        private TrTransform UsdXformToWorldSpaceXform(USD.NET.Unity.XformSample usdXform)
        {
            TrTransform xf_CS = TrTransform.FromMatrix4x4(usdXform.transform);

            return(TrTransform.FromTransform(App.Scene.ActiveCanvas.transform) * xf_CS);
        }
Пример #27
0
 public void ResetInitialTransform()
 {
     m_InitialTransform = TrTransform.identity;
 }
Пример #28
0
        protected override void MaybeCreateChildrenImpl()
        {
            // TODO: when too many children, starve an old one in order to create another.

            int kBranchCount = 12;
            int kFrondCount  = 16;

            if (m_recursionLevel == 0)
            {
                // Trunk
                if (m_children.Count == 0)
                {
                    InitializeAndAddChild(new PbChildIdentityXf(), m_trunkBrush, m_trunkColor);
                }
                if (DistanceSinceLastKnotBasedChild() > m_branchFrequency &&
                    m_children.Count < kBranchCount + 1)
                {
                    int salt = m_children.Count;
                    // Children 1 - 13 are the branches; early ones grow faster.
                    float       growthPercent = (kBranchCount + 1 - (float)m_children.Count) / kBranchCount;
                    TrTransform offset        =
                        // Branches don't extend as quickly as the trunk
                        TrTransform.S(m_branchScale * growthPercent) *
                        // Randomly place around the tree
                        TrTransform.R(m_rng.InRange(salt, 0f, 360f), Vector3.forward) *
                        // Angle the branches backwards (away from the stroke tip)
                        TrTransform.R(120, Vector3.right);
                    InitializeAndAddChild(
                        new PbChildWithOffset(m_knots.Count - 1, AttachFrame.LineTangent, offset, 0),
                        m_Desc, // Recurse with same brush
                        Color.white, m_branchRelativeSize);
                }
            }
            else if (m_recursionLevel == 1)
            {
                // Branch
                if (m_children.Count == 0)
                {
                    InitializeAndAddChild(new PbChildIdentityXf(), m_branchBrush, m_branchColor);
                }
                // TODO: would like this frequency to be higher for tinier branches
                if (DistanceSinceLastKnotBasedChild() > m_frondFrequency &&
                    m_children.Count < kFrondCount + 1)
                {
                    float growthPercent = 1; // (kFrondCount + 1 - (float)m_children.Count) / kFrondCount;
                    for (int deg = -30; deg <= 30; deg += 60)
                    {
                        TrTransform offset =
                            // Fronds don't grow as quickly as the branch
                            TrTransform.S(m_frondScale * growthPercent) *
                            TrTransform.R(deg, Vector3.up);
                        InitializeAndAddChild(
                            new PbChildWithOffset(m_knots.Count - 1, AttachFrame.LineTangent, offset, 0),
                            m_frondBrush, m_frondColor, m_frondRelativeSize);
                        TrTransform decoOffset = TrTransform.T(m_decoOffset);
                        InitializeAndAddChild(
                            new PbChildWithOffset(-1, AttachFrame.LineTangent, decoOffset, m_decoTwist),
                            m_decoBrush, Color.white, m_frondRelativeSize);
                    }
                }
            }
        }
Пример #29
0
 private void OnScenePoseChanged(TrTransform prev, TrTransform current)
 {
     m_ContainerBloat *= prev.scale / current.scale;
     UpdateScale();
 }
Пример #30
0
        // Constructs an updated transform obj1 such that the object-space
        // positions of the left and right grip are invariant. More generally,
        // all points on the line L->R are invariant. Precisely:
        //
        // - inv(obj0) * L0.pos == inv(obj1) * L1.pos
        // - inv(obj0) * R0.pos == inv(obj1) * L1.pos
        //
        // If abs(R0-L0) != abs(R1-L1), then a scaling is necessary.
        // This method chooses to apply a uniform scale.
        //
        // If scale bounds kick in, only a single point on the L->R line can
        // be made invariant; see bUseLeftAsPivot for how this is chosen.
        //
        // Given 2 position deltas, there are 6 DOFs available:
        //  = 3DOF (movement of average position)
        //  + 2DOF (change of direction of vector between L and R)
        //  + 1DOF (scaling, change of length of vector between L and R)
        //
        // One more DOF is needed to fully specify the rotation. This method
        // chooses to get it from L and R's rotations about the L-R vector.
        //
        // Pass:
        //   gripL0, L1, R0, R1 -
        //     The left and right grip points, in their old (0) and new (1) positions.
        //     The scale portion of the TrTransform is ignored.
        //   obj0 -
        //     Transform of the object being manipulated.
        //   deltaScale{Min,Max} -
        //     Constrains the range of result.scale.
        //     Negative means do not constrain that endpoint.
        //   rotationAxisConstraint -
        //     Constrains the value of result.rotation. If passed, the delta rotation
        //     from obj0 -> result will only be about this axis.
        //   bUseLeftAsPivot -
        //     Controls the invariant point if scale constraints are applied.
        //     If false, uses the midpoint between L and R.
        //     If true, uses the point L.
        //
        // Returns:
        //   New position, rotation, and scale
        static public TrTransform TwoPointObjectTransformation(
            TrTransform gripL0, TrTransform gripR0, // prev
            TrTransform gripL1, TrTransform gripR1, // next
            TrTransform obj0,
            float deltaScaleMin            = -1.0f, float deltaScaleMax = -1.0f,
            Vector3 rotationAxisConstraint = default(Vector3),
            bool bUseLeftAsPivot           = false)
        {
            // Vectors from left-hand to right-hand
            Vector3 vLR0 = (gripR0.translation - gripL0.translation);
            Vector3 vLR1 = (gripR1.translation - gripL1.translation);

            // World-space position whose object-space position is used to constrain obj1
            //    inv(obj0) * vInvariant0 = inv(obj1) * vInvariant1
            Vector3 vInvariant0, vInvariant1; {
                // Use left grip or average of grips as pivot point. Maybe switch the
                // bool to be a parametric t instead, so if caller wants to use right
                // grip as pivot they don't need to swap arguments?
                float t = bUseLeftAsPivot ? 0f : 0.5f;
                vInvariant0 = Vector3.Lerp(gripL0.translation, gripR0.translation, t);
                vInvariant1 = Vector3.Lerp(gripL1.translation, gripR1.translation, t);
            }

            // Strategy:
            // 1. Move invariant point to the correct spot, with a translation.
            // 2. Rotate about that point.
            // 3. Uniform scale about that point.
            // Items 2 and 3 can happen in the same TrTransform, since rotation
            // and uniform scale commute as long as they use the same pivot.

            TrTransform xfDelta1 = TrTransform.T(vInvariant1 - vInvariant0);

            TrTransform xfDelta23; {
                // calculate worldspace scale; will adjust center-of-scale later
                float dist0      = vLR0.magnitude;
                float dist1      = vLR1.magnitude;
                float deltaScale = (dist0 == 0) ? 1 : dist1 / dist0;

                // Clamp scale if requested.
                if (deltaScaleMin >= 0)
                {
                    deltaScale = Mathf.Max(deltaScale, deltaScaleMin);
                }
                if (deltaScaleMax >= 0)
                {
                    deltaScale = Mathf.Min(deltaScale, deltaScaleMax);
                }

                // This gets the left-right axis pointing in the correct direction
                Quaternion qSwing0To1 = Quaternion.FromToRotation(vLR0, vLR1);
                // This applies some twist about that left-right axis. The choice of constraint axis
                // (vLR0 vs vLR1) depends on whether qTwist is right- or left-multiplied vs qReach.
                Quaternion qTwistAbout0 = Quaternion.Slerp(
                    ConstrainRotationDelta(gripL0.rotation, gripL1.rotation, vLR0),
                    ConstrainRotationDelta(gripR0.rotation, gripR1.rotation, vLR0),
                    0.5f);
                Quaternion qDelta = qSwing0To1 * qTwistAbout0;
                // Constrain the rotation if requested.
                if (rotationAxisConstraint != default(Vector3))
                {
                    qDelta = ConstrainRotationDelta(Quaternion.identity, qDelta, rotationAxisConstraint);
                }

                xfDelta23 = TrTransform
                            .TRS(Vector3.zero, qDelta, deltaScale)
                            .TransformBy(TrTransform.T(vInvariant1));
            }

            return(xfDelta23 * xfDelta1 * obj0);
        }