Example #1
0
        protected virtual void OnDestroy()
        {
            // In clearing the PolyMesh, its data is pooled.
            _polyMesh.Clear();
            Pool <PolyMesh> .Recycle(_polyMesh);

            _unityMeshA.Clear();
            Pool <Mesh> .Recycle(_unityMeshA);

            _unityMeshB.Clear();
            Pool <Mesh> .Recycle(_unityMeshB);
        }
Example #2
0
        protected virtual void Awake()
        {
            _meshFilter = GetComponent <MeshFilter>();

            _polyMesh = Pool <PolyMesh> .Spawn();

            _polyMesh.DisableEdgeAdjacencyData();
            _polyMesh.Clear();

            _unityMeshA = Pool <Mesh> .Spawn();

            _unityMeshA.Clear();
            _unityMeshA.MarkDynamic();
            _unityMeshB = Pool <Mesh> .Spawn();

            _unityMeshB.Clear();
            _unityMeshB.MarkDynamic();
        }
        /// <summary>
        /// Return a mesh that is the combination of both additionalVertexStreams and the originalMesh.
        ///     - Position
        ///     - UV0
        ///     - UV2
        ///     - UV3
        ///     - UV4
        ///     - Color
        ///     - Tangent
        /// </summary>
        /// <returns>The new PolyMesh object</returns>
        private void GenerateCompositeMesh()
        {
            if (_editMesh == null)
            {
                _editMesh = polybrushMesh.polyMesh;
            }

            _editMesh.Clear();
            _editMesh.name     = originalMesh.name;
            _editMesh.vertices = GetAttribute(x => x.vertices);
            _editMesh.normals  = GetAttribute(x => x.normals);
            _editMesh.colors   = GetAttribute(x => x.colors32);
            _editMesh.tangents = GetAttribute(x => x.tangents);
            _editMesh.uv0      = GetAttribute(x => { List <Vector4> l = new List <Vector4>(); x.GetUVs(0, l); return(l); });
            _editMesh.uv1      = GetAttribute(x => { List <Vector4> l = new List <Vector4>(); x.GetUVs(1, l); return(l); });
            _editMesh.uv2      = GetAttribute(x => { List <Vector4> l = new List <Vector4>(); x.GetUVs(2, l); return(l); });
            _editMesh.uv3      = GetAttribute(x => { List <Vector4> l = new List <Vector4>(); x.GetUVs(3, l); return(l); });

            _editMesh.SetSubMeshes(originalMesh);
        }
Example #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);
            }
        }
Example #5
0
        private void refreshMesh()
        {
            if (outputToFilter == null)
            {
                return;
            }
            if (outputToFilter.sharedMesh == null)
            {
                outputToFilter.sharedMesh      = new Mesh();
                outputToFilter.sharedMesh.name = "PoseRibbonMesh Test";
            }
            var mesh = outputToFilter.sharedMesh;

            mesh.Clear();

            var pose0 = poseSource0.ToLocalPose();
            var pose1 = poseSource1.ToLocalPose();
            var pose2 = poseSource2.ToLocalPose();

            var poses = Pool <List <Pose> > .Spawn();

            poses.Clear();
            try {
                poses.Add(pose0); poses.Add(pose1); poses.Add(pose2);

                if (!usePolyMeshMethod)
                {
                    #region Non-PolyMesh Method
                    var verts   = Pool <List <Vector3> > .Spawn(); verts.Clear();
                    var indices = Pool <List <int> > .Spawn(); indices.Clear();
                    try {
                        for (int i = 0; i < poses.Count; i++)
                        {
                            var p = poses[i];

                            verts.Add(left(p));
                            verts.Add(right(p));
                        }

                        int  vertsPerPose = 2;
                        bool closeLoop    = vertsPerPose != 2;

                        for (int p = 0; p + 1 < poses.Count; p++)
                        {
                            for (int csi = 0; csi < vertsPerPose - (closeLoop ? 0 : 1); csi++)
                            {
                                var csRootIndex     = p * vertsPerPose;
                                var nextCSRootIndex = (p + 1) * vertsPerPose;

                                var i0 = csRootIndex + csi;
                                var i1 = nextCSRootIndex + csi;
                                var i2 = nextCSRootIndex + ((csi + 1) % vertsPerPose);
                                var i3 = csRootIndex + ((csi + 1) % vertsPerPose);

                                indices.Add(i0);
                                indices.Add(i1);
                                indices.Add(i2);

                                indices.Add(i0);
                                indices.Add(i2);
                                indices.Add(i3);
                            }
                        }

                        mesh.SetVertices(verts);
                        mesh.SetTriangles(indices, 0, true);

                        mesh.RecalculateNormals();
                    }
                    finally {
                        verts.Clear(); Pool <List <Vector3> > .Recycle(verts);

                        indices.Clear(); Pool <List <int> > .Recycle(indices);
                    }
                    #endregion
                }
                else
                {
                    polyMesh.Clear();

                    // quad 0
                    polyMesh.AddPosition(left(pose0));
                    polyMesh.AddPosition(right(pose0));
                    polyMesh.AddPosition(left(pose1));
                    polyMesh.AddPosition(right(pose1));
                    var newPoly = Polygon.SpawnQuad(1, 0, 2, 3);
                    polyMesh.AddPolygon(newPoly);

                    // quad 1
                    polyMesh.AddPosition(left(pose2));
                    polyMesh.AddPosition(right(pose2));
                    var nextPoly = Polygon.SpawnQuad(3, 2, 4, 5);
                    polyMesh.AddPolygon(nextPoly);

                    // mark the edge between the two quads as smooth.
                    polyMesh.MarkEdgeSmooth(new Edge(2, 3));

                    polyMesh.FillUnityMesh(mesh, doubleSided: true);
                }
            }
            finally {
                poses.Clear();
                Pool <List <Pose> > .Recycle(poses);
            }
        }