Exemple #1
0
        public static float CalculateDimensionalValueAtIndex(SlicePoint p1, SlicePoint p2, float z, string precision = "0000")
        {
            var slope     = (p1.Y - p2.Y) / (p1.X - p2.X);
            var intercept = p1.Y - (slope * p1.X);
            var rawVal    = slope * z + intercept;
            // using floats we end up with some infinitesimal rounding errors,
            // so we need to set the precision to something reasonable. Default is 1/100th of a micron
            // I'm sure there's a better way than converting it to a string and then back to a float,
            // but that's what I've got right now, so that's what I'm doing.
            var strVal = rawVal.ToString($"0.{precision}");

            return(float.Parse(strVal, CultureInfo.InvariantCulture.NumberFormat));
        }
        public void CalculateZIntercept_GetsZValuesFromAnyTwoFacets()
        {
            // easy math, 45deg, all positive, from origin
            var v1 = new Vertex {
                X = 0, Y = 0, Z = 0
            };
            var v2 = new Vertex {
                X = 10, Y = 10, Z = 10
            };
            var p1 = new SlicePoint {
                X = 5, Y = 5
            };
            var z1 = 5;
            // crosses x- and y- axes, negative z-slope
            var v3 = new Vertex {
                X = -5, Y = -10, Z = 15
            };
            var v4 = new Vertex {
                X = 7, Y = 10, Z = 7
            };
            var p2 = new SlicePoint {
                X = 4, Y = 5
            };
            var z2 = 9;
            // crosses z-axis
            var v5 = new Vertex {
                X = 11, Y = 6, Z = -3
            };
            var v6 = new Vertex {
                X = 17, Y = -4, Z = 7
            };
            var p3 = new SlicePoint {
                X = 14, Y = 1
            };
            var z3 = 2;

            // Again, this should work regardless of direction
            var rp1 = LinAlgUtils.CalculateZIntercept(v1, v2, z1);
            var rp2 = LinAlgUtils.CalculateZIntercept(v1, v2, z1);

            Assert.True(rp1 == rp2 && rp1 == p1);

            rp1 = LinAlgUtils.CalculateZIntercept(v3, v4, z2);
            rp2 = LinAlgUtils.CalculateZIntercept(v4, v3, z2);
            Assert.True(rp1 == rp2 && rp1 == p2);

            rp1 = LinAlgUtils.CalculateZIntercept(v5, v6, z3);
            rp2 = LinAlgUtils.CalculateZIntercept(v6, v5, z3);
            Assert.True(rp1 == rp2 && rp1 == p3);
        }
        public void CalculateDimensionalValueAtIndex_CalculatesProperValuesAtMultipleAngles()
        {
            // easy math, 45dg all positive
            var p1 = new SlicePoint {
                X = 0, Y = 0
            };
            var p2 = new SlicePoint {
                X = 10, Y = 10
            };
            // crosses both axes
            var p3 = new SlicePoint {
                X = -3, Y = -1
            };
            var p4 = new SlicePoint {
                X = 10, Y = 7
            };
            // crosses Y-Axis, heading down
            var p5 = new SlicePoint {
                X = -5, Y = -2
            };
            var p6 = new SlicePoint {
                X = 16, Y = -14
            };

            // we shouldn't be using this for flat lines, but I'll make sure it works, regardless
            var p7 = new SlicePoint {
                X = 10, Y = 22
            };
            var p8 = new SlicePoint {
                X = 4, Y = 22
            };

            // Each time we should find the same value  regardless of which point is placed first
            Assert.Equal(5, LinAlgUtils.CalculateDimensionalValueAtIndex(p1, p2, 5));
            Assert.Equal(5, LinAlgUtils.CalculateDimensionalValueAtIndex(p2, p1, 5));

            Assert.Equal(3, LinAlgUtils.CalculateDimensionalValueAtIndex(p3, p4, 3.5f));
            Assert.Equal(3, LinAlgUtils.CalculateDimensionalValueAtIndex(p4, p3, 3.5f));

            Assert.Equal(-10, LinAlgUtils.CalculateDimensionalValueAtIndex(p5, p6, 9));
            Assert.Equal(-10, LinAlgUtils.CalculateDimensionalValueAtIndex(p6, p5, 9));

            Assert.Equal(22, LinAlgUtils.CalculateDimensionalValueAtIndex(p7, p8, 16));
            Assert.Equal(22, LinAlgUtils.CalculateDimensionalValueAtIndex(p8, p7, 16));
        }
