コード例 #1
0
ファイル: ParentBrush.cs プロジェクト: mikeage/open-brush
            protected override TrTransform CalculateChildXf(List <PbKnot> parentKnots)
            {
                TrTransform actionInCanvasSpace;
                {
                    PbKnot      knot            = GetAttachKnot(parentKnots);
                    float       rotationDegrees = knot.m_distance * App.UNITS_TO_METERS * m_twist;
                    TrTransform offset          = m_offset;

                    // It's cleaner to tack a TrTransform.S(size) onto the action, but that
                    // would modify .scale, which is currently interpreted as "pointer size"
                    // (affecting control point density) and which is also assumed by most
                    // brushes to be constant.
                    if (m_pressureAffectsOffset)
                    {
                        offset.translation *= knot.m_pressuredSize;
                    }
                    else
                    {
                        offset.translation *= m_brush.BaseSize_LS;
                    }

                    TrTransform action =
                        TrTransform.R(Quaternion.AngleAxis(rotationDegrees, Vector3.forward))
                        * offset;
                    actionInCanvasSpace = action.TransformBy(knot.GetFrame(m_frame));
                }

                var cur = parentKnots[parentKnots.Count - 1];

                return(actionInCanvasSpace * cur.m_pointer);
            }
コード例 #2
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);
        }
コード例 #3
0
        public void TestTransformByForBasisChange()
        {
            // This is more a test of TrTransform.TransformBy than anything else
            var zFromU = VrAssetService.kPolyFromUnity;

            // This rotates Unity-forward to Unity-right
            TrTransform xfFwdToRt_U = TrTransform.R(Quaternion.AngleAxis(90, Vector3.up));

            AssertAlmostEqual(Vector3.right, xfFwdToRt_U * Vector3.forward);
            AssertAlmostEqual(Vector3.up, xfFwdToRt_U * Vector3.up);

            // This should rotate Poly-forward to Poly-right (to test)
            TrTransform xfFwdToRt_Z = xfFwdToRt_U.TransformBy(zFromU);

            AssertAlmostEqual(kZRight, xfFwdToRt_Z * kZForward);
            AssertAlmostEqual(kZUp, xfFwdToRt_Z * kZUp);
        }
コード例 #4
0
        protected override void MaybeCreateChildrenImpl()
        {
            // Only create children once
            if (m_children.Count > 1)
            {
                return;
            }

            BrushDescriptor childDesc = m_Desc;

            if (m_recursionLevel == 1)
            {
                childDesc = m_baseBrush;
            }

            // Since we're doing these color modifications, doing reflection or rotation first
            // changes the look.
            if (m_recursionLevel == 0)
            {
                // Reflection
                HSLColor reflectedColor = m_Color;
                reflectedColor.s += m_saturationDelta * ((reflectedColor.s > 0.5f) ? -1 : 1);

                InitializeAndAddChild(new PbChildIdentityXf(), childDesc, m_Color);
                InitializeAndAddChild(
                    new PbChildKnotBasedMirror(0, AttachFrame.Pointer, kReflectionPlane),
                    childDesc, (Color)reflectedColor);
            }
            else if (m_recursionLevel == 1)
            {
                // Rotation
                float rotationDeltaDegrees = 360f / m_numRotations;
                for (int i = 0; i < m_numRotations; ++i)
                {
                    int      iWrapped     = i + ((i * 2 > m_numRotations) ? -m_numRotations : 0);
                    HSLColor rotatedColor = m_Color;
                    float    angle        = iWrapped * rotationDeltaDegrees;
                    rotatedColor.HueDegrees += m_hueDeltaPct * angle;
                    TrTransform offset = TrTransform.R(angle, Vector3.forward);
                    InitializeAndAddChild(
                        new PbChildWithOffset(0, AttachFrame.Pointer, offset, 0),
                        childDesc, (Color)rotatedColor);
                }
            }
        }
コード例 #5
0
            protected override TrTransform CalculateChildXf(List <PbKnot> parentKnots)
            {
                PbKnot lastKnot = parentKnots[parentKnots.Count - 1];

                float distanceMeters = lastKnot.m_distance * App.UNITS_TO_METERS;
                float t = O.CyclesPerMeter * distanceMeters + (float)m_strand / O.NumStrands;
                // Our periodic function makes the plait look pretty square; maybe add
                // some rotation to break things up a bit?
                float rotations = (O.CyclesPerMeter * distanceMeters) * O.RotationsPerCycle;

                float       amplitude = lastKnot.m_pressuredSize / 2; // /2 because size is diameter, not radius.
                TrTransform action    =
                    TrTransform.R(rotations * 360, Vector3.forward) *
                    TrTransform.T(SomePeriodicFunction(t) * amplitude);

                TrTransform actionInCanvasSpace = action.TransformBy(lastKnot.GetFrame(AttachFrame.LineTangent));

                return(actionInCanvasSpace * lastKnot.m_pointer);
            }
