Example #1
0
        public void RayIntersectsTriangle2()
        {
            //create a triangle
            Vector3 vert0 = new Vector3(0f, 0f, 0f);
            Vector3 vert1 = new Vector3(0.5f, 0f, 0.87f);
            Vector3 vert2 = new Vector3(1f, 0f, 0f);

            Vector3 origin    = new Vector3(0.5f, 0.5f, 0.43f);
            Vector3 direction = Vector3.down;

            //result
            Vector3 hitNormal = Vector3.zero;
            float   distance  = 0f;

            //should intersects
            bool intersects = PolyMath.RayIntersectsTriangle2(origin, direction, vert0, vert1, vert2, ref distance, ref hitNormal);

            Assert.IsTrue(intersects);
            Assert.IsTrue(distance == 0.5f);
            //the hitnormal is not normalized, I don't know why (????)
            Assert.IsTrue(hitNormal.normalized == Vector3.up);

            //should not intersects
            direction  = Vector3.up;
            intersects = PolyMath.RayIntersectsTriangle2(origin, direction, vert0, vert1, vert2, ref distance, ref hitNormal);
            Assert.IsFalse(intersects);

            //should not intersects
            origin     = new Vector3(5f, 0.5f, 0f);
            direction  = Vector3.down;
            intersects = PolyMath.RayIntersectsTriangle2(origin, direction, vert0, vert1, vert2, ref distance, ref hitNormal);
            Assert.IsFalse(intersects);
        }
Example #2
0
        public void WeightedAverage()
        {
            //null checks
            Assert.DoesNotThrow(() =>
            {
                PolyMath.WeightedAverage(null, null, null);
            });

            Vector3[] vertices = GetVerticesSample();

            //create a list of indexes that will be used
            List <int> indexes = new List <int>()
            {
                1, 2, 3, 4
            };

            //create a list of weights, size must be equal to the size of the vertices array
            float[] weights = new float[] { 0, 1, 1, 1, 1, 0 };
            //the weights should not affect the result on this test
            Vector3 average = PolyMath.WeightedAverage(vertices, indexes, weights);

            Assert.IsTrue(average == new Vector3(0.5f, 0f, 0.5f));

            //this time only the third corner of the square should be returned
            weights = new float[] { 0, 0, 0, 1, 0, 0 };
            average = PolyMath.WeightedAverage(vertices, indexes, weights);
            Assert.IsTrue(average == new Vector3(1f, 0f, 1f));

            //trying with weights higher than 1
            weights = new float[] { 0, 0, 1, 3, 0, 0 };
            average = PolyMath.WeightedAverage(vertices, indexes, weights);
            Assert.IsTrue(average == new Vector3(0.75f, 0f, 1f));
        }