Exemple #4
0
        public void Slice(DynamicRenderMesh mesh, Camera camera)
        {
            slicePointsDictionary.Clear();
            verticesDictionary.Clear();
            slicePoints.Clear();
            vertices.Clear();
            texCoords.Clear();
            indices.Clear();
            triangles.Clear();
            ResultMeshes.Clear();

            FillVertices(mesh, camera);
            Vector2 A = new Vector2(99999.0f, 99999.0f), B = new Vector2(-99999.0f, -99999.0f);
            var     tempLine      = new Line2d();
            var     workedIndices = new List <int>();
            var     tempIndices   = new List <int>();

            foreach (var line in Lines)
            {
                for (var i = 0; i < 2; i++)
                {
                    if (line.A[i] < A[i])
                    {
                        A[i] = line.A[i];
                    }
                    if (line.B[i] > B[i])
                    {
                        B[i] = line.B[i];
                    }
                }
            }
            for (var i = 0; i < indices.Count / 3; i++)
            {
                var index  = i * 3;
                var point0 = vertices[indices[index]];
                var point1 = vertices[indices[index + 1]];
                var point2 = vertices[indices[index + 2]];



                if (!CheckAABB(ref point0, ref point1, ref point2, ref A, ref B))
                {
                    for (var j = 0; j < 3; j++)
                    {
                        tempIndices.Add(indices[index + j]);
                    }
                    continue;
                }

                for (var j = 0; j < 3; j++)
                {
                    workedIndices.Add(indices[index + j]);
                }
            }

            if (workedIndices.Count == 0)
            {
                return;
            }

            var triangle                  = new Vector3[3];
            var triangleT                 = new Vector2[3];
            var tempCollisions            = new List <Vector3>();
            var tempTexCoords             = new List <Vector2>();
            var tempCollisionsEdgeIndices = new List <int>();
            var newTriangles              = new List <int>();
            var info0 = CollisionInfo.Zero;
            var info1 = CollisionInfo.Zero;

            for (var i = 0; i < sliceLines.Count; i++)
            {
                var line           = Lines[i];
                var sliceLine      = sliceLines[i];
                var trianglesCount = workedIndices.Count / 3;
                for (var j = 0; j < trianglesCount; j++)
                {
                    var index = j * 3;
                    for (var l = 0; l < 3; l++)
                    {
                        triangle[l]  = vertices[workedIndices[index + l]];
                        triangleT[l] = texCoords[workedIndices[index + l]];
                    }

                    info0 = CollisionInfo.Zero;
                    info1 = CollisionInfo.Zero;
                    tempCollisions.Clear();
                    tempTexCoords.Clear();
                    tempCollisionsEdgeIndices.Clear();
                    newTriangles.Clear();
                    //looking for a point / intersection point of the triangle and line
                    for (int k = 0, l = 2; k < 3; l = k, k++)
                    {
                        if (info1.Type != CollisionType.CT_NONE)
                        {
                            break;
                        }
                        var tPoint0 = triangle[l];
                        var tPoint1 = triangle[k];

                        var tTexCoord0 = triangleT[l];
                        var tTexCoord1 = triangleT[k];

                        tempLine.Point0.X = tPoint0.X;
                        tempLine.Point0.Y = tPoint0.Y;
                        tempLine.Point1.X = tPoint1.X;
                        tempLine.Point1.Y = tPoint1.Y;

                        float ua, ub;
                        if (!GetUaUb(tempLine, line, out ua, out ub))
                        {
                            //lines coincide?
                            //Verify whether some point belongs line segment tempLine
                            //if find - get result and break.
                        }
                        else
                        {
                            if (ub < 0.0f || ub > 1.0f)
                            {
                                continue;
                            }
                            var collisionPoint    = tPoint0 + (tPoint1 - tPoint0) * ub;
                            var collisionTexCoord = tTexCoord0 + (tTexCoord1 - tTexCoord0) * ub;
                            if (tempCollisions.Count == 0 || !PointsCompare.Equals(tempCollisions[0], collisionPoint))
                            {
                                tempCollisions.Add(collisionPoint);
                                tempTexCoords.Add(collisionTexCoord);
                                tempCollisionsEdgeIndices.Add(l);
                            }
                            if (ua < 0.0f || ua > 1.0f)
                            {
                                continue;
                            }

                            var     pointType = CollisionType.CT_VERTEX;
                            Vector3 point;
                            Vector2 texCoord;
                            var     pointIndex = -1;
                            var     edgeIndex  = -1;

                            if (ub > 0.0f)
                            {
                                if (ub < 1.0f)
                                {
                                    pointType = CollisionType.CT_EDGE;
                                    point     = tempCollisions.Last();
                                    texCoord  = tempTexCoords.Last();
                                    edgeIndex = l;
                                }
                                else
                                {
                                    point      = tPoint1;
                                    texCoord   = tTexCoord1;
                                    pointIndex = workedIndices[index + k];
                                }
                            }
                            else
                            {
                                point      = tPoint0;
                                texCoord   = tTexCoord0;
                                pointIndex = workedIndices[index + l];
                            }
                            if (info0.Type == CollisionType.CT_NONE)
                            {
                                info0.PointIndex = pointIndex;
                                info0.Type       = pointType;
                                info0.Position   = point;
                                info0.TexCoord   = texCoord;
                                info0.EdgeIndex  = edgeIndex;
                            }
                            else
                            {
                                if (pointIndex == -1 || info0.PointIndex != pointIndex)
                                {
                                    info1.PointIndex = pointIndex;
                                    info1.Type       = pointType;
                                    info1.Position   = point;
                                    info1.TexCoord   = texCoord;
                                    info1.EdgeIndex  = edgeIndex;
                                }
                            }
                        }
                    }

                    if (info1.Type == CollisionType.CT_NONE)
                    {
                        if (tempCollisions.Count == 0)
                        {
                            if (info0.Type == CollisionType.CT_NONE)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (tempCollisions.Count > 1)
                            {
                                //Perhaps the point inside the triangle
                                var dir = line.Direction;
                                for (var l = 0; l < 2; l++)
                                {
                                    var p = l == 0 ? line.Point0 : line.Point1;
                                    if (PointInTriangle(ref triangle[0], ref triangle[1], ref triangle[2], ref p))
                                    {
                                        var v0 = tempCollisions[1].Xy - tempCollisions[0].Xy;
                                        var v1 = p - tempCollisions[0].Xy;
                                        var k  = (v1.Length / v0.Length);
                                        var z  = tempCollisions[0].Z + (tempCollisions[1].Z - tempCollisions[0].Z) * k;
                                        var t  = tempTexCoords[0] + (tempTexCoords[1] - tempTexCoords[0]) * k;
                                        if (info0.Type == CollisionType.CT_NONE)
                                        {
                                            info0.Type     = CollisionType.CT_INSIDE;
                                            info0.Position = new Vector3(p.X, p.Y, z);
                                            info0.TexCoord = t;
                                            if (Vector2.Dot(dir, v0) > 0.0f)
                                            {
                                                info0.EdgeIndex = tempCollisionsEdgeIndices[0];
                                            }
                                            else
                                            {
                                                info0.EdgeIndex = tempCollisionsEdgeIndices[1];
                                            }
                                            tempCollisionsEdgeIndices.Remove(info0.EdgeIndex);
                                        }
                                        else
                                        {
                                            info1.Type      = CollisionType.CT_INSIDE;
                                            info1.Position  = new Vector3(p.X, p.Y, z);
                                            info1.TexCoord  = t;
                                            info1.EdgeIndex = tempCollisionsEdgeIndices[0];
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (info0.Type == CollisionType.CT_NONE)
                    {
                        continue;
                    }
                    //Create new triangles, if we have two points of intersection, and they are not vertices
                    int pi1 = 0, pi0 = 0;
                    if (info1.Type != CollisionType.CT_NONE && (info0.Type != CollisionType.CT_VERTEX || info1.Type != CollisionType.CT_VERTEX))
                    {
                        if (info1.Type == CollisionType.CT_VERTEX ||
                            (info1.Type == CollisionType.CT_EDGE && info0.Type == CollisionType.CT_INSIDE) ||
                            (info1.Type == CollisionType.CT_EDGE && info0.Type == CollisionType.CT_EDGE && (info0.EdgeIndex + 1) % 3 != info1.EdgeIndex) ||
                            (info0.Type == CollisionType.CT_INSIDE && info1.Type == CollisionType.CT_INSIDE && (info0.EdgeIndex + 1) % 3 != info1.EdgeIndex))
                        {
                            var temp = info1;
                            info1 = info0;
                            info0 = temp;
                        }

                        if (!verticesDictionary.TryGetValue(info1.Position, out pi1))
                        {
                            pi1 = vertices.Count;
                            vertices.Add(info1.Position);
                            texCoords.Add(info1.TexCoord);
                            verticesDictionary.Add(info1.Position, pi1);
                        }

                        if (info0.Type == CollisionType.CT_VERTEX) //One point of intersection coincides with the vertex
                        {
                            pi0 = info0.PointIndex;
                            int i0 = workedIndices[index], i1 = workedIndices[index + 1], i2 = workedIndices[index + 2];
                            if (i0 == info0.PointIndex)
                            {
                                i0 = i2;
                                i2 = i1;
                            }
                            else
                            {
                                if (i2 == info0.PointIndex)
                                {
                                    i2 = i0;
                                    i0 = i1;
                                }
                            }
                            i1 = info0.PointIndex;

                            newTriangles.AddRange(new[] { i0, i1, pi1,
                                                          i1, i2, pi1 });
                            if (info1.Type == CollisionType.CT_INSIDE) //The second point inside the triangle
                            {
                                newTriangles.AddRange(new[] { i2, i0, pi1 });
                            }
                        }
                        else
                        {
                            if (!verticesDictionary.TryGetValue(info0.Position, out pi0))
                            {
                                pi0 = vertices.Count;
                                vertices.Add(info0.Position);
                                texCoords.Add(info0.TexCoord);
                                verticesDictionary.Add(info0.Position, pi0);
                            }

                            if (info1.Type != info0.Type) //One point crosses the brink, the second inside the triangle
                            {
                                var prev = info0.EdgeIndex == 0 ? 2 : info0.EdgeIndex - 1;
                                prev = workedIndices[index + prev];
                                var next = info0.EdgeIndex == 2 ? 0 : info0.EdgeIndex + 1;
                                next = workedIndices[index + next];
                                var curr = workedIndices[index + info0.EdgeIndex];
                                newTriangles.AddRange(new[] { prev, curr, pi1,
                                                              curr, pi0, pi1,
                                                              pi0, next, pi1,
                                                              next, prev, pi1 });
                            }
                            else
                            {
                                var c0 = workedIndices[index + info0.EdgeIndex];
                                var c1 = workedIndices[index + info1.EdgeIndex];
                                var c2 = workedIndices[index + ((info1.EdgeIndex + 1) % 3)];

                                if (info0.Type == CollisionType.CT_EDGE)
                                {
                                    newTriangles.AddRange(new[] { c0, pi0, pi1,
                                                                  pi0, c1, pi1,
                                                                  pi1, c2, c0 });
                                }
                                else
                                {
                                    newTriangles.AddRange(new[] { c0, c1, pi0,
                                                                  c1, pi1, pi0,
                                                                  c1, c2, pi1,
                                                                  c2, c0, pi1,
                                                                  c0, pi0, pi1 });
                                }
                            }
                        }
                    }
                    int        slicePointIndex;
                    SlicePoint slicePoint;
                    for (var l = 0; l < 2; l++)
                    {
                        if (l == 1 && info1.Type == CollisionType.CT_NONE)
                        {
                            break;
                        }
                        var position   = l == 0 ? info0.Position.Xy : info1.Position.Xy;
                        var pointIndex = l == 0 ? pi0 : pi1;
                        if (!slicePointsDictionary.TryGetValue(position, out slicePointIndex))
                        {
                            slicePoint = new SlicePoint
                            {
                                Coordinate = position
                            };
                            slicePoint.Lines.Add(sliceLine);
                            slicePoint.PreparePoint();
                            slicePointIndex = slicePoints.Count;
                            slicePoints.Add(slicePoint);
                            slicePointsDictionary.Add(position, slicePointIndex);
                        }
                        else
                        {
                            slicePoint = slicePoints[slicePointIndex];
                        }
                        if (!slicePoint.Indices.Contains(pointIndex))
                        {
                            slicePoint.Indices.Add(pointIndex);
                        }
                    }

                    if (newTriangles.Count > 0)
                    {
                        for (var l = 0; l < 3; l++)
                        {
                            workedIndices[index + l] = newTriangles[l];
                        }
                        newTriangles.RemoveRange(0, 3);
                        workedIndices.InsertRange(index, newTriangles);
                        var count = (newTriangles.Count / 3);
                        j += count;
                        trianglesCount += count;
                    }
                }
            }

            for (var i = 0; i < workedIndices.Count / 3; i++)
            {
                var index = i * 3;
                var t     = new Triangle();
                for (var j = 0; j < 3; j++)
                {
                    t.Indices[j] = workedIndices[index + j];
                }
                triangles.Add(i, new TrianleConnections
                {
                    Triangle = t
                });
            }

            var ind          = new List <int>();
            var tempTriangle = new Triangle();

            tempTriangle.Indices[1] = -1;
            foreach (var point in slicePoints)
            {
                point.PreparePoint();
                foreach (var index in point.Indices)
                {
                    ind.Clear();
                    ind.Add(index);
                    tempTriangle.Indices[0] = index;
                    //Duplicate the verticle several times
                    for (var i = 1; i < point.Directions.Count; i++)
                    {
                        ind.Add(vertices.Count);
                        vertices.Add(vertices[index]);
                        texCoords.Add(texCoords[index]);
                    }
                    foreach (var t in triangles)
                    {
                        var tr = t.Value.Triangle;
                        var id = Triangle.TriangleEquals(ref tempTriangle, ref tr);
                        if (id > -1)
                        {
                            var center = (vertices[tr.Indices[0]].Xy + vertices[tr.Indices[1]].Xy + vertices[tr.Indices[2]].Xy) / 3.0f;
                            var dir    = (center - point.Coordinate).Normalized();
                            var angle  = SlicePoint.GetAngle(ref dir);
                            var ii     = point.Directions.Count - 1;
                            for (var j = 0; j < point.Directions.Count; j++)
                            {
                                if (angle < point.Directions[j])
                                {
                                    break;
                                }
                                ii = j;
                            }
                            tr.Indices[id] = ind[ii];
                        }
                    }
                }
            }

            var invTransform = mesh.Transform * camera.ViewMatrix;

            invTransform.Invert();
            for (var i = 0; i < vertices.Count; i++)
            {
                vertices[i] = Vector3.Transform(vertices[i], invTransform);
            }

            workedIndices.Clear();

            foreach (var t in triangles)
            {
                foreach (var i in t.Value.Triangle.Indices)
                {
                    workedIndices.Add(i);
                }
            }
            workedIndices.AddRange(tempIndices);
            triangleConnections.Clear();
            triangles.Clear();

            for (var i = 0; i < workedIndices.Count / 3; i++)
            {
                var index = i * 3;
                var t     = new Triangle();
                for (var j = 0; j < 3; j++)
                {
                    t.Indices[j] = workedIndices[index + j];
                    List <int> l;
                    if (!triangleConnections.TryGetValue(t.Indices[j], out l))
                    {
                        l = new List <int>();
                        triangleConnections.Add(t.Indices[j], l);
                    }
                    l.Add(i);
                }
                triangles.Add(i, new TrianleConnections
                {
                    Triangle = t
                });
            }

            var mainMesh = true;

            while (triangles.Count > 0)
            {
                foundedTriangles.Clear();
                FillTriangles(triangles.First().Key);

                if (mainMesh)
                {
                    mesh.Create(vertices, texCoords, foundedTriangles, mesh.Material.DiffuseTextureMap, mesh.Material.TransparentTextureMap, mesh.TextureAngle, mesh.TextureSize);
                    mainMesh = false;
                }
                else
                {
                    var tmpMesh = new DynamicRenderMesh(MeshType.Hair);
                    tmpMesh.Create(vertices, texCoords, foundedTriangles, mesh.Material.DiffuseTextureMap, mesh.Material.TransparentTextureMap, mesh.TextureAngle, mesh.TextureSize);
                    tmpMesh.Transform             = mesh.Transform;
                    tmpMesh.Material.DiffuseColor = mesh.Material.DiffuseColor;
                    tmpMesh.MeshAngle             = mesh.MeshAngle;
                    tmpMesh.MeshSize = mesh.MeshSize;

                    var info   = tmpMesh.GetMeshInfo();
                    var center = Vector3.Zero;
                    var scale  = PickingController.GetHairScale(ProgramCore.Project.ManType);
                    foreach (var vert in info.Positions)
                    {
                        center.X += vert.X * scale;
                        center.Y += vert.Y * scale;
                        center.Z += vert.Z * scale;
                    }
                    center          /= info.Positions.Count;
                    tmpMesh.Position = center;

                    ResultMeshes.Add(tmpMesh);
                }
            }
        }
    // returns null if nothing was sliced
    // even when hit by the laser nothing might get sliced
    //	this is because I limit the minimum size of a new
    //	planetoid for performance reasons.
    //
    public Planetoid Slice(Ray2D laser, float laserPower, PlanetoidsManager manager)
    {
        if (_fading)
        {
            return(null);
        }

        try {
            Vector2 start = transform.InverseTransformPoint(laser.origin);
            Vector2 end   = transform.InverseTransformPoint(laser.origin + laser.direction * Laser.LASER_DISTANCE);

            SlicePoint[] slicePoints = new SlicePoint[2];
            Vector2[]    vertices    = _collider.points;
            int          foundPoints = 0;
            for (int i = 0; i < vertices.Length && foundPoints <= 2; ++i)
            {
                //Calculate intersectionPoint
                //For formula see http://en.wikipedia.org/wiki/Line-line_intersection
                //I'm using x1, x2, ... since that's easier to write.
                float   x1 = start.x, x2 = end.x, x3 = vertices[i].x, x4 = vertices[(i + 1) % vertices.Length].x;
                float   y1 = start.y, y2 = end.y, y3 = vertices[i].y, y4 = vertices[(i + 1) % vertices.Length].y;
                Vector2 intersectionPoint = new Vector2(
                    (((x1 * y2 - y1 * x2) * (x3 - x4)) - ((x1 - x2) * (x3 * y4 - y3 * x4))) / (((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))),
                    (((x1 * y2 - y1 * x2) * (y3 - y4)) - ((y1 - y2) * (x3 * y4 - y3 * x4))) / (((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4)))
                    );

                //See if the point is is actually on the side & laser.

                float startx = Mathf.Min(vertices[i].x, vertices[(i + 1) % vertices.Length].x);              //side
                float endx   = Mathf.Max(vertices[i].x, vertices[(i + 1) % vertices.Length].x);
                float starty = Mathf.Min(vertices[i].y, vertices[(i + 1) % vertices.Length].y);
                float endy   = Mathf.Max(vertices[i].y, vertices[(i + 1) % vertices.Length].y);

                float start2x = Mathf.Min(start.x, end.x);                 //laser
                float end2x   = Mathf.Max(start.x, end.x);
                float start2y = Mathf.Min(start.y, end.y);
                float end2y   = Mathf.Max(start.y, end.y);
                if (intersectionPoint.x >= startx && intersectionPoint.x < endx && intersectionPoint.y >= starty && intersectionPoint.y < endy &&
                    intersectionPoint.x >= start2x && intersectionPoint.x < end2x && intersectionPoint.y >= start2y && intersectionPoint.y < end2y)
                {
                    //Add to the slicePoints vector if you find anything
                    // throws when too many points were found
                    slicePoints[foundPoints] = new SlicePoint(intersectionPoint, i);
                    ++foundPoints;
                }
            }

            if (foundPoints != 2)
            {
                throw new UnityException("Wrong number of points found while slicing: " + foundPoints);
            }

            //Calculate the number of sides each part of the rock will have
            int numberOfPoints1 = Mathf.Abs(slicePoints[0].side - slicePoints[1].side);
            int numberOfPoints2 = vertices.Length - numberOfPoints1;
            //numberOfPoints1 = min(numberOfPoints1, b2_maxPolygonVertices-2); //Make sure there aren't too many vertexes (Box2D 'limitation')
            //numberOfPoints2 = min(numberOfPoints2, b2_maxPolygonVertices-2); //I raised the max Polygon verts to 16 (default 8) so it will almost never happen, though when it does it's almost invisible
            //Create vectors to save the sides of each new rock
            Vector2[] sides1 = new Vector2[numberOfPoints1 + 2];
            Vector2[] sides2 = new Vector2[numberOfPoints2 + 2];

            //Filling in the first vector
            int counter = slicePoints[0].side + 1;
            for (var i = 0; i < numberOfPoints1; ++i)
            {
                if (counter >= vertices.Length)
                {
                    throw new UnityException("Whoops, something wrong with the slicing. Should never happen, please report this.");                     //Should never go over 0
                }
                sides1[i] = vertices[counter];
                ++counter;
            }
            //Lastly add the intersection points to the sides1.
            sides1[numberOfPoints1 + 0] = slicePoints[1].point;             //Since I add them to the back the second one found will always be the first one here.
            sides1[numberOfPoints1 + 1] = slicePoints[0].point;

            //Filling in the second one
            for (var i = 0; i < numberOfPoints2; ++i)
            {
                counter   = counter % vertices.Length;
                sides2[i] = vertices[counter];
                ++counter;
            }
            sides2[numberOfPoints2 + 0] = slicePoints[0].point;
            sides2[numberOfPoints2 + 1] = slicePoints[1].point;

            //Check if both new polygons are valid. Their size & winding will be checked, also they have to be convex.
            if (GetArea(sides1) < MINIMUM_AREA || GetArea(sides2) < MINIMUM_AREA)
            {
                throw new UnityException("At least one of the new planetoids is too small, not slicing for performance reasons.");
            }

            //Get some values needed to set later.
            Vector2 linVel   = _rigidbody.velocity;
            float   angleVel = _rigidbody.angularVelocity;
            Vector2 dir      = laser.direction;
            Vector2 lr       = new Vector2(-dir.y, dir.x);
            lr.Normalize();
            lr *= laserPower;

            //Change this rock.
            Initialize(sides1, manager);

            //Make the other part.
            Planetoid newRock = manager.GetNewOrCashedPlanetoid();
            newRock.Initialize(sides2, manager);
            newRock.transform.position         = transform.position;
            newRock.transform.rotation         = transform.rotation;
            newRock._rigidbody.velocity        = linVel;
            newRock._rigidbody.angularVelocity = angleVel;
            newRock._density = _density;

            //Set Velocities.
            _rigidbody.AddForce(lr, ForceMode2D.Impulse);
            newRock._rigidbody.AddForce(-lr, ForceMode2D.Impulse);

            return(newRock);
        }
        catch (UnityException ex) {
            Debug.Log("Failed slicing: " + ex.Message);
            return(null);
        }
        catch {
            Debug.Log("Failed slicing for an unknown reason");
            return(null);
        }
    }
        public void Slice(DynamicRenderMesh mesh, Camera camera)
        {
            slicePointsDictionary.Clear();
            verticesDictionary.Clear();
            slicePoints.Clear();
            vertices.Clear();
            texCoords.Clear();
            indices.Clear();
            triangles.Clear();
            ResultMeshes.Clear();

            FillVertices(mesh, camera);
            Vector2 A = new Vector2(99999.0f, 99999.0f), B = new Vector2(-99999.0f, -99999.0f);
            var tempLine = new Line2d();
            var workedIndices = new List<int>();
            var tempIndices = new List<int>();
            foreach (var line in Lines)
            {
                for (var i = 0; i < 2; i++)
                {
                    if (line.A[i] < A[i])
                        A[i] = line.A[i];
                    if (line.B[i] > B[i])
                        B[i] = line.B[i];
                }
            }
            for (var i = 0; i < indices.Count / 3; i++)
            {
                var index = i * 3;
                var point0 = vertices[indices[index]];
                var point1 = vertices[indices[index + 1]];
                var point2 = vertices[indices[index + 2]];

                if (!CheckAABB(ref point0, ref point1, ref point2, ref A, ref B))
                {
                    for (var j = 0; j < 3; j++)
                        tempIndices.Add(indices[index + j]);
                    continue;
                }

                for (var j = 0; j < 3; j++)
                    workedIndices.Add(indices[index + j]);
            }

            if (workedIndices.Count == 0)
                return;

            var triangle = new Vector3[3];
            var triangleT = new Vector2[3];
            var tempCollisions = new List<Vector3>();
            var tempTexCoords = new List<Vector2>();
            var tempCollisionsEdgeIndices = new List<int>();
            var newTriangles = new List<int>();
            var info0 = CollisionInfo.Zero;
            var info1 = CollisionInfo.Zero;

            for (var i = 0; i < sliceLines.Count; i++)
            {
                var line = Lines[i];
                var sliceLine = sliceLines[i];
                var trianglesCount = workedIndices.Count / 3;
                for (var j = 0; j < trianglesCount; j++)
                {
                    var index = j * 3;
                    for (var l = 0; l < 3; l++)
                    {
                        triangle[l] = vertices[workedIndices[index + l]];
                        triangleT[l] = texCoords[workedIndices[index + l]];
                    }

                    info0 = CollisionInfo.Zero;
                    info1 = CollisionInfo.Zero;
                    tempCollisions.Clear();
                    tempTexCoords.Clear();
                    tempCollisionsEdgeIndices.Clear();
                    newTriangles.Clear();
                    //looking for a point / intersection point of the triangle and line
                    for (int k = 0, l = 2; k < 3; l = k, k++)
                    {
                        if (info1.Type != CollisionType.CT_NONE)
                            break;
                        var tPoint0 = triangle[l];
                        var tPoint1 = triangle[k];

                        var tTexCoord0 = triangleT[l];
                        var tTexCoord1 = triangleT[k];

                        tempLine.Point0.X = tPoint0.X;
                        tempLine.Point0.Y = tPoint0.Y;
                        tempLine.Point1.X = tPoint1.X;
                        tempLine.Point1.Y = tPoint1.Y;

                        float ua, ub;
                        if (!GetUaUb(tempLine, line, out ua, out ub))
                        {
                            //lines coincide?
                            //Verify whether some point belongs line segment tempLine
                            //if find - get result and break.
                        }
                        else
                        {
                            if (ub < 0.0f || ub > 1.0f)
                                continue;
                            var collisionPoint = tPoint0 + (tPoint1 - tPoint0) * ub;
                            var collisionTexCoord = tTexCoord0 + (tTexCoord1 - tTexCoord0) * ub;
                            if (tempCollisions.Count == 0 || !PointsCompare.Equals(tempCollisions[0], collisionPoint))
                            {
                                tempCollisions.Add(collisionPoint);
                                tempTexCoords.Add(collisionTexCoord);
                                tempCollisionsEdgeIndices.Add(l);
                            }
                            if (ua < 0.0f || ua > 1.0f)
                                continue;

                            var pointType = CollisionType.CT_VERTEX;
                            Vector3 point;
                            Vector2 texCoord;
                            var pointIndex = -1;
                            var edgeIndex = -1;

                            if (ub > 0.0f)
                            {
                                if (ub < 1.0f)
                                {
                                    pointType = CollisionType.CT_EDGE;
                                    point = tempCollisions.Last();
                                    texCoord = tempTexCoords.Last();
                                    edgeIndex = l;
                                }
                                else
                                {
                                    point = tPoint1;
                                    texCoord = tTexCoord1;
                                    pointIndex = workedIndices[index + k];
                                }
                            }
                            else
                            {
                                point = tPoint0;
                                texCoord = tTexCoord0;
                                pointIndex = workedIndices[index + l];
                            }
                            if (info0.Type == CollisionType.CT_NONE)
                            {
                                info0.PointIndex = pointIndex;
                                info0.Type = pointType;
                                info0.Position = point;
                                info0.TexCoord = texCoord;
                                info0.EdgeIndex = edgeIndex;
                            }
                            else
                            {
                                if (pointIndex == -1 || info0.PointIndex != pointIndex)
                                {
                                    info1.PointIndex = pointIndex;
                                    info1.Type = pointType;
                                    info1.Position = point;
                                    info1.TexCoord = texCoord;
                                    info1.EdgeIndex = edgeIndex;
                                }
                            }
                        }
                    }

                    if (info1.Type == CollisionType.CT_NONE)
                    {
                        if (tempCollisions.Count == 0)
                        {
                            if (info0.Type == CollisionType.CT_NONE)
                                continue;
                        }
                        else
                        {
                            if (tempCollisions.Count > 1)
                            {
                                //Perhaps the point inside the triangle
                                var dir = line.Direction;
                                for (var l = 0; l < 2; l++)
                                {
                                    var p = l == 0 ? line.Point0 : line.Point1;
                                    if (PointInTriangle(ref triangle[0], ref triangle[1], ref triangle[2], ref p))
                                    {
                                        var v0 = tempCollisions[1].Xy - tempCollisions[0].Xy;
                                        var v1 = p - tempCollisions[0].Xy;
                                        var k = (v1.Length / v0.Length);
                                        var z = tempCollisions[0].Z + (tempCollisions[1].Z - tempCollisions[0].Z) * k;
                                        var t = tempTexCoords[0] + (tempTexCoords[1] - tempTexCoords[0]) * k;
                                        if (info0.Type == CollisionType.CT_NONE)
                                        {
                                            info0.Type = CollisionType.CT_INSIDE;
                                            info0.Position = new Vector3(p.X, p.Y, z);
                                            info0.TexCoord = t;
                                            if (Vector2.Dot(dir, v0) > 0.0f)
                                                info0.EdgeIndex = tempCollisionsEdgeIndices[0];
                                            else
                                                info0.EdgeIndex = tempCollisionsEdgeIndices[1];
                                            tempCollisionsEdgeIndices.Remove(info0.EdgeIndex);
                                        }
                                        else
                                        {
                                            info1.Type = CollisionType.CT_INSIDE;
                                            info1.Position = new Vector3(p.X, p.Y, z);
                                            info1.TexCoord = t;
                                            info1.EdgeIndex = tempCollisionsEdgeIndices[0];
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (info0.Type == CollisionType.CT_NONE)
                        continue;
                    //Create new triangles, if we have two points of intersection, and they are not vertices
                    int pi1 = 0, pi0 = 0;
                    if (info1.Type != CollisionType.CT_NONE && (info0.Type != CollisionType.CT_VERTEX || info1.Type != CollisionType.CT_VERTEX ))
                    {
                        if (info1.Type == CollisionType.CT_VERTEX
                            || (info1.Type == CollisionType.CT_EDGE && info0.Type == CollisionType.CT_INSIDE)
                            || (info1.Type == CollisionType.CT_EDGE && info0.Type == CollisionType.CT_EDGE && (info0.EdgeIndex + 1) % 3 != info1.EdgeIndex)
                            || (info0.Type == CollisionType.CT_INSIDE && info1.Type == CollisionType.CT_INSIDE && (info0.EdgeIndex + 1) % 3 != info1.EdgeIndex))
                        {
                            var temp = info1;
                            info1 = info0;
                            info0 = temp;
                        }

                        if (!verticesDictionary.TryGetValue(info1.Position, out pi1))
                        {
                            pi1 = vertices.Count;
                            vertices.Add(info1.Position);
                            texCoords.Add(info1.TexCoord);
                            verticesDictionary.Add(info1.Position, pi1);
                        }

                        if (info0.Type == CollisionType.CT_VERTEX) //One point of intersection coincides with the vertex
                        {
                            pi0 = info0.PointIndex;
                            int i0 = workedIndices[index], i1 = workedIndices[index + 1], i2 = workedIndices[index + 2];
                            if (i0 == info0.PointIndex)
                            {
                                i0 = i2;
                                i2 = i1;
                            }
                            else
                            {
                                if (i2 == info0.PointIndex)
                                {
                                    i2 = i0;
                                    i0 = i1;
                                }
                            }
                            i1 = info0.PointIndex;

                            newTriangles.AddRange(new[] {   i0, i1, pi1,
                                                            i1, i2, pi1 });
                            if (info1.Type == CollisionType.CT_INSIDE) //The second point inside the triangle
                                newTriangles.AddRange(new[] { i2, i0, pi1 });
                        }
                        else
                        {
                            if (!verticesDictionary.TryGetValue(info0.Position, out pi0))
                            {
                                pi0 = vertices.Count;
                                vertices.Add(info0.Position);
                                texCoords.Add(info0.TexCoord);
                                verticesDictionary.Add(info0.Position, pi0);
                            }

                            if (info1.Type != info0.Type) //One point crosses the brink, the second inside the triangle
                            {
                                var prev = info0.EdgeIndex == 0 ? 2 : info0.EdgeIndex - 1;
                                prev = workedIndices[index + prev];
                                var next = info0.EdgeIndex == 2 ? 0 : info0.EdgeIndex + 1;
                                next = workedIndices[index + next];
                                var curr = workedIndices[index + info0.EdgeIndex];
                                newTriangles.AddRange(new[] {   prev, curr, pi1,
                                                                curr, pi0, pi1,
                                                                pi0, next, pi1,
                                                                next, prev, pi1 });
                            }
                            else
                            {
                                var c0 = workedIndices[index + info0.EdgeIndex];
                                var c1 = workedIndices[index + info1.EdgeIndex];
                                var c2 = workedIndices[index + ((info1.EdgeIndex + 1) % 3)];

                                if (info0.Type == CollisionType.CT_EDGE)
                                {
                                    newTriangles.AddRange(new[] {   c0, pi0, pi1,
                                                                pi0, c1, pi1,
                                                                pi1, c2, c0 });
                                }
                                else
                                {
                                    newTriangles.AddRange(new[] {   c0, c1, pi0,
                                                                    c1, pi1, pi0,
                                                                    c1, c2, pi1,
                                                                    c2, c0, pi1,
                                                                    c0, pi0, pi1});

                                }
                            }
                        }
                    }
                    int slicePointIndex;
                    SlicePoint slicePoint;
                    for (var l = 0; l < 2; l++)
                    {
                        if (l == 1 && info1.Type == CollisionType.CT_NONE)
                            break;
                        var position = l == 0 ? info0.Position.Xy : info1.Position.Xy;
                        var pointIndex = l == 0 ? pi0 : pi1;
                        if (!slicePointsDictionary.TryGetValue(position, out slicePointIndex))
                        {
                            slicePoint = new SlicePoint
                            {
                                Coordinate = position
                            };
                            slicePoint.Lines.Add(sliceLine);
                            slicePoint.PreparePoint();
                            slicePointIndex = slicePoints.Count;
                            slicePoints.Add(slicePoint);
                            slicePointsDictionary.Add(position, slicePointIndex);
                        }
                        else
                            slicePoint = slicePoints[slicePointIndex];
                        if (!slicePoint.Indices.Contains(pointIndex))
                            slicePoint.Indices.Add(pointIndex);
                    }

                    if (newTriangles.Count > 0)
                    {
                        for (var l = 0; l < 3; l++)
                            workedIndices[index + l] = newTriangles[l];
                        newTriangles.RemoveRange(0, 3);
                        workedIndices.InsertRange(index, newTriangles);
                        var count = (newTriangles.Count / 3);
                        j += count;
                        trianglesCount += count;
                    }
                }
            }

            for (var i = 0; i < workedIndices.Count / 3; i++)
            {
                var index = i * 3;
                var t = new Triangle();
                for (var j = 0; j < 3; j++)
                    t.Indices[j] = workedIndices[index + j];
                triangles.Add(i, new TrianleConnections
                {
                    Triangle = t
                });
            }

            var ind = new List<int>();
            var tempTriangle = new Triangle();
            tempTriangle.Indices[1] = -1;
            foreach (var point in slicePoints)
            {
                point.PreparePoint();
                foreach (var index in point.Indices)
                {
                    ind.Clear();
                    ind.Add(index);
                    tempTriangle.Indices[0] = index;
                    //Duplicate the verticle several times
                    for (var i = 1; i < point.Directions.Count; i++)
                    {
                        ind.Add(vertices.Count);
                        vertices.Add(vertices[index]);
                        texCoords.Add(texCoords[index]);
                    }
                    foreach (var t in triangles)
                    {
                        var tr = t.Value.Triangle;
                        var id = Triangle.TriangleEquals(ref tempTriangle, ref tr);
                        if (id > -1)
                        {
                            var center = (vertices[tr.Indices[0]].Xy + vertices[tr.Indices[1]].Xy + vertices[tr.Indices[2]].Xy) / 3.0f;
                            var dir = (center - point.Coordinate).Normalized();
                            var angle = SlicePoint.GetAngle(ref dir);
                            var ii = point.Directions.Count - 1;
                            for (var j = 0; j < point.Directions.Count; j++)
                            {
                                if (angle < point.Directions[j])
                                    break;
                                ii = j;
                            }
                            tr.Indices[id] = ind[ii];
                        }
                    }
                }
            }

            var invTransform = mesh.Transform * camera.ViewMatrix;
            invTransform.Invert();
            for (var i = 0; i < vertices.Count; i++)
            {
                vertices[i] = Vector3.Transform(vertices[i], invTransform);
            }

            workedIndices.Clear();

            foreach (var t in triangles)
            {
                foreach (var i in t.Value.Triangle.Indices)
                    workedIndices.Add(i);
            }
            workedIndices.AddRange(tempIndices);
            triangleConnections.Clear();
            triangles.Clear();

            for (var i = 0; i < workedIndices.Count / 3; i++)
            {
                var index = i * 3;
                var t = new Triangle();
                for (var j = 0; j < 3; j++)
                {
                    t.Indices[j] = workedIndices[index + j];
                    List<int> l;
                    if (!triangleConnections.TryGetValue(t.Indices[j], out l))
                    {
                        l = new List<int>();
                        triangleConnections.Add(t.Indices[j], l);
                    }
                    l.Add(i);
                }
                triangles.Add(i, new TrianleConnections
                {
                    Triangle = t
                });
            }

            var mainMesh = true;
            while (triangles.Count > 0)
            {
                foundedTriangles.Clear();
                FillTriangles(triangles.First().Key);

                if (mainMesh)
                {
                    mesh.Create(vertices, texCoords, foundedTriangles, mesh.Material.DiffuseTextureMap, mesh.Material.TransparentTextureMap, mesh.TextureAngle, mesh.TextureSize);
                    mainMesh = false;
                }
                else
                {
                    var tmpMesh = new DynamicRenderMesh(MeshType.Hair);
                    tmpMesh.Create(vertices, texCoords, foundedTriangles, mesh.Material.DiffuseTextureMap, mesh.Material.TransparentTextureMap, mesh.TextureAngle, mesh.TextureSize);
                    tmpMesh.Transform = mesh.Transform;
                    tmpMesh.Material.DiffuseColor = mesh.Material.DiffuseColor;
                    tmpMesh.MeshAngle = mesh.MeshAngle;
                    tmpMesh.MeshSize = mesh.MeshSize;

                    var info = tmpMesh.GetMeshInfo(1.0f);
                    var center = Vector3.Zero;
                    var scale = PickingController.GetHairScale(ProgramCore.Project.ManType);
                    foreach (var vert in info.Positions)
                    {
                        center.X += vert.X * scale;
                        center.Y += vert.Y * scale;
                        center.Z += vert.Z * scale;
                    }
                    center /= info.Positions.Count;
                    tmpMesh.Position = center;

                    ResultMeshes.Add(tmpMesh);
                }
            }
        }