public void AddVertex(Vector3 pos, Vector3 normal, Vector2 texCoord) { Vertices.Add(pos); Normals.Add(normal); TexCoords.Add(texCoord); Indices.Add(Indices.Count); }
public void AddVtx(Primitive src, int vtxIdx) { VertexCount++; Matrices.Add(src.Matrices[vtxIdx]); Positions.Add(src.Positions[vtxIdx]); Normals.Add(src.Normals[vtxIdx]); Colors.Add(src.Colors[vtxIdx]); TexCoords.Add(src.TexCoords[vtxIdx]); }
public Geoset1300(BinaryReader br) { TotalSize = br.ReadUInt32(); long end = TotalSize + br.BaseStream.Position; //Vertices if (br.HasTag("VRTX")) { NrOfVertices = br.ReadUInt32(); for (int i = 0; i < NrOfVertices; i++) { Vertices.Add(new CVector3(br)); } } //Normals if (br.HasTag("NRMS")) { NrOfNormals = br.ReadUInt32(); for (int i = 0; i < NrOfNormals; i++) { Normals.Add(new CVector3(br)); } } //TexCoords if (br.HasTag("UVAS")) { NrOfTexCoords = br.ReadUInt32(); //Amount of groups for (int i = 0; i < NrOfNormals * NrOfTexCoords; i++) { TexCoords.Add(new CVector2(br)); } } //Face Group Type if (br.HasTag("PTYP")) { NrOfFaceTypeGroups = br.ReadUInt32(); FaceTypes.AddRange(br.ReadBytes((int)NrOfFaceTypeGroups)); } //Face Groups if (br.HasTag("PCNT")) { NrOfFaceGroups = br.ReadUInt32(); for (int i = 0; i < NrOfFaceGroups; i++) { FaceGroups.Add(br.ReadUInt32()); } } //Indexes if (br.HasTag("PVTX")) { NrOfFaceVertices = br.ReadUInt32(); for (int i = 0; i < NrOfFaceVertices / 3; i++) { FaceVertices.Add(new CVertex(br)); } } //Vertex Groups if (br.HasTag("GNDX")) { NrOfVertexGroupIndices = br.ReadUInt32(); VertexGroupIndices.AddRange(br.ReadBytes((int)NrOfVertexGroupIndices)); } //Matrix Groups if (br.HasTag("MTGC")) { NrOfMatrixGroups = br.ReadUInt32(); for (int i = 0; i < NrOfMatrixGroups; i++) { MatrixGroups.Add(br.ReadUInt32()); } } //Matrix Indexes if (br.HasTag("MATS")) { NrOfMatrixIndexes = br.ReadUInt32(); for (int i = 0; i < NrOfMatrixIndexes; i++) { MatrixIndexes.Add(br.ReadUInt32()); } } //Bone Indexes if (br.HasTag("BIDX")) { NrOfBoneIndexes = br.ReadUInt32(); for (int i = 0; i < NrOfBoneIndexes; i++) { BoneIndexes.Add(br.ReadUInt32()); } } //Bone Weights if (br.HasTag("BWGT")) { NrOfBoneWeights = br.ReadUInt32(); for (int i = 0; i < NrOfBoneWeights; i++) { BoneWeights.Add(br.ReadUInt32()); } } MaterialId = br.ReadUInt32(); SelectionGroup = br.ReadUInt32(); Unselectable = br.ReadUInt32() == 1; Bounds = new CExtent(br); //Extents NrOfExtents = br.ReadUInt32(); for (int i = 0; i < NrOfExtents; i++) { Extents.Add(new CExtent(br)); } //Grouped Vertices for (int i = 0; i < NrOfVertices; i++) { if (!GroupedVertices.ContainsKey(VertexGroupIndices[i])) { GroupedVertices.Add(VertexGroupIndices[i], new List <CVector3>()); } GroupedVertices[VertexGroupIndices[i]].Add(Vertices[i]); } }
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); }
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 void Create(string filename) { if (!File.Exists(filename)) { Console.WriteLine("[E] Could not find: {0}", filename); return; } var vertices = new List <Vector3>(); var verticeIndice = new List <int>(); var texCoords = new List <Vector2>(); var texCoordIndice = new List <int>(); var normals = new List <Vector3>(); var normalIndice = new List <int>(); using (var objStream = new StreamReader(filename)) { while (!objStream.EndOfStream) { var line = objStream.ReadLine().Trim(); #region "Sort out Vertices" if (line.StartsWith("v ")) { var vertexParts = Functions.SplitString(line.Replace(" ", " "), " "); var vertice = new Vector3( float.Parse(vertexParts[1], CultureInfo.InvariantCulture.NumberFormat), float.Parse(vertexParts[2], CultureInfo.InvariantCulture.NumberFormat), float.Parse(vertexParts[3], CultureInfo.InvariantCulture.NumberFormat) ); vertices.Add(vertice); continue; } if (line.StartsWith("vt ")) { var vertexTexCoord = Functions.SplitString(line, " "); var texCoord = new Vector2( float.Parse(vertexTexCoord[1], CultureInfo.InvariantCulture.NumberFormat), float.Parse(vertexTexCoord[2], CultureInfo.InvariantCulture.NumberFormat) ); texCoords.Add(texCoord); continue; } if (line.StartsWith("vn ")) { var vertexNormal = Functions.SplitString(line, " "); var normal = new Vector3( float.Parse(vertexNormal[1], CultureInfo.InvariantCulture.NumberFormat), float.Parse(vertexNormal[2], CultureInfo.InvariantCulture.NumberFormat), float.Parse(vertexNormal[3], CultureInfo.InvariantCulture.NumberFormat) ); normals.Add(normal); continue; } #endregion #region "Faces" if (line.StartsWith("f ")) { var faceParts = Functions.SplitString(line, " ").ToList(); for (var f = 0; f < faceParts.Count; f++) { var face = Functions.SplitString(faceParts[f], "/"); if (face.Length < 2) { continue; } verticeIndice.Add(int.Parse(face[0]) - 1); texCoordIndice.Add(int.Parse(face[1]) - 1); normalIndice.Add(int.Parse(face[2]) - 1); } } #endregion } objStream.Close(); } int indice = 0; foreach (var item in verticeIndice) { Vertices.Add(vertices[item]); Indices.Add(indice++); } foreach (var item in texCoordIndice) { TexCoords.Add(texCoords[item]); } foreach (var item in normalIndice) { Normals.Add(normals[item]); } VertexArray.Upload(Vertices, Indices); VertexArray.Upload(TexCoords); VertexArray.Upload(Normals, new List <int>()); }
private void AddTexCoord(string values) { var fields = Split(values); TexCoords.Add(new Point(fields[0], 1 - fields[1])); }