// fatten edge into a tube-like section
        public static Section Tubify(Edge pts, float wid)
        {
            Edge edge0 = new Edge();
            Edge edge1 = new Edge();

            for (int i = 1; i < pts.Count - 1; i++)
            {
                float w  = wid;
                float a1 = Mathf.Atan2(pts[i].y - pts[i - 1].y, pts[i].x - pts[i - 1].x);
                float a2 = Mathf.Atan2(pts[i].y - pts[i + 1].y, pts[i].x - pts[i + 1].x);
                float a  = (a1 + a2) / 2;
                if (a < a2)
                {
                    a += Mathf.PI;
                }
                edge0.Add(new Vector2(pts[i].x + w * Mathf.Cos(a), (pts[i].y + w * Mathf.Sin(a))));
                edge1.Add(new Vector2(pts[i].x - w * Mathf.Cos(a), (pts[i].y - w * Mathf.Sin(a))));
            }
            if (pts.Count >= 2)
            {
                int   l  = pts.Count - 1;
                float a3 = Mathf.Atan2(pts [1].y - pts [0].y, pts [1].x - pts [0].x) - Mathf.PI / 2;
                float a4 = Mathf.Atan2(pts [l].y - pts [l - 1].y, pts [l].x - pts [l - 1].x) - Mathf.PI / 2;
                float w0 = wid;
                float w1 = wid;
                edge0.Insert(0, new Vector2(pts [0].x + w0 * Mathf.Cos(a3), (pts [0].y + w0 * Mathf.Sin(a3))));
                edge1.Insert(0, new Vector2(pts [0].x - w0 * Mathf.Cos(a3), (pts [0].y - w0 * Mathf.Sin(a3))));
                edge0.Add(new Vector2(pts [l] [0] + w1 * Mathf.Cos(a4), (pts [l] [1] + w1 * Mathf.Sin(a4))));
                edge1.Add(new Vector2(pts [l] [0] - w1 * Mathf.Cos(a4), (pts [l] [1] - w1 * Mathf.Sin(a4))));
            }
            edge0.Reverse();
            return(new Section(new Edge[] { edge0, edge1 }));
        }
示例#2
0
        /// <summary>
        /// Tries to create edge with given adpositions
        /// </summary>
        /// <param name="left">Left vertex</param>
        /// <param name="right">Right vertex</param>
        /// <param name="adpositions">Adposition list</param>
        /// <param name="isRightSubject">Flag if right is subject</param>
        /// <returns>Edge if exists for given adpositions. Else null.</returns>
        private Edge Create(IDrawable left, IDrawable right, List <string> adpositions, bool isRightSubject)
        {
            Edge edge = GetEdge(string.Join(" ", adpositions).ToLower());

            if (edge == null)
            {
                return(null);
            }

            if (isRightSubject)
            {
                edge.Add(right, left);
            }
            else
            {
                edge.Add(left, right);
            }

            return(edge);
        }
示例#3
0
 /// <summary>
 /// ワーシャルフロイド法
 /// O(N^3)
 /// </summary>
 /// <param name="edge">Edgeオブジェクト</param>
 /// <param name="nodeNum">ノードの数</param>
 /// <returns>各ノード間の最短距離を辺として持つEdgeオブジェクト</returns>
 public static Edge WarshallFloyd (Edge edge) {
     var res = new Edge (edge);
     foreach (var b in Enumerable.Range (0, edge.NodeNum)) {
         foreach (var a in Enumerable.Range (0, edge.NodeNum)) {
             foreach (var c in Enumerable.Range (0, edge.NodeNum)) {
                 res.Add (a, c, Min (res.GetLength (a, c), res.GetLength (a, b) + res.GetLength (b, c)));
             }
         }
     }
     return res;
 }