Example #3
0
        /// <inheritdoc />
        public void Contour(
            IDualContourable <TVoxel, TSurfaceData> contourable,
            IMutableDivisibleMesh <NormalColorTextureVertex> meshBuilder)
        {
            IDualContourerContracts.Contour(contourable, meshBuilder);

            foreach (var projection in contourable.GetContourableProjections(this.contourDeterminer))
            {
                Vector3 topLeftVertex, topRightVertex, botLeftVertex, botRightVertex;
                this.positioner.GenerateValues(
                    projection,
                    out topLeftVertex,
                    out topRightVertex,
                    out botLeftVertex,
                    out botRightVertex);

                Vector3      normal;
                QuadDiagonal diagonal;

                if (projection.AbsoluteIndexOfOrigin.SumCoordinatesLong().IsEven())
                {
                    diagonal = QuadDiagonal.Ascending;
                    normal   = PolyMath.GetNormalizedAverage(
                        PolyMath.GetSurfaceNormal(topLeftVertex, botLeftVertex, topRightVertex),
                        PolyMath.GetSurfaceNormal(botLeftVertex, botRightVertex, topRightVertex));
                }
                else
                {
                    diagonal = QuadDiagonal.Descending;
                    normal   = PolyMath.GetNormalizedAverage(
                        PolyMath.GetSurfaceNormal(topLeftVertex, botLeftVertex, botRightVertex),
                        PolyMath.GetSurfaceNormal(topLeftVertex, botRightVertex, topRightVertex));
                }

                projection.SurfaceData.Diagonal = diagonal;

                Color topLeftColor, topRightColor, botLeftColor, botRightColor;
                this.colorer.GenerateValues(
                    projection,
                    out topLeftColor,
                    out topRightColor,
                    out botLeftColor,
                    out botRightColor);

                Vector2 topLeftTexture, topRightTexture, botLeftTexture, botRightTexture;
                this.texturer.GenerateValues(
                    projection,
                    out topLeftTexture,
                    out topRightTexture,
                    out botLeftTexture,
                    out botRightTexture);

                meshBuilder.AddFlatQuad(
                    topLeft: new NormalColorTextureVertex(topLeftVertex, normal, topLeftColor, topLeftTexture),
                    topRight: new NormalColorTextureVertex(topRightVertex, normal, topRightColor, topRightTexture),
                    bottomLeft: new NormalColorTextureVertex(botLeftVertex, normal, botLeftColor, botLeftTexture),
                    bottomRight: new NormalColorTextureVertex(botRightVertex, normal, botRightColor, botRightTexture),
                    diagonal: diagonal);
            }
        }
Example #4
0
        public void GenerateValues(
            IVoxelProjection <TVoxel, TSurfaceData> projection,
            out TValue topLeftValue,
            out TValue topRightValue,
            out TValue bottomLeftValue,
            out TValue bottomRightValue)
        {
            if (projection.SurfaceData.Diagonal == QuadDiagonal.Ascending)
            {
                projection.SurfaceData.SurfaceArea =
                    PolyMath.GetArea(
                        projection.SurfaceData.TopLeftVertex,
                        projection.SurfaceData.BottomLeftVertex,
                        projection.SurfaceData.TopRightVertex) +
                    PolyMath.GetArea(
                        projection.SurfaceData.BottomLeftVertex,
                        projection.SurfaceData.BottomRightVertex,
                        projection.SurfaceData.TopRightVertex);
            }
            else
            {
                projection.SurfaceData.SurfaceArea =
                    PolyMath.GetArea(
                        projection.SurfaceData.TopLeftVertex,
                        projection.SurfaceData.BottomLeftVertex,
                        projection.SurfaceData.BottomRightVertex) +
                    PolyMath.GetArea(
                        projection.SurfaceData.TopLeftVertex,
                        projection.SurfaceData.BottomRightVertex,
                        projection.SurfaceData.TopRightVertex);
            }

            if (projection.SurfaceData.SurfaceArea >= this.threshold)
            {
                this.aboveThresholdGenerator.GenerateValues(
                    projection,
                    out topLeftValue,
                    out topRightValue,
                    out bottomLeftValue,
                    out bottomRightValue);
            }
            else
            {
                this.belowThresholdGenerator.GenerateValues(
                    projection,
                    out topLeftValue,
                    out topRightValue,
                    out bottomLeftValue,
                    out bottomRightValue);
            }
        }
