private void lineSketchObjectTest()
    {
        foreach (Transform controlPoint in controlPointParent.transform)
        {
            strokeSketchObject.AddControlPoint(controlPoint.position);
            strokeSketchObject2.AddControlPoint(controlPoint.position);
        }

        strokeSketchObject.SetStrokeCrossSection(CircularCrossSection.GenerateVertices(16), CircularCrossSection.GenerateVertices(16, 1f), .5f);
        //lineSketchObject.setLineDiameter(.7f);
        StartCoroutine(changeDiameter());

        //StartCoroutine(deactivateSelection(selection));
    }
    // Start is called before the first frame update
    void Start()
    {
        //Create a SketchWorld, many commands require a SketchWorld to be present
        SketchWorld = Instantiate(Defaults.SketchWorldPrefab).GetComponent <SketchWorld>();

        //Create a LineSketchObject
        LineSketchObject = Instantiate(Defaults.LineSketchObjectPrefab).GetComponent <LineSketchObject>();
        Invoker          = new CommandInvoker();
        Invoker.ExecuteCommand(new AddControlPointCommand(this.LineSketchObject, new Vector3(1, 2, 3)));
        Invoker.ExecuteCommand(new AddControlPointCommand(this.LineSketchObject, new Vector3(1, 4, 2)));
        Invoker.ExecuteCommand(new AddControlPointCommand(this.LineSketchObject, new Vector3(1, 5, 3)));
        Invoker.ExecuteCommand(new AddControlPointCommand(this.LineSketchObject, new Vector3(1, 5, 2)));
        Invoker.Undo();
        Invoker.Redo();

        LineBrush brush = this.LineSketchObject.GetBrush() as LineBrush;

        brush.CrossSectionVertices = CircularCrossSection.GenerateVertices(3);
        brush.CrossSectionNormals  = CircularCrossSection.GenerateVertices(3, 1);
        Invoker.ExecuteCommand(new SetBrushCommand(this.LineSketchObject, brush));
        //oder ohne Command
        //this.LineSketchObject.SetBrush(brush);
        //oder nur
        //this.LineSketchObject.SetLineCrossSection(...


        //Create a RibbonSketchObject
        RibbonSketchObject = Instantiate(Defaults.RibbonSketchObjectPrefab).GetComponent <RibbonSketchObject>();
        Invoker.ExecuteCommand(new AddPointAndRotationCommand(RibbonSketchObject, new Vector3(1, 1, 1), Quaternion.identity));
        Invoker.ExecuteCommand(new AddPointAndRotationCommand(RibbonSketchObject, new Vector3(1.5f, 1.1f, 1), Quaternion.Euler(0, 0, 0)));
        Invoker.ExecuteCommand(new AddPointAndRotationCommand(RibbonSketchObject, new Vector3(2f, 1.2f, 1), Quaternion.Euler(22, 0, 0)));
        Invoker.ExecuteCommand(new AddPointAndRotationCommand(RibbonSketchObject, new Vector3(2.5f, 1.3f, 1), Quaternion.Euler(45, 0, 0)));
        Invoker.ExecuteCommand(new AddPointAndRotationCommand(RibbonSketchObject, new Vector3(3f, 1.4f, 1), Quaternion.Euler(60, 0, 0)));

        //Create a PatchSketchObject
        PatchSketchObject       = Instantiate(Defaults.PatchSketchObjectPrefab).GetComponent <PatchSketchObject>();
        PatchSketchObject.Width = 3;
        Invoker.ExecuteCommand(new AddSegmentCommand(PatchSketchObject, new List <Vector3> {
            new Vector3(0, 0, 1), new Vector3(0, 1, 2), new Vector3(0, 0, 3)
        }));
        Invoker.ExecuteCommand(new AddSegmentCommand(PatchSketchObject, new List <Vector3> {
            new Vector3(1, 1, 1), new Vector3(1, 0, 2), new Vector3(1, 1, 3)
        }));
        Invoker.ExecuteCommand(new AddSegmentCommand(PatchSketchObject, new List <Vector3> {
            new Vector3(2, 0, 1), new Vector3(2, 1, 2), new Vector3(2, 0, 3)
        }));

        //Add the LineSketchObject to the SketchWorld
        Invoker.ExecuteCommand(new AddObjectToSketchWorldRootCommand(LineSketchObject, SketchWorld));
        //Create a SketchObjectGroup and add objects to it
        SketchObjectGroup = Instantiate(Defaults.SketchObjectGroupPrefab).GetComponent <SketchObjectGroup>();
        Invoker.ExecuteCommand(new AddToGroupCommand(SketchObjectGroup, RibbonSketchObject));
        Invoker.ExecuteCommand(new AddToGroupCommand(SketchObjectGroup, PatchSketchObject));
        //Add the SketchObjectGroup to the SketchWorld
        Invoker.ExecuteCommand(new AddObjectToSketchWorldRootCommand(SketchObjectGroup, SketchWorld));

        //Serialize the SketchWorld to a XML file
        SavePath = System.IO.Path.Combine(Application.dataPath, "YourSketch.xml");
        SketchWorld.SaveSketchWorld(SavePath);

        //Create another SketchWorld and load the serialized SketchWorld
        DeserializedSketchWorld = Instantiate(Defaults.SketchWorldPrefab).GetComponent <SketchWorld>();
        DeserializedSketchWorld.LoadSketchWorld(SavePath);
        DeserializedSketchWorld.transform.position += new Vector3(5, 0, 0);

        //Export the SketchWorld as an OBJ file
        //SketchWorld.ExportSketchWorldToDefaultPath();

        //Select the SketchObjectGroup
        SketchObjectSelection = Instantiate(Defaults.SketchObjectSelectionPrefab).GetComponent <SketchObjectSelection>();
        Invoker.ExecuteCommand(new AddToSelectionAndHighlightCommand(SketchObjectSelection, SketchObjectGroup));
        Invoker.ExecuteCommand(new ActivateSelectionCommand(SketchObjectSelection));
    }