示例#4
0
        public static void Main(string[] args)
        {
            var NM   = ReadInts();
            var N    = NM[0];
            var M    = NM[1];
            var ab   = ReadIntColumns(M);
            var a    = ab[0];
            var b    = ab[1];
            var edge = new Edge(N, -1);

            foreach (var m in Enumerable.Range(0, M))
            {
                edge.Add(a[m] - 1, b[m] - 1, 1);
                edge.Add(b[m] - 1, a[m] - 1, 1);
            }

            var count = Enumerable.Range(1, N - 1).Perm(N - 1).Where(perm =>
                                                                     perm.Prepend(0).Aggregate(0, (accm, i) => accm == -1 || edge.GetLength(accm, i) == -1 ? -1 : i) != -1)
                        .Count();

            Print(count);
        }
        // shrink toward center by a factor
        public static Section Shrink(Section section, float p)
        {
            Section nsection = new Section();
            Vector2 c        = PolyTool.Centroid(ToPoly(section));

            //Debug.Log (c);
            for (int i = 0; i < section.Count; i++)
            {
                Edge nedge = new Edge();
                for (int j = 0; j < section[i].Count; j++)
                {
                    Vector2 pt  = section [i] [j];
                    Vector2 npt = Vector2.Lerp(pt, c, p);
                    nedge.Add(npt);
                }
                nsection.Add(nedge);
            }
            return(nsection);
        }
        // rotate around center by angle
        public static Section Rotate(Section section, Vector2 center, float angle)
        {
            Section nsection = new Section();

            for (int i = 0; i < section.Count; i++)
            {
                Edge nedge = new Edge();
                for (int j = 0; j < section[i].Count; j++)
                {
                    Vector2 pt   = section [i] [j];
                    float   ang  = Mathf.Atan2(pt.y - center.y, pt.x - center.x);
                    float   dist = Vector2.Distance(center, pt);
                    ang += angle;
                    Vector2 npt = new Vector2(center.x + dist * Mathf.Cos(ang),
                                              center.y + dist * Mathf.Sin(ang));
                    nedge.Add(npt);
                }
                nsection.Add(nedge);
            }
            return(nsection);
        }
示例#7
0
        public void AddsARoadToAnEdge()
        {
            var node1 = new Node();
            var node2 = new Node();
            var node3 = new Node();
            var edge1 = new Edge(node1, node2);
            var edge2 = new Edge(node2, node3);
            var road = new Road();
            edge1.Add(road);
            var context = CreateContext(
                edge2,
                new Dictionary<Node, IEnumerable<Edge>>
                    {
                        {node1, new[] {edge1}},
                        {node2, new[] {edge1, edge2}},
                        {node3, new[] {edge2}}
                    });
            context.Player.Roads.Add(road);

            new PlaceRoad().Execute(context);

            Assert.Equal(context.Player.Roads[1], edge2.Get<Road>());
        }
        // split a list of sections into smaller sections
        public static List <Section> SplitAll(List <Section> sections, out List <Edge> edges)
        {
            edges = new List <Edge> ();
            List <Section> nsections = new List <Section> ();

            for (int i = 0; i < sections.Count; i++)
            {
                int   s1      = 0;
                int   s2      = 0;
                float maxlen1 = 0;
                float maxlen2 = 0;
                float minlen  = float.PositiveInfinity;

                for (int j = 0; j < sections[i].Count; j++)
                {
                    float l = EdgeTool.EstLen(sections [i] [j]);
                    if (l > maxlen1)
                    {
                        s1      = j;
                        maxlen1 = l;
                    }
                    else if (l > maxlen2)
                    {
                        s2      = j;
                        maxlen2 = l;
                    }
                    if (l < minlen)
                    {
                        minlen = l;
                    }
                }

                if (EstArea(sections[i]) < 100 || minlen < 5)
                {
                    nsections.Add(sections [i]);
                    continue;
                }

                if (s2 < s1)
                {
                    int temp = s2;
                    s2 = s1;
                    s1 = temp;
                }

                Edge e1   = sections [i] [s1];
                Edge e2   = sections [i] [s2];
                int  mid1 = (int)Mathf.Floor(e1.Count / 2);
                int  mid2 = (int)Mathf.Floor(e2.Count / 2);

                Vector2 p1 = Vector2.Lerp(e1[mid1], e1[(mid1 + 1) % e1.Count], 0.5f);
                Vector2 p2 = Vector2.Lerp(e2[mid2], e2[(mid2 + 1) % e2.Count], 0.5f);

                Edge e11 = e1.GetRange(0, mid1);
                Edge e12 = e1.GetRange(mid1 + 1, e1.Count - mid1 - 1);
                Edge e21 = e2.GetRange(0, mid2);
                Edge e22 = e2.GetRange(mid2 + 1, e2.Count - mid2 - 1);

                e11.Add(p1);
                e12.Insert(0, p1);
                e21.Add(p2);
                e22.Insert(0, p2);

                //Edge en1 = new List<Vector2>(new Vector2[]{p1,p2});
                Edge en1 = EdgeTool.MakeCurve(p1, p2);
                edges.Add(en1);
                Edge en2 = new List <Vector2> ();
                en2.AddRange(en1);
                en2.Reverse();

                int len = sections [i].Count;

                Section left = new Section();

                left.Add(en2);
                left.Add(e12);
                left.AddRange(sections [i].GetRange((s1 + 1) % len, s2 - s1 - 1));
                left.Add(e21);

                Section right = new Section();
                right.Add(en1);
                right.Add(e22);
                right.AddRange(sections [i].GetRange((s2 + 1) % len, len - (s2 + 1)));
                right.AddRange(sections [i].GetRange(0, s1));
                right.Add(e11);

                Clean(left);
                Clean(right);

                nsections.Add(left);
                nsections.Add(right);
            }
            return(nsections);
        }