Example #5
0
        public void Average()
        {
            //null checks
            Assert.DoesNotThrow(() =>
            {
                PolyMath.Average(null, null);
            });

            Vector3[] vertices = GetVerticesSample();

            //create a list of indexes that will be used
            List <int> indexes = new List <int>()
            {
                1, 2, 3, 4
            };

            Vector3 average = PolyMath.Average(vertices, indexes);

            Assert.IsTrue(average == new Vector3(0.5f, 0f, 0.5f));
        }
        /// <summary>
        /// Cast a ray (in model space) against a mesh.
        /// </summary>
        /// <param name="InRay"></param>
        /// <param name="vertices"></param>
        /// <param name="triangles"></param>
        /// <param name="hit"></param>
        /// <param name="distance"></param>
        /// <param name="cullingMode"></param>
        /// <returns></returns>
        internal static bool MeshRaycast(Ray InRay, Vector3[] vertices, int[] triangles, out PolyRaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front)
        {
            float   hitDistance = Mathf.Infinity;
            Vector3 hitNormal = Vector3.zero;   // vars used in loop
            Vector3 vert0, vert1, vert2;
            int     hitFace = -1;
            Vector3 origin = InRay.origin, direction = InRay.direction;

            /**
             * Iterate faces, testing for nearest hit to ray origin.
             */
            for (int CurTri = 0; CurTri < triangles.Length; CurTri += 3)
            {
                if (CurTri + 2 >= triangles.Length)
                {
                    continue;
                }
                if (triangles[CurTri + 2] >= vertices.Length)
                {
                    continue;
                }

                vert0 = vertices[triangles[CurTri + 0]];
                vert1 = vertices[triangles[CurTri + 1]];
                vert2 = vertices[triangles[CurTri + 2]];

                if (PolyMath.RayIntersectsTriangle2(origin, direction, vert0, vert1, vert2, ref distance, ref hitNormal))
                {
                    hitFace     = CurTri / 3;
                    hitDistance = distance;
                    break;
                }
            }

            hit = new PolyRaycastHit(hitDistance,
                                     InRay.GetPoint(hitDistance),
                                     hitNormal,
                                     hitFace);

            return(hitFace > -1);
        }
        internal override void OnBrushApply(BrushTarget target, BrushSettings settings)
        {
            if (!likelyToSupportVertexSculpt)
            {
                return;
            }

            int rayCount = target.raycastHits.Count;

            Vector3[] normals = (s_SmoothDirection == PolyDirection.BrushNormal) ? target.editableObject.editMesh.normals : null;

            Vector3  v, t, avg, dirVec = s_SmoothDirection.value.ToVector3();
            Plane    plane       = new Plane(Vector3.up, Vector3.zero);
            PolyMesh mesh        = target.editableObject.editMesh;
            int      vertexCount = mesh.vertexCount;

            // don't use target.GetAllWeights because brush normal needs
            // to know which ray to use for normal
            for (int ri = 0; ri < rayCount; ri++)
            {
                PolyRaycastHit hit = target.raycastHits[ri];

                if (hit.weights == null || hit.weights.Length < vertexCount)
                {
                    continue;
                }

                for (int i = 0; i < commonVertexCount; i++)
                {
                    int index = commonVertices[i][0];

                    if (hit.weights[index] < .0001f || (s_IgnoreOpenEdges && nonManifoldIndices.Contains(index)))
                    {
                        continue;
                    }

                    v = vertices[index];

                    if (s_SmoothDirection == PolyDirection.VertexNormal)
                    {
                        avg = PolyMath.Average(vertices, neighborLookup[index]);
                    }
                    else
                    {
                        avg = PolyMath.WeightedAverage(vertices, neighborLookup[index], hit.weights);

                        if (s_SmoothDirection == PolyDirection.BrushNormal)
                        {
                            if (s_UseFirstNormalVector)
                            {
                                dirVec = brushNormalOnBeginApply[ri];
                            }
                            else
                            {
                                dirVec = PolyMath.WeightedAverage(normals, neighborLookup[index], hit.weights).normalized;
                            }
                        }

                        plane.SetNormalAndPosition(dirVec, avg);
                        avg = v - dirVec * plane.GetDistanceToPoint(v);
                    }

                    t = Vector3.Lerp(v, avg, hit.weights[index]);
                    List <int> indices = commonVertices[i];

                    Vector3 pos = v + (t - v) * settings.strength * SMOOTH_STRENGTH_MODIFIER;

                    for (int n = 0; n < indices.Count; n++)
                    {
                        vertices[indices[n]] = pos;
                    }
                }
            }

            mesh.vertices = vertices;

            if (tempComponent != null)
            {
                tempComponent.OnVerticesMoved(mesh);
            }

            base.OnBrushApply(target, settings);
        }