コード例 #6
0
ファイル: TestMathUtils.cs プロジェクト: sw0817/open-brush
        public void TestMengerCurvatureNonDegenerate()
        {
            float kRadius    = 2.5f;
            float kInvRadius = 1 / kRadius;

            Vector3 radius = new Vector3(kRadius, 0, 0);
            Vector3 axis   = new Vector3(0, 1, 0); // should be perpendicular to radius

            TrTransform arbitrary = TrTransform.TR(
                new Vector3(5, 8, -10),
                Quaternion.AngleAxis(35, new Vector3(-1, 3, -5)));

            // Pick a bunch of triplets on a circle of radius r.
            // Points are chosen by selecting two arc angles a, b, and computing the third arc angle c.
            // Repetitions are avoided by choosing a, b, c such that a <= b <= c.
            // Degenerate cases are avoided by choosing a > 0 (implying a, b, c > 0).

            // If a > 120, one of b or c will always be smaller than a
            for (int a = 12; a <= 120; a += 24)
            {
                for (int b = a; /*b <= c*/; b += 24)
                {
                    int c = 360 - a - b;
                    if (!(b <= c))
                    {
                        break;
                    }
                    Vector3 va = TrTransform.R(0, axis) * radius;
                    Vector3 vb = TrTransform.R(a, axis) * radius;
                    Vector3 vc = TrTransform.R(a + b, axis) * radius;
                    AssertAlmostEqual(kInvRadius, MathUtils.MengerCurvature(va, vb, vc));

                    Vector3 va2 = arbitrary * va;
                    Vector3 vb2 = arbitrary * vb;
                    Vector3 vc2 = arbitrary * vc;
                    AssertAlmostEqual(kInvRadius, MathUtils.MengerCurvature(va2, vb2, vc2));
                }
            }
        }
コード例 #7
0
        /// Spawn a model.
        /// Precondition: Model must have m_Valid == true.
        protected void SpawnValidModel(Model model)
        {
            if (!model.m_Valid)
            {
                throw new InvalidOperationException("model must be valid");
            }
            // Button forward is into the panel, not out of the panel; so flip it around
            TrTransform xfSpawn = Coords.AsGlobal[transform]
                                  * TrTransform.R(Quaternion.AngleAxis(180, Vector3.up));
            CreateWidgetCommand createCommand = new CreateWidgetCommand(
                WidgetManager.m_Instance.ModelWidgetPrefab, xfSpawn, m_PreviewBaseRotation);

            SketchMemoryScript.m_Instance.PerformAndRecordCommand(createCommand);
            ModelWidget modelWidget = createCommand.Widget as ModelWidget;

            modelWidget.Model = model;
            modelWidget.Show(true);
            createCommand.SetWidgetCost(modelWidget.GetTiltMeterCost());

            WidgetManager.m_Instance.WidgetsDormant = false;
            SketchControlsScript.m_Instance.EatGazeObjectInput();
            SelectionManager.m_Instance.RemoveFromSelection(false);
        }
コード例 #8
0
ファイル: HolidayTree.cs プロジェクト: mikeage/open-brush
        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);
                    }
                }
            }
        }
コード例 #9
0
        protected override IEnumerable <ControlPoint> DoGetPoints(TrTransform finalTransform)
        {
            double t0 = m_initialTime;
            double t1 = App.Instance.CurrentSketchTime;

            Vector3 center  = m_initialTransform.translation;
            Vector3 nRadius = finalTransform.translation - center;
            float   fRadius = nRadius.magnitude;

            nRadius /= fRadius;

            // Degenerate circle -- turn it into a line
            if (fRadius < 1e-5f)
            {
                yield return(new ControlPoint
                {
                    m_Pos = m_initialTransform.translation,
                    m_Orient = m_initialTransform.rotation,
                    m_Pressure = 1f,
                    m_TimestampMs = (uint)(t0 * kSecondsToMs)
                });

                yield return(new ControlPoint
                {
                    m_Pos = finalTransform.translation,
                    m_Orient = finalTransform.rotation,
                    m_Pressure = 1f,
                    m_TimestampMs = (uint)(t1 * kSecondsToMs)
                });

                yield break;
            }

            // Tangent must be perpendicular to nRadius

            var thisState = new ComputeTangentState
            {
                nRadius   = nRadius,
                rotation  = finalTransform.rotation,
                preferred = m_vPreferredTangent
            };
            Vector3 nTangent = ComputeTangent(thisState);

            m_vPreferredTangent = nTangent;

#if DEBUG_TANGENT
            if (m_oldState != null)
            {
                Vector3 nOldTangent = ComputeTangent(m_oldState.Value);
                if (fRadius > .5f && Vector3.Dot(nOldTangent, nTangent) < .966f)
                {
                    int nn = 20;
                    for (int i = 0; i < nn; ++i)
                    {
                        Vector3 v0 = ComputeTangent(thisState);
                        Vector3 v1 = ComputeTangent(m_oldState.Value);
                    }
                }
            }
            m_oldState = thisState;
#endif


            // Axis is perpendicular to tangent and radius
            // TODO: experiment with removing this restriction?
            Vector3 nAxis = Vector3.Cross(nTangent, nRadius).normalized;

            TrTransform xf0 = finalTransform;

            // TODO: adjust control point density

            int n = 30; // number of points; must be >= 2
            for (int i = 0; i <= n; ++i)
            {
                float t = (float)i / n;

                Quaternion  rot   = Quaternion.AngleAxis(360 * t, nAxis);
                TrTransform delta = TrTransform.R(rot).TransformBy(TrTransform.T(center));
                TrTransform xf    = delta * xf0;

                yield return(new ControlPoint
                {
                    m_Pos = xf.translation,
                    m_Orient = xf.rotation,
                    m_Pressure = 1f,
                    m_TimestampMs = (uint)(Mathf.Lerp((float)t0, (float)t1, t) * 1000)
                });
            }

#if DEBUG_TANGENT
            var start = finalTransform.translation;
            foreach (var val in DrawLine(start, nTangent, 5))
            {
                yield return(val);
            }
            foreach (var val in DrawLine(start, nAxis, 7))
            {
                yield return(val);
            }
#endif
        }