/// <summary> /// Store the vertex into the cache for later retrieval. /// </summary> /// <param name="vertexIndex">The index associated with this vertex.</param> /// <param name="point">The location of the point on the square: an int from 0 to 7.</param> /// <param name="x">Location in the current row of squares.</param> public void CacheVertex(VertexIndex vertexIndex, int point, int x) { if (point < perSquareCacheSize) { currentRow[point, x] = vertexIndex; } }
// Token: 0x0600003A RID: 58 RVA: 0x000030B8 File Offset: 0x000012B8 private static IEnumerable <UVSetTagg> createUVSetTaggs(LOD src) { int nFaces = src.Faces.Length; int num3; for (int i = 0; i < src.UVSets.Length; i = num3) { UVSetTagg uvsetTagg = new UVSetTagg(); uvsetTagg.Name = "#UVSet#"; uvsetTagg.uvSetNr = (uint)i; uvsetTagg.faceUVs = new float[nFaces][, ]; float[] uvdata = src.UVSets[i].UVData; uint num = 4u; for (int j = 0; j < nFaces; j++) { Polygon polygon = src.Faces[j]; int num2 = polygon.VertexIndices.Length; uvsetTagg.faceUVs[j] = new float[num2, 2]; for (int k = 0; k < num2; k++) { VertexIndex vi = polygon.VertexIndices[num2 - 1 - k]; uvsetTagg.faceUVs[j][k, 0] = uvdata[vi * 2]; uvsetTagg.faceUVs[j][k, 1] = uvdata[vi * 2 + 1]; num += 8u; } } uvsetTagg.DataSize = num; yield return(uvsetTagg); num3 = i + 1; } yield break; }
/// <summary> /// Store the vertex into the cache for later retrieval. /// </summary> /// <param name="vertexIndex">The index associated with this vertex.</param> /// <param name="point">The location of the point on the square: an int from 0 to 7.</param> /// <param name="x">Location in the current row.</param> public void CacheVertex(VertexIndex vertexIndex, int point, int x) { if (point < perSquareCacheSize) { int positionInRow = perSquareCacheSize * x + point; currentRow[positionInRow] = vertexIndex; } }
public VertexLookup(int rowLength) { VertexIndex[] currentRow = new VertexIndex[rowLength * perSquareCacheSize]; VertexIndex[] previousRow = new VertexIndex[rowLength * perSquareCacheSize]; for (int i = 0; i < currentRow.Length; i++) { currentRow[i] = VertexIndex.VoidValue; previousRow[i] = VertexIndex.VoidValue; } this.currentRow = currentRow; this.previousRow = previousRow; }
/// <summary> /// Retrieve the vertex from the cache, if it exists. /// </summary> /// <param name="vertexIndex">The index associated with this vertex.</param> /// <param name="point">The location of the point on the square: an int from 0 to 7.</param> /// <param name="x">Location in the current row.</param> /// <returns>Bool representing whether the vertex was found.</returns> public bool TryGetCachedVertex(int point, int x, out VertexIndex vertexIndex) { vertexIndex = VertexIndex.VoidValue; if (IsPointOnBottomOfSquare(point)) { vertexIndex = GetVertexFromBelow(point, x); } if (IsVertexIndexVoid(vertexIndex) && IsPointOnLeftOfSquare(point) && x > 0) { vertexIndex = GetVertexFromLeft(point, x); } return(!IsVertexIndexVoid(vertexIndex)); }
/// <summary> /// Retrieve the vertex from the cache, if it exists. /// </summary> /// <param name="vertexIndex">The index associated with this vertex.</param> /// <param name="point">The location of the point on the square: an int from 0 to 7.</param> /// <param name="x">Location in the current row.</param> /// <returns>Bool representing whether the vertex was found.</returns> public bool TryGetCachedVertex(int point, int x, out VertexIndex vertexIndex) { VertexIndex?index = null; if (isOnBottom[point]) { index = previousRow[bottomOffset[point], x]; } if (!index.HasValue && isOnLeft[point] && x > 0) { index = currentRow[leftOffset[point], x - 1]; } vertexIndex = index.HasValue ? index.Value : (VertexIndex)0; return(index.HasValue); }
/// <summary> /// Writes a Vertex Index into the data stream /// </summary> /// <param name="vertexIndex">The Vertex Index to write</param> public void WriteVertexIndex(VertexIndex vertexIndex) { short value = vertexIndex.index; if (vertexIndex.polyBoundary) { //if index is a polygon boundary (begin/end), set the highest bit // (using logical OR) // value 0000000000000111 = 7 // mask 1000000000000000 = 0x8000 in hex // result 1000000000000111 = desired index value (-32761 in dec) value = (short)(value ^ 0x8000); } data.AddRange(BitConverter.GetBytes(value)); }
public IEnumerable <VertexIndex> FindNeighbours(VertexIndex a) { var indexOfA = this.TriangleIndicies.IndexOf(a); while (indexOfA != -1) { var verticeTripleIndex = (int)((indexOfA / 3.0).Floor() * 3); yield return(new VertexIndex(this.TriangleIndicies[verticeTripleIndex + 0])); yield return(new VertexIndex(this.TriangleIndicies[verticeTripleIndex + 1])); yield return(new VertexIndex(this.TriangleIndicies[verticeTripleIndex + 2])); indexOfA = this.TriangleIndicies.IndexOf(a, verticeTripleIndex + 3); // start search at next triple } }
public VertexIndex[] Duplicate(VertexIndex[] duplicateVertices, params IBufferObject[] duplicateVbos) { var newExtrudedVertices = new VertexIndex[duplicateVertices.Length]; // duplicate selected vertexes for (int i = 0; i < duplicateVertices.Length; i++) { newExtrudedVertices[i] = new VertexIndex(Vertices.Count); foreach (var vbo in duplicateVbos) { vbo.Duplicate(duplicateVertices[i]); } } // if they are neighbouring, make face between them for (int a = 0; a < newExtrudedVertices.Length; a++) { for (int b = a; b < newExtrudedVertices.Length; b++) { if (IsNeighbouring(duplicateVertices[a], duplicateVertices[b])) { //OVERKILL: to make sure skirts are visible we make both CW and CCW triangles //CW vs CCW might actually depend on the order of array duplicateVertices //CCW AddTriangle(duplicateVertices[a], duplicateVertices[b], newExtrudedVertices[b]); AddTriangle(duplicateVertices[a], newExtrudedVertices[b], newExtrudedVertices[a]); //CW AddTriangle(duplicateVertices[b], duplicateVertices[a], newExtrudedVertices[b]); AddTriangle(duplicateVertices[a], newExtrudedVertices[a], newExtrudedVertices[b]); } } } return(newExtrudedVertices); }
/// <summary> /// Find the direction vector for a vertex by taking the average direction vector of the faces the vertex belongs to /// </summary> /// <param name="vertex">Vertex in a mesh</param> /// <param name="mesh">Mesh which vertex is a part of.</param> /// <returns>Normal/Direction vector for vertex</returns> public Vector3 FindVertexNormal(VertexIndex vertex, CVMesh mesh) { mesh.Faces = Extensions.ToFaces(mesh.TriangleIndeces); int index = vertex.Index; List <Vector3> faceNormals = new List <Vector3>(); for (int i = 0; i < mesh.Faces.Count; i++) { Face f = mesh.Faces[i]; if (f.index1 == index || f.index2 == index || f.index3 == index) { faceNormals.Add(GetFaceNormal(i, mesh)); } } if (faceNormals.Count == 0) { return new Vector3 { X = 0, Y = 0, Z = 1 } } ; return(Extensions.Normalize(Extensions.AvgVector(faceNormals))); }
/// <summary> /// Initializes a new instance of the <see cref="SEGM"/> class. /// </summary> /// <param name="from">The <see cref="BaseChunk" /> to use for creating this Chunk. The given data will be interpreted respectively.</param> public SEGM(BaseChunk from) : base(from) { List <Vector3> verts = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); Polygon currentPoly = new Polygon(vertices); bool lastBoundry = false; while (!EndOfData) { BaseChunk nextChunk = ReadChunk(); int count = 0; switch (nextChunk.ChunkName) { case "MATI": matIndex = nextChunk.ReadInt32(); break; case "POSL": count = nextChunk.ReadInt32(); for (int i = 0; i < count; i++) { verts.Add(nextChunk.ReadVector3()); } break; case "NRML": count = nextChunk.ReadInt32(); for (int i = 0; i < count; i++) { normals.Add(nextChunk.ReadVector3()); } break; case "UV0L": count = nextChunk.ReadInt32(); for (int i = 0; i < count; i++) { uvs.Add(nextChunk.ReadVector2()); } break; case "STRP": count = nextChunk.ReadInt32(); for (int i = 0; i < count; i++) { VertexIndex next = nextChunk.ReadVertexIndex(); if (next.polyBoundary && !lastBoundry) { //polygon finished, add to buffer if (currentPoly.VertexIndices.Count > 0) { polygons.Add(currentPoly); } //start new polygon currentPoly = new Polygon(vertices); //write first index value to polygon currentPoly.VertexIndices.Add(next.index); } else { if (currentPoly != null) { currentPoly.VertexIndices.Add(next.index); } else { //this should never happen Log.Add("Warning: Lone Vertex in Strip Buffer!", LogType.Warning); } } lastBoundry = next.polyBoundary; } break; } } if (uvs.Count > 0) { hasUVs = true; } for (int i = 0; i < verts.Count; i++) { //since uv coordinates are optional, deliver empty ones if non existent Vector2 uv = (i < uvs.Count) ? uvs[i] : new Vector2(); vertices.Add(new Vertex(verts[i], normals[i], uv)); } //Add last Polygon if (currentPoly != null && currentPoly.VertexIndices.Count > 0) { polygons.Add(currentPoly); } }
/// <summary> /// Writes the complete data stream new from scratch. /// Every Chunk inheriting from this must override this function /// </summary> public override void WriteData() { base.WriteData(); WriteHeader("MATI"); WriteInt32(4); WriteInt32(Owner.Materials.FindIndex(mat => mat == Material)); WriteHeader("POSL"); WriteInt32(vertices.Count * 12 + 4); //float 4 bytes * vector3, 3 floats = 12 bytes per Position WriteInt32(vertices.Count); //first integer indicates number of vertices that follow foreach (Vertex vert in vertices) { WriteVector3(vert.position); } WriteHeader("NRML"); WriteInt32(vertices.Count * 12 + 4); WriteInt32(vertices.Count); foreach (Vertex vert in vertices) { WriteVector3(vert.normal); } if (hasUVs) { WriteHeader("UV0L"); WriteInt32(vertices.Count * 8 + 4); WriteInt32(vertices.Count); foreach (Vertex vert in vertices) { WriteVector2(vert.uvCoordinate); } } //Write Polygon Strips WriteHeader("STRP"); //lets build up an index buffer from our stored polygons List <VertexIndex> vertexBuffer = new List <VertexIndex>(); foreach (Polygon poly in polygons) { for (int i = 0; i < poly.VertexIndices.Count; i++) { VertexIndex vertInd = new VertexIndex { index = poly.VertexIndices[i] }; //the first two indices are always tagged as begin/end if (i == 0 || i == 1) { vertInd.polyBoundary = true; } vertexBuffer.Add(vertInd); } } WriteInt32(vertexBuffer.Count * 2 + 4); WriteInt32(vertexBuffer.Count); foreach (VertexIndex vertInd in vertexBuffer) { WriteVertexIndex(vertInd); } WriteChunkLength(); }
public VertexIndex(int index) : base(dataSize, index) { _inst = this; }
public bool IsNeighbouring(VertexIndex a, VertexIndex b) { return(FindNeighbours(a).Contains(b)); }
public void AddTriangle(VertexIndex a, VertexIndex b, VertexIndex c) { this.TriangleIndicies.Add(a); this.TriangleIndicies.Add(b); this.TriangleIndicies.Add(c); }
public void Duplicate(VertexIndex index) { Add(this[index.Index]); }
bool IsVertexIndexVoid(VertexIndex index) { return(index == VertexIndex.VoidValue); }
public bool Equals(VertexIndex other) { return(VertexIndexInPart == other.VertexIndexInPart && PartIndex == other.PartIndex); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static Mesh MergedVertices(this Mesh mesh, double tolerance = Tolerance.Distance) //TODO: use the point matrix { List <Face> faces = mesh.Faces.Select(x => x.Clone() as Face).ToList(); List <VertexIndex> vertices = mesh.Vertices.Select((x, i) => new VertexIndex(x.Clone() as Point, i)).ToList(); foreach (Face face in faces) { vertices[face.A].Faces.Add(face); vertices[face.B].Faces.Add(face); vertices[face.C].Faces.Add(face); if (face.IsQuad()) { vertices[face.A].Faces.Add(face); } } vertices.Sort(delegate(VertexIndex v1, VertexIndex v2) { return(v1.Location.SquareDistance(Point.Origin).CompareTo(v2.Location.SquareDistance(Point.Origin))); }); List <int> culledIndices = new List <int>(); double sqTol = tolerance * tolerance; for (int i = 0; i < vertices.Count; i++) { double distance = vertices[i].Location.Distance(Point.Origin); int j = i + 1; while (j < vertices.Count && Math.Abs(vertices[j].Location.Distance(Point.Origin) - distance) < tolerance) { VertexIndex v2 = vertices[j]; if (vertices[i].Location.SquareDistance(vertices[j].Location) < sqTol) { SetFaceIndex(v2.Faces, vertices[j].Index, vertices[i].Index); culledIndices.Add(vertices[j].Index); v2.Index = vertices[i].Index; break; } j++; } } for (int i = 0; i < faces.Count; i++) { for (int k = 0; k < culledIndices.Count; k++) { if (faces[i].A > culledIndices[k]) { faces[i].A--; } if (faces[i].B > culledIndices[k]) { faces[i].B--; } if (faces[i].C > culledIndices[k]) { faces[i].C--; } if (faces[i].D > culledIndices[k]) { faces[i].D--; } } } return(new Mesh { Vertices = vertices.Select(x => x.Location).ToList(), Faces = faces }); }
// Token: 0x06000035 RID: 53 RVA: 0x00002CE4 File Offset: 0x00000EE4 private static void ReconstructProxies(LOD src, out Dictionary <string, List <Conversion.PointWeight> > points, out Dictionary <string, List <int> > faces) { points = new Dictionary <string, List <Conversion.PointWeight> >(src.NamedSelections.Length * 2); faces = new Dictionary <string, List <int> >(src.NamedSelections.Length * 2); for (int i = 0; i < src.Faces.Length; i++) { Polygon polygon = src.Faces[i]; if (polygon.VertexIndices.Length == 3) { VertexIndex vi = polygon.VertexIndices[0]; VertexIndex vi2 = polygon.VertexIndices[1]; VertexIndex vi3 = polygon.VertexIndices[2]; Vector3P vector3P = src.Vertices[vi]; Vector3P vector3P2 = src.Vertices[vi2]; Vector3P vector3P3 = src.Vertices[vi3]; float num = vector3P.Distance(vector3P2); float num2 = vector3P.Distance(vector3P3); float num3 = vector3P2.Distance(vector3P3); if (num > num2) { Methods.Swap <Vector3P>(ref vector3P2, ref vector3P3); Methods.Swap <float>(ref num, ref num2); } if (num > num3) { Methods.Swap <Vector3P>(ref vector3P, ref vector3P3); Methods.Swap <float>(ref num, ref num3); } if (num2 > num3) { Methods.Swap <Vector3P>(ref vector3P, ref vector3P2); Methods.Swap <float>(ref num2, ref num3); } Vector3P vector3P4 = vector3P; Vector3P vector3P5 = vector3P2 - vector3P; Vector3P vector3P6 = vector3P3 - vector3P; vector3P5.Normalize(); vector3P6.Normalize(); if (Methods.EqualsFloat(vector3P6 * vector3P5, 0f, 0.05f)) { for (int j = 0; j < src.Proxies.Length; j++) { Vector3P position = src.Proxies[j].transformation.Position; Vector3P up = src.Proxies[j].transformation.Orientation.Up; Vector3P dir = src.Proxies[j].transformation.Orientation.Dir; if (vector3P4.Equals(position) && vector3P5.Equals(dir) && vector3P6.Equals(up)) { Proxy proxy = src.Proxies[j]; string name = src.NamedSelections[proxy.namedSelectionIndex].Name; if (!faces.ContainsKey(name)) { faces[name] = i.Yield <int>().ToList <int>(); points[name] = Methods.Yield <Conversion.PointWeight>(new Conversion.PointWeight[] { new Conversion.PointWeight(vi, byte.MaxValue), new Conversion.PointWeight(vi2, byte.MaxValue), new Conversion.PointWeight(vi3, byte.MaxValue) }).ToList <Conversion.PointWeight>(); break; } } } } } } }