コード例 #1
0
ファイル: TestJsonGlue.cs プロジェクト: pixelfelt/silk-brush
        public void TestReadTrTransform()
        {
            var xf = Deserialize <TrTransform>("[ [0,1,0], [0,0,0,1], 3]");

            Assert.AreEqual(xf, TrTransform.TRS(Vector3.up, Quaternion.identity, 3));
        }
コード例 #2
0
        /// Non-playback case:
        /// - Update the stroke based on the object's position.
        /// - Save off control points
        /// - Play audio.
        public void UpdateLineFromObject()
        {
            var xf_LS = GetTransformForLine(m_CurrentLine.transform, Coords.AsRoom[transform]);

            if (!PointerManager.m_Instance.IsMainPointerProcessingLine() && m_CurrentCreator != null)
            {
                var straightEdgeGuide = PointerManager.m_Instance.StraightEdgeGuide;

                if (straightEdgeGuide.SnapEnabled)
                {
                    // Snapping should be applied before symmetry, and lift is applied
                    // after symmetry, so redo both.

                    TrTransform xfMain_RS = Coords.AsRoom[PointerManager.m_Instance.MainPointer.transform];
                    xfMain_RS.translation = Coords.CanvasPose * straightEdgeGuide.GetTargetPos();
                    TrTransform xfSymmetry_RS = PointerManager.m_Instance.GetSymmetryTransformFor(
                        this, xfMain_RS);
                    xf_LS = GetTransformForLine(m_CurrentLine.transform, xfSymmetry_RS);
                }

                m_ControlPoints.Clear();
                m_ControlPoints.AddRange(m_CurrentCreator.GetPoints(xf_LS));
                float scale = xf_LS.scale;
                m_CurrentLine.ResetBrushForPreview(
                    TrTransform.TRS(m_ControlPoints[0].m_Pos, m_ControlPoints[0].m_Orient, scale));
                for (int i = 0; i < m_ControlPoints.Count; ++i)
                {
                    if (m_CurrentLine.IsOutOfVerts())
                    {
                        m_ControlPoints.RemoveRange(i, m_ControlPoints.Count - i);
                        break;
                    }
                    m_CurrentLine.UpdatePosition_LS(
                        TrTransform.TRS(m_ControlPoints[i].m_Pos, m_ControlPoints[i].m_Orient, scale),
                        m_ControlPoints[i].m_Pressure);
                }
                UpdateLineVisuals();
                return;
            }

            bool bQuadCreated = m_CurrentLine.UpdatePosition_LS(xf_LS, m_CurrentPressure);

            // TODO: let brush take care of storing control points, not us
            SetControlPoint(xf_LS, isKeeper: bQuadCreated);

            // TODO: Pointers should hold a reference to the stencil they're painting on.  This
            // is a hacky temporary check to ensure mirrored pointers don't add to the lift of
            // the active stencil.
            if (PointerManager.m_Instance.MainPointer == this)
            {
                // Increase stencil lift if we're painting on one.
                StencilWidget stencil = WidgetManager.m_Instance.ActiveStencil;
                if (stencil != null && m_CurrentCreator == null)
                {
                    float fPointerMovement_CS = GetMovementDelta() / Coords.CanvasPose.scale;
                    stencil.AdjustLift(fPointerMovement_CS);
                    m_LineLength_CS += fPointerMovement_CS;
                }
            }

            UpdateLineVisuals();

            /* Update desired brush audio
             * if (m_AudioSources.Length > 0) {
             * float fMovementSpeed = Vector3.Distance(m_PreviousPosition, transform.position) /
             *  Time.deltaTime;
             *
             * float fVelRangeRange = m_BrushAudioVolumeVelocityRange.y - m_BrushAudioVolumeVelocityRange.x;
             * float fVolumeRatio = Mathf.Clamp01((fMovementSpeed - m_BrushAudioVolumeVelocityRange.x) / fVelRangeRange);
             * m_AudioVolumeDesired = fVolumeRatio;
             *
             * float fPitchRangeRange = m_BrushAudioPitchVelocityRange.y - m_BrushAudioPitchVelocityRange.x;
             * float fPitchRatio = Mathf.Clamp01((fMovementSpeed - m_BrushAudioPitchVelocityRange.x) / fPitchRangeRange);
             * m_AudioPitchDesired = m_BrushAudioBasePitch + (fPitchRatio * m_BrushAudioMaxPitchShift);
             * } */
        }
コード例 #3
0
        private void ApplyRevolver(ref Vector3 pos, ref Quaternion rot)
        {
            if (!m_RevolverActive)
            {
                return;
            }

            Transform lAttachPoint = InputManager.m_Instance.GetWandControllerAttachPoint();
            Vector3   lPos         = lAttachPoint.position;

            Transform rAttachPoint = InputManager.m_Instance.GetBrushControllerAttachPoint();
            Vector3   rPos         = rAttachPoint.position;

            Vector3 guideDelta  = lPos - m_btCursorPos;
            Vector3 radialDelta = Vector3.ProjectOnPlane(rPos - m_btIntersectGoal, guideDelta.normalized);

            Quaternion radialLookRot = Quaternion.LookRotation(radialDelta.normalized, guideDelta);

            m_RevolverAngle = m_RevolverAngle + m_RevolverVelocity * 720 * Time.deltaTime;

            if (m_brushTrigger)
            {
                if (InputManager.m_Instance.IsBrushScrollActive())
                {
                    float turnRate = InputManager.m_Instance.GetBrushScrollAmount();
                    // apply a cubic exponential speed curve to make joystick handling easier
                    turnRate = Mathf.Sign(turnRate) * Mathf.Pow(Mathf.Abs(turnRate), 3);

                    m_RevolverVelocity = Mathf.MoveTowards(m_RevolverVelocity, -turnRate, Time.deltaTime * (turnRate == 0 ? 0.15f : 0.333f));
                }
            }
            else
            {
                Transform brushAttachTransform = InputManager.m_Instance.GetBrushControllerAttachPoint();

                Quaternion brushWorldRotation = brushAttachTransform.rotation * sm_OrientationAdjust;

                m_RevolverBrushRotationOffset = radialLookRot.TrueInverse() * brushWorldRotation;

                BrushGhostTilt = m_RevolverBrushRotationOffset;

                if (m_RevolverVelocity == 0)
                {
                    m_RevolverAngle = 0;
                }
            }


            Quaternion spindleRotation = Quaternion.AngleAxis(m_RevolverAngle, guideDelta.normalized);

            if (m_brushUndoButton)
            {
                SetRevolverRadius(m_brushTrigger ? m_lazyInputRate : 1);
            }

            Vector3    revolverOffset  = spindleRotation * radialDelta.normalized * m_RevolverRadius;
            Quaternion btCursorRotGoal = spindleRotation * radialLookRot * m_RevolverBrushRotationOffset;

            m_btCursorRot = btCursorRotGoal;

            pos = (m_brushTrigger && !m_LazyInputActive ? m_btCursorPos : m_btIntersectGoal) + revolverOffset;
            rot = m_btCursorRot;

            BrushGhostTransform = TrTransform.TRS(m_btIntersectGoal, Quaternion.LookRotation(radialDelta.normalized, guideDelta), PointerManager.m_Instance.MainPointer.BrushSizeAbsolute);
            BrushGhostLerpT     = (BrushGhostLerpT + Time.deltaTime * 0.25f) % 1f;
        }
コード例 #4
0
ファイル: MathUtils.cs プロジェクト: mikeage/open-brush
        // 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);
        }
コード例 #5
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();
        }