Example #8
0
 public Vector3 CalculateNormalWithPointsCollection(Vector3[] points)
 {
     return(PolyMath.Normal(points));
 }
Example #9
0
 public Vector3 TestMathNormalWithThreePoints(Vector3 v0, Vector3 v1, Vector3 v2)
 {
     return(PolyMath.Normal(v0, v1, v2));
 }
Example #10
0
 public void VectorIsUniform()
 {
     Assert.IsTrue(PolyMath.VectorIsUniform(Vector3.one));
     Assert.IsFalse(PolyMath.VectorIsUniform(Vector3.right));
 }
Example #11
0
        /// <summary>
        /// Calculates the per-vertex weight for each raycast hit and fills in brush target weights.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="settings"></param>
        /// <param name="tool"></param>
        /// <param name="bMode"></param>
        internal static void CalculateWeightedVertices(BrushTarget target, BrushSettings settings, BrushTool tool = BrushTool.None, BrushMode bMode = null)
        {
            //null checks
            if (target == null || settings == null)
            {
                return;
            }

            if (target.editableObject == null)
            {
                return;
            }

            bool  uniformScale = PolyMath.VectorIsUniform(target.transform.lossyScale);
            float scale        = uniformScale ? 1f / target.transform.lossyScale.x : 1f;

            PolyMesh mesh = target.editableObject.visualMesh;

            if (tool == BrushTool.Texture && mesh.subMeshCount > 1)
            {
                var   mode           = bMode as BrushModeTexture;
                int[] submeshIndices = mesh.subMeshes[mode.currentMeshACIndex].indexes;

                //List<List<int>> common = PolyMeshUtility.GetCommonVertices(mesh);

                Transform transform   = target.transform;
                int       vertexCount = mesh.vertexCount;
                Vector3[] vertices    = mesh.vertices;

                if (!uniformScale)
                {
                    Vector3[] world = new Vector3[vertexCount];
                    for (int i = 0; i < vertexCount; i++)
                    {
                        world[i] = transform.TransformPoint(vertices[i]);
                    }
                    vertices = world;
                }

                AnimationCurve curve = settings.falloffCurve;
                float          radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f);

                Vector3        hitPosition = Vector3.zero;
                PolyRaycastHit hit;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    for (int i = 0; i < vertexCount; i++)
                    {
                        hit.weights[i] = 0f;
                    }

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < submeshIndices.Length; i++)
                    {
                        int   currentIndex = submeshIndices[i];
                        float dist         = (hitPosition - vertices[currentIndex]).magnitude;
                        float delta        = radius - dist;

                        if (delta >= 0)
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp(delta / falloff_mag, 0f, 1f)), 0f, 1f);

                            hit.weights[currentIndex] = weight;
                        }
                    }
                }
            }
            else
            {
                List <List <int> > common = PolyMeshUtility.GetCommonVertices(mesh);

                Transform transform   = target.transform;
                int       vertexCount = mesh.vertexCount;
                Vector3[] vertices    = mesh.vertices;

                if (!uniformScale)
                {
                    Vector3[] world = new Vector3[vertexCount];
                    for (int i = 0; i < vertexCount; i++)
                    {
                        world[i] = transform.TransformPoint(vertices[i]);
                    }
                    vertices = world;
                }

                AnimationCurve curve = settings.falloffCurve;
                float          radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f);

                Vector3        hitPosition = Vector3.zero;
                PolyRaycastHit hit;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < common.Count; i++)
                    {
                        int   commonArrayCount = common[i].Count;
                        float sqrDist          = (hitPosition - vertices[common[i][0]]).sqrMagnitude;

                        if (sqrDist > radius * radius)
                        {
                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[common[i][j]] = 0f;
                            }
                        }
                        else
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp((radius - Mathf.Sqrt(sqrDist)) / falloff_mag, 0f, 1f)), 0f, 1f);

                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[common[i][j]] = weight;
                            }
                        }
                    }
                }
            }
            target.GetAllWeights(true);
        }