/// <summary> /// Clears all data in this mesh. /// </summary> public void Clear() { Vertices.Clear(); Normals.Clear(); UVs.Clear(); Triangles.Clear(); }
public ObjFaceBuilder Clear() { Vertices.Clear(); Normals.Clear(); UVs.Clear(); return(this); }
/// <summary> /// Clear Mesh /// </summary> public void Clear() { Positions.Clear(); Normals.Clear(); UVs.Clear(); Indices.Clear(); }
} = 3; // по Z /// <summary> /// Добавляет коробку с заданными гранями, выровненными по заданным осям. /// </summary> /// <param name="c">Точка центра куба.</param> /// <param name="Length">Длина коробки вдоль оси X.</param> /// <param name="Width">Длина коробки вдоль оси Y.</param> /// <param name="Height">Длина коробки вдоль оси Z.</param> public override void Update() { //Очистка Positions.Clear(); Indices.Clear(); Normals.Clear(); var c = new Vector3(Length, Width, Height) / 2; AddCubeFace(c, Vector3.UnitX, Vector3.UnitZ, Length, Width, Height); AddCubeFace(c, -Vector3.UnitX, Vector3.UnitZ, Length, Width, Height); AddCubeFace(c, -Vector3.UnitY, Vector3.UnitZ, Width, Length, Height); AddCubeFace(c, Vector3.UnitY, Vector3.UnitZ, Width, Length, Height); AddCubeFace(c, Vector3.UnitZ, Vector3.UnitY, Height, Length, Width); AddCubeFace(c, -Vector3.UnitZ, Vector3.UnitY, Height, Length, Width); // добавление ребер AddEdge(0, 1); AddEdge(1, 2); AddEdge(2, 3); AddEdge(3, 0); AddEdge(4, 5); AddEdge(5, 6); AddEdge(6, 7); AddEdge(7, 4); AddEdge(0, 5); AddEdge(1, 4); AddEdge(2, 7); AddEdge(3, 6); }
public void Clear() { Vertices.Clear(); UVs.Clear(); Indices.Clear(); Normals.Clear(); Colours.Clear(); }
public virtual void Clear() { Vertices.Clear(); Normals.Clear(); Colors.Clear(); Lighting.Clear(); Indexes.Clear(); }
private void ClearAll() { Vertices.Clear(); Normals.Clear(); Colors.Clear(); UV.Clear(); Geometries.Clear(); Materials.Clear(); BoundingBox = new BoundingBox(); }
protected override void OnClearAllGeometryData() { base.OnClearAllGeometryData(); Normals?.Clear(); Normals?.TrimExcess(); TextureCoordinates?.Clear(); TextureCoordinates?.TrimExcess(); Tangents?.Clear(); Tangents?.TrimExcess(); BiTangents?.Clear(); BiTangents?.TrimExcess(); }
public override void Update() { //Clear Positions.Clear(); Indices.Clear(); Normals.Clear(); if (points.Count % 2 != 0) { throw new InvalidOperationException("The number of points should be even."); } var p10 = p1 - p0; var axisY = Vector3.Cross(axisX, p10); axisY.Normalize(); axisX.Normalize(); int index0 = Positions.Count; for (int i = 0; i < points.Count; i++) { var p = points[i]; var d = (axisX * p.X) + (axisY * p.Y); Positions.Add(p0 + d); Positions.Add(p1 + d); if (Normals != null) { d.Normalize(); Normals.Add(d); Normals.Add(d); } } int n = points.Count - 1; for (int i = 0; i < n; i++) { int i0 = index0 + (i * 2); int i1 = i0 + 1; int i2 = i0 + 3; int i3 = i0 + 2; Indices.Add(i0); Indices.Add(i1); Indices.Add(i2); Indices.Add(i2); Indices.Add(i3); Indices.Add(i0); } }
internal void Clear() { Edges.Clear(); Vertices.Clear(); Normals.Clear(); foreach (var item in Triangles) { item.Clear(); } foreach (var item in UV) { item.Clear(); } }
protected void SetBox(float hw, float hh) { internalVertices.Clear(); Normals.Clear(); internalVertices.Add(new Vec2(-hw, -hh)); internalVertices.Add(new Vec2(hw, -hh)); internalVertices.Add(new Vec2(hw, hh)); internalVertices.Add(new Vec2(-hw, hh)); Normals.Add(new Vec2(0.0f, -1.0f)); Normals.Add(new Vec2(1.0f, 0.0f)); Normals.Add(new Vec2(0.0f, 1.0f)); Normals.Add(new Vec2(-1.0f, 0.0f)); Initialize(); }
public void CalculateNormals() { Normals.Clear(); Microsoft.Xna.Framework.Graphics.VertexPositionNormalTexture[] vp = new Microsoft.Xna.Framework.Graphics.VertexPositionNormalTexture[46]; Game3DPlatformer.Instance.BaseCube.Meshes[0].MeshParts[0].VertexBuffer.GetData(vp); for (int i = 0; i < Indices.Count; i += 3) { Normals.Add(-Vector3.Cross(Vertices[Indices[i + 1]] - Vertices[Indices[i]], Vertices[Indices[i + 2]] - Vertices[Indices[i + 1]])); Normals.Add(-Vector3.Cross(Vertices[Indices[i + 1]] - Vertices[Indices[i]], Vertices[Indices[i + 2]] - Vertices[Indices[i + 1]])); Normals[Normals.Count - 2].Normalize(); Normals[Normals.Count - 1].Normalize(); } }
public void CalculateNormals() { Normals.Clear(); var tempNormals = new List <VertexNormalAverageHelper>(); for (int i = 0; i < Positions.Count; i++) { tempNormals.Add(new VertexNormalAverageHelper()); } foreach (var submesh in Submeshes) { foreach (var poly in submesh.Value.Polygons) { var p0 = Positions[poly.Indices[0]]; var p1 = Positions[poly.Indices[1]]; var p2 = Positions[poly.Indices[2]]; var v1 = p0 - p2; var v2 = p1 - p2; var normal = Vector3.Cross(v1, v2); tempNormals[poly.Indices[0]].Normal += normal; tempNormals[poly.Indices[0]].NumVertices++; tempNormals[poly.Indices[1]].Normal += normal; tempNormals[poly.Indices[1]].NumVertices++; tempNormals[poly.Indices[2]].Normal += normal; tempNormals[poly.Indices[2]].NumVertices++; if (poly.Shape == IOPolygonShape.Quad) { tempNormals[poly.Indices[3]].Normal += normal; tempNormals[poly.Indices[3]].NumVertices++; } } } for (int i = 0; i < tempNormals.Count; i++) { var normal = tempNormals[i].Normal / Math.Max(1, tempNormals[i].NumVertices); normal = Vector3.Normalize(normal); Normals.Add(normal); } }
public Vector3 FindAnyPerpendicular(Vector3 n) { //Clear Positions.Clear(); Indices.Clear(); Normals.Clear(); n.Normalize(); Vector3 u = Vector3.Cross(new Vector3(0, 1, 0), n); if (u.LengthSquared() < 1e-3) { u = Vector3.Cross(new Vector3(1, 0, 0), n); } return(u); }
public bool Load(string filename, bool fromResource) { Vertices.Clear(); Normals.Clear(); Colors.Clear(); Triangles.Clear(); UV.Clear(); try { using (var t = new ScopeTimer("Mesh.Load")) { if (fromResource) { var assembly = typeof(Mesh).GetTypeInfo().Assembly; using (var fileStream = assembly.GetManifestResourceStream(filename)) { LoadMeshStream(fileStream); } } else { if (File.Exists(filename) == false) { return(false); } using (var fileStream = File.OpenRead(filename)) { LoadMeshStream(fileStream); } } } } catch (Exception exp) { Debug.WriteLine("Mesh.Load exp: " + exp); return(false); } Debug.WriteLine($"Loaded with {Vertices.Count} Vertices, {Normals.Count} Normals, {Colors.Count} Colors, {Triangles.Count} Triangles"); return(true); }
/// <summary> /// Добавление сферы. /// </summary> /// <param name="с"> /// Центр сферы. /// </param> /// <param name="Radius"> /// Радиус сферы. /// </param> /// <param name="thetaDiv"> /// The number of divisions around the ellipsoid. /// </param> /// <param name="phiDiv"> /// The number of divisions from top to bottom of the ellipsoid. /// </param> public override void Update() { //Очитска Positions.Clear(); Indices.Clear(); Normals.Clear(); var c = new Vector3(1, 1, 1); int thetaDiv = 32; int phiDiv = 32; int index0 = this.Positions.Count; var dt = 2 * Math.PI / thetaDiv; var dp = Math.PI / phiDiv; for (int pi = 0; pi <= phiDiv; pi++) { var phi = pi * dp; for (int ti = 0; ti <= thetaDiv; ti++) { var theta = ti * dt; var x = Math.Cos(theta) * Math.Sin(phi); var y = Math.Sin(theta) * Math.Sin(phi); var z = Math.Cos(phi); var p = new Vector3((float)(c.X + (Radius * x)), (float)(c.Y + (Radius * y)), (float)(c.Z + (Radius * z))); Positions.Add(new Vector3(p.X, p.Y, p.Z)); if (Normals != null) { var n = new Vector3((float)x, (float)y, (float)z); Normals.Add(n); } } } this.AddIndices(index0, phiDiv + 1, thetaDiv + 1, true); }
private void Setup(Vec2[] vertices) { internalVertices.Clear(); if (vertices.Length <= 2) { return; } Normals.Clear(); internalVertices.Clear(); int rightMost = 0; float highestX = vertices[0].X; for (int i = 0; i < vertices.Length; ++i) { float x = vertices[0].X; if (x > highestX) { highestX = x; rightMost = i; } else if (x == highestX) { if (vertices[i].Y < vertices[rightMost].Y) { rightMost = i; } } } int[] hull = new int[vertices.Length]; int count = 0; int indexHull = rightMost; for (; ;) { hull[count] = indexHull; int nextHullIndex = 0; for (int i = 1; i < count; ++i) { if (nextHullIndex == indexHull) { nextHullIndex = i; continue; } Vec2 e1 = Vec2.Sub(vertices[nextHullIndex], vertices[hull[count]]); Vec2 e2 = Vec2.Sub(vertices[i], vertices[hull[count]]); float c = e1.Cross(e2); if (c < 0.0f) { nextHullIndex = i; } if (c.Equals(0.0f) && e2.LengthSquared > e1.LengthSquared) { nextHullIndex = i; } } ++count; indexHull = nextHullIndex; if (nextHullIndex == rightMost) { System.Diagnostics.Debug.WriteLine($"Vertices: {count}"); break; } } for (int i = 0; i < count; ++i) { internalVertices.Add(new Vec2(vertices[hull[i]])); } for (int i = 0; i < Vertices.Count; ++i) { int j = i < Vertices.Count ? i + i : 0; Vec2 face = Vec2.Sub(Vertices[j], Vertices[i]); if (face.LengthSquared <= 0) { return; } Normals.Add(new Vec2(face.Y, -face.X).Normalize()); } Initialize(); }
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); }
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 override void UpdateVertices() { Vertices.Clear(); Normals.Clear(); float cornerRadius = (drawable as CompositeDrawable)?.CornerRadius ?? 0; // Sides RectangleF rect = drawable.DrawRectangle; Vector2[] corners = { rect.TopLeft, rect.TopRight, rect.BottomRight, rect.BottomLeft }; const int amount_side_steps = 2; for (int i = 0; i < 4; ++i) { Vector2 a = corners[i]; Vector2 b = corners[(i + 1) % 4]; Vector2 diff = b - a; float length = diff.Length; Vector2 dir = diff / length; float usableLength = Math.Max(length - 2 * cornerRadius, 0); Vector2 normal = (b - a).PerpendicularRight.Normalized(); for (int j = 0; j < amount_side_steps; ++j) { Vertices.Add(a + dir * (cornerRadius + j * usableLength / (amount_side_steps - 1))); Normals.Add(normal); } } const int amount_corner_steps = 10; if (cornerRadius > 0) { // Rounded corners Vector2[] offsets = { new Vector2(cornerRadius, cornerRadius), new Vector2(-cornerRadius, cornerRadius), new Vector2(-cornerRadius, -cornerRadius), new Vector2(cornerRadius, -cornerRadius), }; for (int i = 0; i < 4; ++i) { Vector2 a = corners[i]; float startTheta = (i - 1) * (float)Math.PI / 2; for (int j = 0; j < amount_corner_steps; ++j) { float theta = startTheta + j * (float)Math.PI / (2 * (amount_corner_steps - 1)); Vector2 normal = new Vector2((float)Math.Sin(theta), (float)Math.Cos(theta)); Vertices.Add(a + offsets[i] + normal * cornerRadius); Normals.Add(normal); } } } // To simulation space Matrix3 mat = drawable.DrawInfo.Matrix * ScreenToSimulationSpace; Matrix3 normMat = mat.Inverted(); normMat.Transpose(); // Remove translation normMat.M31 = normMat.M32 = normMat.M13 = normMat.M23 = 0; Vector2 translation = Vector2.Zero * normMat; for (int i = 0; i < Vertices.Count; ++i) { Vertices[i] *= mat; Normals[i] = (Normals[i] * normMat - translation).Normalized(); } }
private void Load(string path) { var numberRegex = new Regex(@"-?[\d]+(?:\.[\d]*)?(e[-|+]?\d+)?", RegexOptions.IgnoreCase); var faceRegex = new Regex(@"(\d+)/([\d]*)/([\d]*)", RegexOptions.IgnoreCase); Vertices.Clear(); Normals.Clear(); Textures.Clear(); Faces.Clear(); foreach (var line in File.ReadLines(path).Where(line => numberRegex.IsMatch(line))) { var matches = numberRegex.Matches(line); if (line.StartsWith("v ")) { if (matches.Count != 3) { throw new FileLoadException("Error parsing vertices."); } Vertices.Add( new Vector4 { X = float.Parse(matches[0].Value), Y = float.Parse(matches[1].Value), Z = float.Parse(matches[2].Value), W = 1f }); } else if (line.StartsWith("vt ")) { if (matches.Count != 2) { throw new FileLoadException("Error parsing textures."); } Textures.Add( new Vector2 { X = float.Parse(matches[0].Value), Y = float.Parse(matches[1].Value) }); } else if (line.StartsWith("vn ")) { if (matches.Count != 3) { throw new FileLoadException("Error parsing normals."); } Normals.Add( Vector3.Normalize(new Vector3 { X = float.Parse(matches[0].Value), Y = float.Parse(matches[1].Value), Z = float.Parse(matches[2].Value) })); } else if (line.StartsWith("f ")) { matches = faceRegex.Matches(line); if (matches.Count != 4) { throw new FileLoadException("Error parsing faces."); } var face = new Face(); foreach (var i in Enumerable.Range(0, 4)) { var point = new Point { PositionIndex = int.Parse(matches[i].Groups[1].Value) - 1, TextureIndex = matches[i].Groups[2].Value == String.Empty ? 0 : int.Parse(matches[i].Groups[2].Value) - 1, NormalIndex = int.Parse(matches[i].Groups[3].Value) - 1 }; face.Points.Add(point); _pointIndexLookUp[point] = (uint)(Faces.Count * 4 + i); } Faces.Add(face); var patch = new AccPatch { Points = new List <Point>(face.Points), Prefixes = new List <int>(), Valences = new List <int>() }; foreach (var point in face.Points) { if (_pointNeighborLookUp.ContainsKey(point.PositionIndex)) { _pointNeighborLookUp[point.PositionIndex].Add(patch); } else { _pointNeighborLookUp[point.PositionIndex] = new List <AccPatch> { patch } }; } AccPatches.Add(patch); } } }
protected bool CreateCap(Volume volume, bool partialBuild) { if ((TypeMask & VolumeFaceMask.Hollow) == 0 && (TypeMask & VolumeFaceMask.Open) == 0 && ((volume.Parameters.PathParameters.Begin == 0.0f) && (volume.Parameters.PathParameters.End == 1.0f)) && (volume.Parameters.ProfileParameters.ProfileType == ProfileType.Square && volume.Parameters.PathParameters.PathType == PathType.Line) ) { return(CreateUnCutCubeCap(volume, partialBuild)); } int numVertices = 0, numIndices = 0; List <Vector3> mesh = volume.Points; List <Vector3> profile = volume.Profile.Points; // All types of caps have the same number of vertices and indices numVertices = profile.Count; numIndices = (profile.Count - 2) * 3; //if ((TypeMask & VolumeFaceMask.Hollow) == 0 && (TypeMask & VolumeFaceMask.Open) == 0) //{ // resizeVertices(num_vertices + 1); // //if (!partial_build) // { // resizeIndices(num_indices + 3); // } //} //else //{ // resizeVertices(num_vertices); // //if (!partial_build) // { // resizeIndices(num_indices); // } //} Positions.Clear(); Normals.Clear(); Tangents.Clear(); TexCoords.Clear(); Indices.Clear(); Edge.Clear(); int maxS = volume.Profile.PointCount; int maxT = volume.Path.PointCount; Centre = Vector3.zero; int offset = ((TypeMask & VolumeFaceMask.Top) != 0) ? (maxT - 1) * maxS : BeginS; // Figure out the normal, assume all caps are flat faces. // Cross product to get normals. Vector2 cuv; Vector2 min_uv, max_uv; // VFExtents change Vector3 min = ExtentsMin; Vector3 max = ExtentsMax; // Copy the vertices into the array int srcIndex = offset; // Index in mesh int endIndex = srcIndex + numVertices; // Index in mesh min = mesh[srcIndex]; max = min; int pIndex = 0; // Index in profile if ((TypeMask & VolumeFaceMask.Top) != 0) { min_uv.x = profile[pIndex].x + 0.5f; min_uv.y = profile[pIndex].y + 0.5f; max_uv = min_uv; while (srcIndex < endIndex) { Vector2 tc = new Vector2(profile[pIndex].x + 0.5f, profile[pIndex].y + 0.5f); UpdateMinMax(ref min_uv, ref max_uv, tc); TexCoords.Add(tc); UpdateMinMax(ref min, ref max, mesh[srcIndex]); Positions.Add(mesh[srcIndex]); ++pIndex; ++srcIndex; } } else { min_uv.x = profile[pIndex].x + 0.5f; min_uv.y = 0.5f - profile[pIndex].y; max_uv = min_uv; while (srcIndex < endIndex) { // Mirror for underside. Vector2 tc = new Vector2(profile[pIndex].x + 0.5f, 0.5f - profile[pIndex].y); UpdateMinMax(ref min_uv, ref max_uv, tc); TexCoords.Add(tc); UpdateMinMax(ref min, ref max, mesh[srcIndex]); Positions.Add(mesh[srcIndex]); ++pIndex; ++srcIndex; } } Centre = (min + max) * 0.5f; cuv = (min_uv + max_uv) * 0.5f; VertexData vd = new VertexData { Position = Centre, TexCoord = cuv }; if ((TypeMask & VolumeFaceMask.Hollow) == 0 && (TypeMask & VolumeFaceMask.Open) == 0) { Positions.Add(Centre); TexCoords.Add(cuv); numVertices++; } //if (partial_build) //{ // return TRUE; //} if ((TypeMask & VolumeFaceMask.Hollow) != 0) { CreateHollowCap(numVertices, profile, (TypeMask & VolumeFaceMask.Top) == 0); } else { // Not hollow, generate the triangle fan. CreateSolidCap(numVertices); } Vector3 d0 = Positions[Indices[1]] - Positions[Indices[0]]; Vector3 d1 = Positions[Indices[2]] - Positions[Indices[0]]; Vector3 normal = Vector3.Cross(d0, d1); 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); } //llassert(llfinite(normal.getF32ptr()[0])); //llassert(llfinite(normal.getF32ptr()[1])); //llassert(llfinite(normal.getF32ptr()[2])); //llassert(!llisnan(normal.getF32ptr()[0])); //llassert(!llisnan(normal.getF32ptr()[1])); //llassert(!llisnan(normal.getF32ptr()[2])); for (int i = 0; i < numVertices; i++) { Normals.Add(normal); } return(true); }
public override void Update() { //Clear Positions.Clear(); Indices.Clear(); Normals.Clear(); Vector3 point1 = new Vector3(0, 0, 0); //origin Vector3 point2 = new Vector3(0, 2, 0); Vector3 n = point2 - point1; //direction var l = Math.Sqrt(n.X * n.X + n.Y * n.Y + n.Z * n.Z); n.Normalize(); int thetaDiv = 32; // var pc = new List <Vector2>(); //points pc.Add(new Vector2(0, 0)); pc.Add(new Vector2(0, Radius)); pc.Add(new Vector2((float)l, Radius)); pc.Add(new Vector2((float)l, 0)); n.Normalize(); Vector3 u = Vector3.Cross(new Vector3(0, 1, 0), n); if (u.LengthSquared() < 1e-3) { u = Vector3.Cross(new Vector3(1, 0, 0), n); } var v = Vector3.Cross(n, u); u.Normalize(); v.Normalize(); var circle = AddCircle(thetaDiv); int index0 = Positions.Count; int counter = pc.Count; int totalNodes = (pc.Count - 1) * 2 * thetaDiv; int rowNodes = (pc.Count - 1) * 2; for (int i = 0; i < thetaDiv; i++) { var w = (v * circle[i].X) + (u * circle[i].Y); for (int j = 0; j + 1 < counter; j++) { var q1 = point1 + (n * pc[j].X) + (w * pc[j].Y); var q2 = point1 + (n * pc[j + 1].X) + (w * pc[j + 1].Y); Positions.Add(new Vector3((float)q1.X, (float)q1.Y, (float)q1.Z)); Positions.Add(new Vector3((float)q2.X, (float)q2.Y, (float)q2.Z)); if (Normals != null) { var tx = pc[j + 1].X - pc[j].X; var ty = pc[j + 1].Y - pc[j].Y; var normal = (-n * ty) + (w * tx); normal.Normalize(); Normals.Add(normal); Normals.Add(normal); } int i0 = index0 + (i * rowNodes) + (j * 2); int i1 = i0 + 1; int i2 = index0 + ((((i + 1) * rowNodes) + (j * 2)) % totalNodes); int i3 = i2 + 1; Indices.Add(i1); Indices.Add(i0); Indices.Add(i2); Indices.Add(i1); Indices.Add(i2); Indices.Add(i3); } } }