Пример #1
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);
                }
            }
        }
        /// <summary> Initialize control and setup GL settings </summary>
        public void Initialize()
        {
            loaded = true;
            PlayAnimation = false;
            pickingController = new PickingController(camera);

            idleShader = new ShaderController("idle.vs", "idle.fs");
            idleShader.SetUniformLocation("u_UseTexture");
            idleShader.SetUniformLocation("u_Color");
            idleShader.SetUniformLocation("u_Texture");
            idleShader.SetUniformLocation("u_BrushMap");
            idleShader.SetUniformLocation("u_TransparentMap");
            idleShader.SetUniformLocation("u_World");
            idleShader.SetUniformLocation("u_WorldView");
            idleShader.SetUniformLocation("u_ViewProjection");
            idleShader.SetUniformLocation("u_LightDirection");

            blendShader = new ShaderController(ProgramCore.PluginMode ? "blendingPl.vs" : "blending.vs", "blending.fs");
            blendShader.SetUniformLocation("u_Texture");
            blendShader.SetUniformLocation("u_BlendStartDepth");
            blendShader.SetUniformLocation("u_BlendDepth");

            brushShader = new ShaderController("brush.vs", "brush.fs");
            brushShader.SetUniformLocation("u_Texture");
            brushShader.SetUniformLocation("u_World");
            brushShader.SetUniformLocation("u_BrushColor");
            brushShader.SetUniformLocation("u_SphereCenter");
            brushShader.SetUniformLocation("u_SphereRadius");

            SetupViewport(glControl);

            windowInfo = Utilities.CreateWindowsWindowInfo(renderPanel.Handle);
            graphicsContext = new GraphicsContext(GraphicsMode.Default, windowInfo);
            renderPanel.Resize += (sender, args) => graphicsContext.Update(windowInfo);
            glControl.Context.MakeCurrent(glControl.WindowInfo);

            InitializeProfileSprites();
            InitializeCustomBaseSprites();
        }