// 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 })); }
/// <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); }
/// <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; }
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); }
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); }
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); } }
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)); }
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); }
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); }