Esempio n. 3
0
    private void SketchWorldSerializationTest()
    {
        strokeSketchObject.AddControlPoint(new Vector3(-2, 1, 0));
        strokeSketchObject.AddControlPoint(Vector3.one);
        strokeSketchObject.AddControlPoint(new Vector3(2, 2, 0));
        strokeSketchObject.AddControlPoint(new Vector3(2, 1, 0));
        //lineSketchObject.gameObject.GetComponent<MeshRenderer>().material = twoSidedMaterial;
        strokeSketchObject.gameObject.GetComponent <MeshRenderer>().material = ropeMaterial;
        strokeSketchObject.SetStrokeCrossSection(CircularCrossSection.GenerateVertices(4), CircularCrossSection.GenerateVertices(4, 1f), .4f);

        //lineSketchObject.setLineDiameter(.7f);
        //StartCoroutine(changeDiameter());

        strokeSketchObject2.AddControlPoint(new Vector3(1, 0, 0));
        strokeSketchObject2.AddControlPoint(new Vector3(2, 1, 1));
        strokeSketchObject2.AddControlPoint(new Vector3(3, 2, 0));
        strokeSketchObject2.AddControlPoint(new Vector3(4, 4, 4));
        strokeSketchObject2.DeleteControlPoint();
        strokeSketchObject2.DeleteControlPoint();
        strokeSketchObject2.DeleteControlPoint();
        strokeSketchObject2.DeleteControlPoint();
        strokeSketchObject2.DeleteControlPoint();
        strokeSketchObject2.AddControlPoint(new Vector3(1, 0, 0));
        strokeSketchObject2.AddControlPoint(new Vector3(2, 1, 1));
        strokeSketchObject2.AddControlPoint(new Vector3(3, 2, 0));
        strokeSketchObject2.AddControlPoint(new Vector3(4, 4, 4));
        strokeSketchObject2.GetComponent <MeshRenderer>().material.color      = Color.blue;
        strokeSketchObject2.gameObject.GetComponent <MeshRenderer>().material = ropeMaterial;

        patchSketchObject.transform.position += new Vector3(3, 0, 0);
        patchSketchObject.Width = 3;
        patchSketchObject.AddPatchSegment(new List <Vector3> {
            new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(2, 0, 0)
        });
        patchSketchObject.AddPatchSegment(new List <Vector3> {
            new Vector3(0, 0, 1), new Vector3(1, 2, 1), new Vector3(2, 0, 1)
        });
        patchSketchObject.AddPatchSegment(new List <Vector3> {
            new Vector3(0, 0, 2), new Vector3(1, 0, 2), new Vector3(2, 0, 2)
        });

        (List <Vector3> points, List <Quaternion> rotations) = RibbonTest.GetPointTransformation(ControlPointParent);
        ribbonSketchObject.SetControlPoints(points, rotations);
        SketchWorld.AddObject(ribbonSketchObject);

        //lineSketchObject2.minimumControlPointDistance = 2f;
        //lineSketchObject2.addControlPointContinuous(new Vector3(3, 1, 0));
        GameObject        groupGO = new GameObject("sketchObjectGroup", typeof(SketchObjectGroup));
        SketchObjectGroup group   = groupGO.GetComponent <SketchObjectGroup>();

        group.defaults = this.defaults;

        SketchWorld.AddObject(strokeSketchObject);
        group.AddToGroup(strokeSketchObject2);
        group.AddToGroup(patchSketchObject);
        group.transform.position += new Vector3(2.568f, 5.555f, 1.123f);
        SketchWorld.AddObject(group);

        string worldXmlPath = System.IO.Path.Combine(Application.dataPath, "SketchWorldTest.xml");

        SketchWorld.SaveSketchWorld(worldXmlPath);

        SketchWorld2.LoadSketchWorld(worldXmlPath);

        SerializeBrushCollection();

        //SketchObjectGroupData groupData = group.GetData();
        //string xmlFilePath = Serializer.WriteTestXmlFile<SketchObjectGroupData>(groupData);
        //Serializer.DeserializeFromXmlFile<SketchObjectGroupData>(out SketchObjectGroupData readGrouptData, xmlFilePath);
        //Debug.Log(readGrouptData.SketchObjects[0].GetType());

        //SketchObjectGroup deserGroup = Instantiate(defaults.SketchObjectGroupPrefab).GetComponent<SketchObjectGroup>();
        //deserGroup.ApplyData(readGrouptData);

        //deserGroup.transform.position += new Vector3(3, 0, 0);
    }