示例#9
0
        public void Append(KeyValuePair <string, string[]> edge_vertex)
        {
            string edge    = edge_vertex.Key;
            string vertex1 = edge_vertex.Value[0];
            string vertex2 = edge_vertex.Value[1];

            if (dic_vertex_tree.ContainsKey(vertex1) && dic_vertex_tree.ContainsKey(vertex2))
            {
                string tree1 = dic_vertex_tree[vertex1];
                string tree2 = dic_vertex_tree[vertex2];
                if (tree1 == tree2)
                {
                    this[tree1].m_Edge_Vertex.Add(edge_vertex.Key, edge_vertex.Value);
                    this[tree1][vertex1].Add(edge);
                    this[tree1][vertex2].Add(edge);
                    dic_edge_tree.Add(edge, tree1);
                }
                else
                {
                    Merge(tree1, tree2, vertex1, vertex2, edge);
                }
            }
            else if (dic_vertex_tree.ContainsKey(vertex1))
            {
                string tree = dic_vertex_tree[vertex1];
                this[tree][vertex1].Add(edge);
                Edge edge_new = new Edge();
                edge_new.Add(edge);
                this[tree].Add(vertex2, edge_new);
                if (string.Compare(vertex2, this[tree].m_First_Vertex) < 0)
                {
                    this[tree].m_First_Vertex = vertex2;
                }
                dic_vertex_tree.Add(vertex2, tree);
                dic_edge_tree.Add(edge, tree);
                this[tree].m_Edge_Vertex.Add(edge, edge_vertex.Value);
            }
            else if (dic_vertex_tree.ContainsKey(vertex2))
            {
                string tree = dic_vertex_tree[vertex2];
                this[tree][vertex2].Add(edge);
                Edge edge_new = new Edge();
                edge_new.Add(edge);
                this[tree].Add(vertex1, edge_new);
                if (string.Compare(vertex1, this[tree].m_First_Vertex) < 0)
                {
                    this[tree].m_First_Vertex = vertex1;
                }
                dic_vertex_tree.Add(vertex1, tree);
                dic_edge_tree.Add(edge, tree);
                this[tree].m_Edge_Vertex.Add(edge, edge_vertex.Value);
            }
            else
            {
                string tree_id = tree_count;
                Tree   tree    = new Tree();
                tree.m_Tree_ID = tree_id;
                if (string.Compare(vertex1, vertex2) > 0)
                {
                    tree.m_First_Vertex = vertex2;
                }
                else
                {
                    tree.m_First_Vertex = vertex1;
                }
                Edge edge1_new = new Edge();
                Edge edge2_new = new Edge();
                edge1_new.Add(edge);
                edge2_new.Add(edge);
                tree.Add(vertex1, edge1_new);
                tree.Add(vertex2, edge2_new);
                tree.m_Edge_Vertex.Add(edge_vertex.Key, edge_vertex.Value);
                dic_vertex_tree.Add(vertex1, tree_id);
                dic_vertex_tree.Add(vertex2, tree_id);
                dic_edge_tree.Add(edge, tree_id);
                Add(tree_id, tree);
                tree_count = Convert.ToString(Convert.ToInt32(tree_count) + 1);
            }
        }
示例#10
0
    public void FindPath(PathRequest request, Action <PathResult> callback)
    {
        Stopwatch sw = new Stopwatch();

        sw.Start();

        Vector3[] waypoints   = new Vector3[0];
        bool      pathSuccess = false;

        Node startNode  = grid.NodeFromWorldPoint(request.pathStart);
        Node targetNode = grid.NodeFromWorldPoint(request.pathEnd);

        startNode.parent = startNode;

        if (startNode.walkable && targetNode.walkable)
        {
            Edge <Node>    openSet   = new Edge <Node>(grid.MaxSize);
            HashSet <Node> closedSet = new HashSet <Node>();
            openSet.Add(startNode);

            while (openSet.Count > 0)
            {
                Node currentNode = openSet.RemoveFirst();
                closedSet.Add(currentNode);

                if (currentNode == targetNode)
                {
                    sw.Stop();
                    //print ("Path found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }

                foreach (Node neighbour in grid.GetNeighbours(currentNode))
                {
                    if (!neighbour.walkable || closedSet.Contains(neighbour))
                    {
                        continue;
                    }

                    int newCToN = currentNode.gCost + GetDistance(currentNode, neighbour) + neighbour.movementPenalty;
                    if (newCToN < neighbour.gCost || !openSet.Contains(neighbour))
                    {
                        neighbour.gCost  = newCToN;
                        neighbour.hCost  = GetDistance(neighbour, targetNode);
                        neighbour.parent = currentNode;

                        if (!openSet.Contains(neighbour))
                        {
                            openSet.Add(neighbour);
                        }
                        else
                        {
                            openSet.UpdateItem(neighbour);
                        }
                    }
                }
            }
        }
        if (pathSuccess)
        {
            waypoints   = RetracePath(startNode, targetNode);
            pathSuccess = waypoints.Length > 0;
        }
        callback(new PathResult(waypoints, pathSuccess, request.callback));
    }
示例#11
0
    protected bool CreateSide(Volume volume, bool partialBuild)
    {
        bool flat = TypeMask.HasFlag(VolumeFaceMask.Flat);

        SculptType  sculptStitching         = volume.Parameters.SculptType;
        SculptFlags sculptFlags             = volume.Parameters.SculptFlags;
        bool        sculptInvert            = sculptFlags.HasFlag(SculptFlags.Invert);
        bool        sculptMirror            = sculptFlags.HasFlag(SculptFlags.Mirror);
        bool        sculptReverseHorizontal = (sculptInvert ? !sculptMirror : sculptMirror);   // XOR

        int numVertices, numIndices;

        List <Vector3>        mesh     = volume.Points;
        List <Vector3>        profile  = volume.Profile.Points;
        List <Path.PathPoint> pathData = volume.Path.Points;

        int maxS = volume.Profile.PointCount;

        int   s, t, i;
        float ss, tt;

        numVertices = NumS * NumT;
        numIndices  = (NumS - 1) * (NumT - 1) * 6;

        // TODO: How does partial builds work?
        //partial_build = (num_vertices > NumVertices || num_indices > NumIndices) ? false : partial_build;

        //if (!partial_build)
        //{
        //	resizeVertices(num_vertices);
        //	resizeIndices(num_indices);

        //	if (!volume->isMeshAssetLoaded())
        //	{
        //		mEdge.resize(num_indices);
        //	}
        //}
        Positions.Clear();
        Normals.Clear();
        Indices.Clear();
        Edge.Clear();


        float beginStex = Mathf.Floor(profile[BeginS][2]);
        bool  test      = TypeMask.HasFlag(VolumeFaceMask.Inner | VolumeFaceMask.Flat) && NumS > 2;
        int   numS      = test ? NumS / 2 : NumS;

        int curVertex = 0;
        int endT      = BeginT + NumT;

        // Copy the vertices into the array
        for (t = BeginT; t < endT; t++)
        {
            tt = pathData[t].ExtrusionT;
            for (s = 0; s < numS; s++)
            {
                if (TypeMask.HasFlag(VolumeFaceMask.End))
                {
                    ss = s > 0 ? 1f : 0f;
                }
                else
                {
                    // Get s value for tex-coord.
                    if (!flat)
                    {
                        ss = profile[BeginS + s][2];
                    }
                    else
                    {
                        ss = profile[BeginS + s][2] - beginStex;
                    }
                }

                if (sculptReverseHorizontal)
                {
                    ss = 1f - ss;
                }

                // Check to see if this triangle wraps around the array.
                if (BeginS + s >= maxS)
                {
                    // We're wrapping
                    i = BeginS + s + maxS * (t - 1);
                }
                else
                {
                    i = BeginS + s + maxS * t;
                }

                Positions.Add(mesh[i]);
                Normals.Add(Vector3.zero);                  // This will be calculated later
                TexCoords.Add(new Vector2(ss, tt));

                curVertex++;

                if (test && s > 0)
                {
                    Positions.Add(mesh[i]);
                    Normals.Add(Vector3.zero); // This will be calculated later
                    TexCoords.Add(new Vector2(ss, tt));
                    curVertex++;
                }
            }

            if (test)
            {
                s = TypeMask.HasFlag(VolumeFaceMask.Open) ? numS - 1 : 0;

                i  = BeginS + s + maxS * t;
                ss = profile[BeginS + s][2] - beginStex;

                Positions.Add(mesh[i]);
                Normals.Add(Vector3.zero); // This will be calculated later
                TexCoords.Add(new Vector2(ss, tt));

                curVertex++;
            }
        }

        Centre = Vector3.zero;

        int curPos = 0;
        int endPos = Positions.Count;

        //get bounding box for this side
        Vector3 faceMin;
        Vector3 faceMax;

        faceMin = faceMax = Positions[curPos++];

        while (curPos < endPos)
        {
            UpdateMinMax(ref faceMin, ref faceMax, Positions[curPos++]);
        }
        // VFExtents change
        ExtentsMin = faceMin;
        ExtentsMax = faceMax;

        int tcCount = NumVertices;

        if (tcCount % 2 == 1)
        {         //odd number of texture coordinates, duplicate last entry to padded end of array
            tcCount++;
            TexCoords.Add(TexCoords[NumVertices - 1]);
        }

        int curTc = 0;
        int endTc = TexCoords.Count;

        Vector3 tcMin;
        Vector3 tcMax;

        tcMin = tcMax = TexCoords[curTc++];

        while (curTc < endTc)
        {
            UpdateMinMax(ref tcMin, ref tcMax, TexCoords[curTc++]);
        }

        //TODO: TexCoordExtents are weird this assumes Vector4
        //TexCoordExtentsMin.x = llmin(minp[0], minp[2]);
        //TexCoordExtentsMin.y = llmin(minp[1], minp[3]);
        //TexCoordExtentsMax.x = llmax(maxp[0], maxp[2]);
        //TexCoordExtentsMax.y = llmax(maxp[1], maxp[3]);

        Centre = (faceMin + faceMax) * 0.5f;

        bool flatFace = TypeMask.HasFlag(VolumeFaceMask.Flat); //(TypeMask & VolumeFaceMask.Flat) != 0;

        if (!partialBuild)
        {
            // Now we generate the indices.
            for (t = 0; t < (NumT - 1); t++)
            {
                for (s = 0; s < (NumS - 1); s++)
                {
                    Indices.Add(s + NumS * t);                                 //bottom left
                    Indices.Add(s + 1 + NumS * (t + 1));                       //top right
                    Indices.Add(s + NumS * (t + 1));                           //top left
                    Indices.Add(s + NumS * t);                                 //bottom left
                    Indices.Add(s + 1 + NumS * t);                             //bottom right
                    Indices.Add(s + 1 + NumS * (t + 1));                       //top right

                    Edge.Add((NumS - 1) * 2 * t + s * 2 + 1);                  //bottom left/top right neighbor face
                    if (t < NumT - 2)
                    {                                                          //top right/top left neighbor face
                        Edge.Add((NumS - 1) * 2 * (t + 1) + s * 2 + 1);
                    }
                    else if (NumT <= 3 || volume.Path.IsOpen == true)
                    {                     //no neighbor
                        Edge.Add(-1);
                    }
                    else
                    {                     //wrap on T
                        Edge.Add(s * 2 + 1);
                    }
                    if (s > 0)
                    {                                                                       //top left/bottom left neighbor face
                        Edge.Add((NumS - 1) * 2 * t + s * 2 - 1);
                    }
                    else if (flatFace || volume.Profile.IsOpen == true)
                    {                     //no neighbor
                        Edge.Add(-1);
                    }
                    else
                    {                       //wrap on S
                        Edge.Add((NumS - 1) * 2 * t + (NumS - 2) * 2 + 1);
                    }

                    if (t > 0)
                    {                                                                       //bottom left/bottom right neighbor face
                        Edge.Add((NumS - 1) * 2 * (t - 1) + s * 2);
                    }
                    else if (NumT <= 3 || volume.Path.IsOpen == true)
                    {                     //no neighbor
                        Edge.Add(-1);
                    }
                    else
                    {                     //wrap on T
                        Edge.Add((NumS - 1) * 2 * (NumT - 2) + s * 2);
                    }
                    if (s < NumS - 2)
                    {                                                                   //bottom right/top right neighbor face
                        Edge.Add((NumS - 1) * 2 * t + (s + 1) * 2);
                    }
                    else if (flatFace || volume.Profile.IsOpen == true)
                    {                     //no neighbor
                        Edge.Add(-1);
                    }
                    else
                    {                     //wrap on S
                        Edge.Add((NumS - 1) * 2 * t);
                    }
                    Edge.Add((NumS - 1) * 2 * t + s * 2);                                                 //top right/bottom left neighbor face
                }
            }
        }



        //      //clear normals
        //int dst = Normals.Count;
        //int end = dst + NumVertices;
        //Vector3 zero = Vector3.zero;

        //while (dst < end)
        //      {
        //          Normals.Add(zero);
        //	dst++;
        //}

        //generate normals

        // Compute triangle normals:
        int            count           = Indices.Count / 3;
        List <Vector3> triangleNormals = new List <Vector3>();
        int            idx             = 0;

        for (int triangleIndex = 0; triangleIndex < count; triangleIndex++)
        {
            Vector3 p0 = Positions[Indices[idx + 0]];
            Vector3 p1 = Positions[Indices[idx + 1]];
            Vector3 p2 = Positions[Indices[idx + 2]];

            //calculate triangle normal
            Vector3 a = p1 - p0;
            Vector3 b = p2 - p0;

            Vector3 normal = Vector3.Cross(a, b);

            if (Vector3.Dot(normal, normal) > 0.00001f)
            {
                normal.Normalize();
            }
            else
            {
                //degenerate, make up a value
                normal = normal.z >= 0 ? new Vector3(0f, 0f, 1f) : new Vector3(0f, 0f, -1f);
            }

            // This is probably an optimised way to calculate this:
            //LLQuad & vector1 = *((LLQuad*)&v1);
            //LLQuad & vector2 = *((LLQuad*)&v2);

            //LLQuad & amQ = *((LLQuad*)&a);
            //LLQuad & bmQ = *((LLQuad*)&b);

            // Vectors are stored in memory in w, z, y, x order from high to low
            // Set vector1 = { a[W], a[X], a[Z], a[Y] }
            //vector1 = _mm_shuffle_ps(amQ, amQ, _MM_SHUFFLE(3, 0, 2, 1));
            // Set vector2 = { b[W], b[Y], b[X], b[Z] }
            //vector2 = _mm_shuffle_ps(bmQ, bmQ, _MM_SHUFFLE(3, 1, 0, 2));
            // mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] }
            //vector2 = _mm_mul_ps(vector1, vector2);
            // vector3 = { a[W], a[Y], a[X], a[Z] }
            //amQ = _mm_shuffle_ps(amQ, amQ, _MM_SHUFFLE(3, 1, 0, 2));
            // vector4 = { b[W], b[X], b[Z], b[Y] }
            //bmQ = _mm_shuffle_ps(bmQ, bmQ, _MM_SHUFFLE(3, 0, 2, 1));
            // mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] }
            //vector1 = _mm_sub_ps(vector2, _mm_mul_ps(amQ, bmQ));

            //llassert(v1.isFinite3());

            triangleNormals.Add(normal);
            idx += 3;
        }

        // Add triangle normal contributions from each triangle to the vertex normals:
        idx = 0;
        for (int triangleIndex = 0; triangleIndex < count; triangleIndex++) //for each triangle
        {
            Vector3 c = triangleNormals[triangleIndex];

            Vector3 n0 = Normals[Indices[idx + 0]];
            Vector3 n1 = Normals[Indices[idx + 1]];
            Vector3 n2 = Normals[Indices[idx + 2]];

            n0 += c;
            n1 += c;
            n2 += c;

            //llassert(c.isFinite3());

            //even out quad contributions
            switch (triangleIndex % 2 + 1)
            {
            case 0: n0 += c; break;

            case 1: n1 += c; break;

            case 2: n2 += c; break;
            }
            ;

            Normals[Indices[idx + 0]] = n0;
            Normals[Indices[idx + 1]] = n1;
            Normals[Indices[idx + 2]] = n2;

            idx += 3;
        }

        // adjust normals based on wrapping and stitching

        Vector3 top = (Positions[0] - Positions[NumS * (NumT - 2)]);
        bool    s_bottom_converges = Vector3.Dot(top, top) < 0.000001f;

        top = Positions[NumS - 1] - Positions[NumS * (NumT - 2) + NumS - 1];
        bool s_top_converges = Vector3.Dot(top, top) < 0.000001f;

        if (sculptStitching == SculptType.None)          // logic for non-sculpt volumes
        {
            if (volume.Path.IsOpen == false)
            {             //wrap normals on T
                for (int j = 0; j < NumS; j++)
                {
                    Vector3 n = Normals[j] + Normals[NumS * (NumT - 1) + j];
                    Normals[j] = n;
                    Normals[NumS * (NumT - 1) + j] = n;
                }
            }

            if ((volume.Profile.IsOpen == false) && !(s_bottom_converges))
            {             //wrap normals on S
                for (int j = 0; j < NumT; j++)
                {
                    Vector3 n = Normals[NumS * j] + Normals[NumS * j + NumS - 1];
                    Normals[NumS * j]            = n;
                    Normals[NumS * j + NumS - 1] = n;
                }
            }

            if (volume.Parameters.PathParameters.PathType == PathType.Circle &&
                volume.Parameters.ProfileParameters.ProfileType == ProfileType.CircleHalf)
            {
                if (s_bottom_converges)
                {                 //all lower S have same normal
                    for (int j = 0; j < NumT; j++)
                    {
                        Normals[NumS * j] = new Vector3(1f, 0f, 0f);
                    }
                }

                if (s_top_converges)
                {                 //all upper S have same normal
                    for (int j = 0; j < NumT; j++)
                    {
                        Normals[NumS * j + NumS - 1] = new Vector3(-1f, 0f, 0f);
                    }
                }
            }
        }
        //else  // logic for sculpt volumes
        //{
        //BOOL average_poles = FALSE;
        //BOOL wrap_s = FALSE;
        //BOOL wrap_t = FALSE;

        //if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE)
        //	average_poles = TRUE;

        //if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) ||
        //	(sculpt_stitching == LL_SCULPT_TYPE_TORUS) ||
        //	(sculpt_stitching == LL_SCULPT_TYPE_CYLINDER))
        //	wrap_s = TRUE;

        //if (sculpt_stitching == LL_SCULPT_TYPE_TORUS)
        //	wrap_t = TRUE;


        //if (average_poles)
        //{
        //	// average normals for north pole

        //	LLVector4a average;
        //	average.clear();

        //	for (S32 i = 0; i < mNumS; i++)
        //	{
        //		average.add(norm[i]);
        //	}

        //	// set average
        //	for (S32 i = 0; i < mNumS; i++)
        //	{
        //		norm[i] = average;
        //	}

        //	// average normals for south pole

        //	average.clear();

        //	for (S32 i = 0; i < mNumS; i++)
        //	{
        //		average.add(norm[i + mNumS * (mNumT - 1)]);
        //	}

        //	// set average
        //	for (S32 i = 0; i < mNumS; i++)
        //	{
        //		norm[i + mNumS * (mNumT - 1)] = average;
        //	}
        //         }

        //if (wrap_s)
        //{
        //	for (S32 i = 0; i < mNumT; i++)
        //	{
        //		LLVector4a n;
        //		n.setAdd(norm[mNumS * i], norm[mNumS * i + mNumS - 1]);
        //		norm[mNumS * i] = n;
        //		norm[mNumS * i + mNumS - 1] = n;
        //	}
        //}

        //if (wrap_t)
        //{
        //	for (S32 i = 0; i < mNumS; i++)
        //	{
        //		LLVector4a n;
        //		n.setAdd(norm[i], norm[mNumS * (mNumT - 1) + i]);
        //		norm[i] = n;
        //		norm[mNumS * (mNumT - 1) + i] = n;
        //	}
        //}
        //}

        // Normalise normals:
        for (int normalIndex = 0; normalIndex < Normals.Count; normalIndex++)
        {
            Normals[normalIndex] = Normals[normalIndex].normalized;
        }

        return(true);
    }
示例#12
0
    protected bool CreateUnCutCubeCap(Volume volume, bool partialBuild)
    {
        List <Vector3> mesh    = volume.Points;
        List <Vector3> profile = volume.Profile.Points;
        int            maxS    = volume.Profile.PointCount;
        int            maxT    = volume.Path.PointCount;

        int gridSize = (profile.Count - 1) / 4;
        // VFExtents change
        Vector3 min = ExtentsMin;
        Vector3 max = ExtentsMax;

        int offset = ((TypeMask & VolumeFaceMask.Top) != 0)
            ? (maxT - 1) * maxS
            : BeginS;

        {
            VertexData[] corners  = new VertexData[4];
            VertexData   baseVert = new VertexData();
            for (int t = 0; t < 4; t++)
            {
                corners[t] = new VertexData
                {
                    Position = mesh[offset + (gridSize * t)],
                    TexCoord = new Vector2(profile[gridSize * t].x + 0.5f, 0.5f - profile[gridSize * t].y)
                };
            }

            {
                Vector3 lhs = corners[1].Position - corners[0].Position;
                Vector3 rhs = corners[2].Position - corners[1].Position;
                baseVert.Normal = Vector3.Cross(lhs, rhs);
                baseVert.Normal.Normalize();
            }

            if ((TypeMask & VolumeFaceMask.Top) == 0)
            {
                baseVert.Normal *= -1.0f;
            }
            else
            {
                //Swap the UVs on the U(X) axis for top face
                Vector2 swap;
                swap = corners[0].TexCoord;
                corners[0].TexCoord = corners[3].TexCoord;
                corners[3].TexCoord = swap;
                swap = corners[1].TexCoord;
                corners[1].TexCoord = corners[2].TexCoord;
                corners[2].TexCoord = swap;
            }

            int size = (gridSize + 1) * (gridSize + 1);
            //resizeVertices(size);
            Positions.Clear();
            Normals.Clear();
            Tangents.Clear();
            TexCoords.Clear();
            Indices.Clear();
            Edge.Clear();

            for (int gx = 0; gx < gridSize + 1; gx++)
            {
                for (int gy = 0; gy < gridSize + 1; gy++)
                {
                    VertexData newVert = LerpPlanarVertex(corners[0],
                                                          corners[1],
                                                          corners[3],
                                                          (float)gx / (float)gridSize,
                                                          (float)gy / (float)gridSize);

                    Positions.Add(newVert.Position);
                    Normals.Add(baseVert.Normal);
                    TexCoords.Add(newVert.TexCoord);

                    if (gx == 0 && gy == 0)
                    {
                        min = newVert.Position;
                        max = min;
                    }
                    else
                    {
                        UpdateMinMax(ref min, ref max, newVert.Position);
                    }
                }
            }

            Centre     = (min + max) * 0.5f;
            ExtentsMin = min;
            ExtentsMax = max;
        }

        if (!partialBuild)
        {
            int[] idxs = { 0, 1, (gridSize + 1) + 1, (gridSize + 1) + 1, (gridSize + 1), 0 };
            for (int gx = 0; gx < gridSize; gx++)
            {
                for (int gy = 0; gy < gridSize; gy++)
                {
                    if ((TypeMask & VolumeFaceMask.Top) != 0)
                    {
                        for (int i = 5; i >= 0; i--)
                        {
                            Indices.Add((gy * (gridSize + 1)) + gx + idxs[i]);
                        }

                        int edgeValue = gridSize * 2 * gy + gx * 2;

                        if (gx > 0)
                        {
                            Edge.Add(edgeValue);
                        }
                        else
                        {
                            Edge.Add(-1);                             // Mark face to higlight it
                        }

                        if (gy < gridSize - 1)
                        {
                            Edge.Add(edgeValue);
                        }
                        else
                        {
                            Edge.Add(-1);
                        }

                        Edge.Add(edgeValue);

                        if (gx < gridSize - 1)
                        {
                            Edge.Add(edgeValue);
                        }
                        else
                        {
                            Edge.Add(-1);
                        }

                        if (gy > 0)
                        {
                            Edge.Add(edgeValue);
                        }
                        else
                        {
                            Edge.Add(-1);
                        }

                        Edge.Add(edgeValue);
                    }
                    else
                    {
                        for (int i = 0; i < 6; i++)
                        {
                            Indices.Add((gy * (gridSize + 1)) + gx + idxs[i]);
                        }

                        int edgeValue = gridSize * 2 * gy + gx * 2;

                        if (gy > 0)
                        {
                            Edge.Add(edgeValue);
                        }
                        else
                        {
                            Edge.Add(-1);
                        }

                        if (gx < gridSize - 1)
                        {
                            Edge.Add(edgeValue);
                        }
                        else
                        {
                            Edge.Add(-1);
                        }

                        Edge.Add(edgeValue);

                        if (gy < gridSize - 1)
                        {
                            Edge.Add(edgeValue);
                        }
                        else
                        {
                            Edge.Add(-1);
                        }

                        if (gx > 0)
                        {
                            Edge.Add(edgeValue);
                        }
                        else
                        {
                            Edge.Add(-1);
                        }

                        Edge.Add(edgeValue);
                    }
                }
            }
        }

        return(true);
    }