Esempio n. 4
0
        public static void FillPolyMesh(this IPositionSpline spline,
                                        PolyMesh polyMesh,
                                        Matrix4x4?applyTransform = null,
                                        float?startT             = null, float?endT = null,
                                        int?numSegments          = null,
                                        float[] radii            = null,
                                        float?radius             = null,
                                        bool drawDebug           = false)
        {
            float minT, maxT;
            int   effNumSegments;
            //bool useRadiusArr = false;
            //float[] effRadii;
            float     effRadius;
            bool      useTransform;
            Matrix4x4 transform;

            RuntimeGizmos.RuntimeGizmoDrawer drawer = null;
            if (drawDebug)
            {
                RuntimeGizmos.RuntimeGizmoManager.TryGetGizmoDrawer(out drawer);
            }

            // Assign parameters based on optional inputs
            {
                minT = spline.minT;
                if (startT.HasValue)
                {
                    minT = startT.Value;
                }

                maxT = spline.maxT;
                if (endT.HasValue)
                {
                    maxT = endT.Value;
                }

                effNumSegments = 32;
                if (numSegments.HasValue)
                {
                    effNumSegments = numSegments.Value;
                    effNumSegments = Mathf.Max(1, effNumSegments);
                }

                //useRadiusArr = false;
                effRadius = 0.02f;
                if (radius.HasValue)
                {
                    effRadius = radius.Value;
                }

                //effRadii = null;
                //if (radii != null) {
                //  useRadiusArr = true;
                //  effRadii = radii;
                //}

                useTransform = false;
                transform    = Matrix4x4.identity;
                if (applyTransform.HasValue)
                {
                    useTransform = true;
                    transform    = applyTransform.Value;
                }
            }

            // Multiple passes through the spline data will construct all the positions and
            // orientations we need to build the mesh.
            polyMesh.Clear();
            var     crossSection = new CircularCrossSection(effRadius, 16);
            float   tStep        = (maxT - minT) / effNumSegments;
            Vector3 position     = Vector3.zero;
            Vector3 dPosition    = Vector3.zero;
            Vector3?tangent      = null;

            var positions = Pool <List <Vector3> > .Spawn();

            positions.Clear();
            var normals = Pool <List <Vector3> > .Spawn(); // to start, normals contain velocities,

            normals.Clear();                               // but zero velocities are filtered out.
            var binormals = Pool <List <Vector3> > .Spawn();

            binormals.Clear();
            var crossSection0Positions = Pool <List <Vector3> > .Spawn();

            crossSection0Positions.Clear();
            var crossSection1Positions = Pool <List <Vector3> > .Spawn();

            crossSection1Positions.Clear();
            try {
                // Construct a rough list of positions and normals for each cross section. Some
                // of the normals may be zero, so we'll have to fix those.
                for (int i = 0; i <= effNumSegments; i++)
                {
                    var t = minT + i * tStep;

                    spline.ValueAndDerivativeAt(t, out position, out dPosition);

                    if (useTransform)
                    {
                        positions.Add(transform.MultiplyPoint3x4(position));
                        normals.Add(transform.MultiplyVector(dPosition).normalized);
                    }
                    else
                    {
                        positions.Add(position);
                        normals.Add(dPosition.normalized);
                    }

                    if (!tangent.HasValue && dPosition.sqrMagnitude > 0.001f * 0.001f)
                    {
                        tangent = (transform * dPosition.WithW(1)).ToVector3().normalized.Perpendicular();
                    }
                }

                // In case we never got a non-zero velocity, try to construct a tangent based on
                // delta positions.
                if (!tangent.HasValue)
                {
                    if (positions[0] == positions[1])
                    {
                        // No spline mesh possible; there's no non-zero length segment.
                        return;
                    }
                    else
                    {
                        var delta = positions[1] - positions[0];

                        // Very specific case: Two points, each with zero velocity, use delta for
                        // normals
                        if (positions.Count == 2)
                        {
                            normals[0] = delta; normals[1] = delta;
                        }

                        tangent = delta.Perpendicular();
                    }
                }

                // Try to propagate non-zero normals into any "zero" normals.
                for (int i = 0; i <= effNumSegments; i++)
                {
                    if (normals[i].sqrMagnitude < 0.00001f)
                    {
                        if (i == 0)
                        {
                            normals[i] = normals[i + 1];
                        }
                        else if (i == effNumSegments)
                        {
                            normals[i] = normals[i - 1];
                        }
                        else
                        {
                            normals[i] = Vector3.Slerp(normals[i - 1], normals[i + 1], 0.5f);
                        }
                    }

                    if (normals[i].sqrMagnitude < 0.00001f)
                    {
                        // OK, we tried, but we still have zero normals. Error and fail.
                        throw new System.InvalidOperationException(
                                  "Unable to build non-zero normals for this spline during PolyMesh "
                                  + "construction");
                    }
                }

                // With a set of normals and a starting tangent vector, we can construct all the
                // binormals we need to have an orientation and position for every cross-section.
                Vector3?lastNormal   = null;
                Vector3?lastBinormal = null;
                for (int i = 0; i <= effNumSegments; i++)
                {
                    var     normal = normals[i];
                    Vector3 binormal;
                    if (!lastBinormal.HasValue)
                    {
                        binormal = Vector3.Cross(normal, tangent.Value);
                    }
                    else
                    {
                        var rotFromLastNormal = Quaternion.FromToRotation(lastNormal.Value, normal);

                        binormal = rotFromLastNormal * lastBinormal.Value;
                    }
                    binormals.Add(binormal);

                    lastNormal   = normal;
                    lastBinormal = binormal;
                }

                // With positions, normals, and binormals for every cross section, add positions
                // and polygons for each cross section and their connections to the PolyMesh.
                int cs0Idx = -1, cs1Idx = -1;
                for (int i = 0; i + 1 <= effNumSegments; i++)
                {
                    var pose0 = new Pose(positions[i],
                                         Quaternion.LookRotation(normals[i], binormals[i]));
                    var pose1 = new Pose(positions[i + 1],
                                         Quaternion.LookRotation(normals[i + 1], binormals[i + 1]));

                    if (drawDebug)
                    {
                        drawer.PushMatrix();
                        drawer.matrix = transform.inverse;

                        drawer.color = LeapColor.blue;
                        drawer.DrawRay(pose0.position, normals[i] * 0.2f);

                        drawer.color = LeapColor.red;
                        drawer.DrawRay(pose0.position, binormals[i] * 0.2f);

                        drawer.PopMatrix();
                    }

                    bool addFirstPositions = i == 0;

                    // Add positions from Cross Section definition to reused buffers.
                    if (addFirstPositions)
                    {
                        crossSection.FillPositions(crossSection0Positions, pose0);
                    }
                    crossSection.FillPositions(crossSection1Positions, pose1);

                    // Add positions from buffers into the PolyMesh.
                    if (addFirstPositions)
                    {
                        cs0Idx = polyMesh.positions.Count;
                        polyMesh.AddPositions(crossSection0Positions);
                    }
                    cs1Idx = polyMesh.positions.Count;
                    polyMesh.AddPositions(crossSection1Positions);

                    // Add polygons to connect one cross section in the PolyMesh to the other.
                    crossSection.AddConnectingPolygons(polyMesh, cs0Idx, cs1Idx);

                    Utils.Swap(ref crossSection0Positions, ref crossSection1Positions);
                    cs0Idx = cs1Idx;
                }
            }
            finally {
                positions.Clear();
                Pool <List <Vector3> > .Recycle(positions);

                normals.Clear();
                Pool <List <Vector3> > .Recycle(normals);

                binormals.Clear();
                Pool <List <Vector3> > .Recycle(binormals);

                crossSection0Positions.Clear();
                Pool <List <Vector3> > .Recycle(crossSection0Positions);

                crossSection1Positions.Clear();
                Pool <List <Vector3> > .Recycle(crossSection1Positions);
            }
        }