void AppendIndex(int index, ObjLine line) { string[] indices = line.Tokens[index].Split('/'); // Required: Position int positionIndex = int.Parse(indices[0], CultureInfo.InvariantCulture) - positionsIndexOffset; int texCoordIndex = -1; int normalIndex = -1; // Optional: Texture coordinate if (indices.Length > 1 && indices[1].Equals(string.Empty) == false) { texCoordIndex = int.Parse(indices[1]) - textureCoordinatesIndexOffset; } // Optional: Normal if (indices.Length > 2 && indices[2].Equals(string.Empty) == false) { normalIndex = int.Parse(indices[2]) - normalsIndexOffset; } // Build vertex var vertex = new PositionNormalTextured { Position = positions[positionIndex] }; if (texCoordIndex >= 0) { vertex.TextureCoordinates = textureCoordinates[texCoordIndex]; } if (normalIndex >= 0) { vertex.Normal = normals[normalIndex]; } // check if the vertex does not already exists string hash = vertex.ToString(); int vertexIndex; if (!registeredVertices.TryGetValue(hash, out vertexIndex)) { stagingVertices.Add(vertex); vertexIndex = stagingVertices.Count - 1; registeredVertices.Add(hash, vertexIndex); } stagingIndices.Add(vertexIndex); }
void ParseMesh(ModelMesh modelMesh, BabylonScene scene, BabylonSkeleton skeleton) { var proxyID = ProxyMesh.CreateBabylonMesh(modelMesh.Name, scene); int indexName = 0; foreach (var part in modelMesh.MeshParts) { var material = exportedMaterials.First(m => m.Name == part.Effect.GetHashCode().ToString()); var indices = new ushort[part.PrimitiveCount * 3]; part.IndexBuffer.GetData(part.StartIndex * 2, indices, 0, indices.Length); if (part.VertexBuffer.VertexDeclaration.VertexStride > PositionNormalTextured.Stride) { var mesh = new Mesh <PositionNormalTexturedWeights>(material); var vertices = new PositionNormalTexturedWeights[part.NumVertices]; part.VertexBuffer.GetData(part.VertexOffset * part.VertexBuffer.VertexDeclaration.VertexStride, vertices, 0, vertices.Length, part.VertexBuffer.VertexDeclaration.VertexStride); for (int index = 0; index < vertices.Length; index++) { vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y; } mesh.AddPart(indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList()); mesh.CreateBabylonMesh(scene, proxyID, skeleton); } else { var mesh = new Mesh <PositionNormalTextured>(material); var vertices = new PositionNormalTextured[part.NumVertices]; part.VertexBuffer.GetData(part.VertexOffset * PositionNormalTextured.Stride, vertices, 0, vertices.Length, PositionNormalTextured.Stride); for (int index = 0; index < vertices.Length; index++) { vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y; } mesh.AddPart(indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList()); mesh.CreateBabylonMesh(scene, proxyID, skeleton); } indexName++; } }
/// <summary> /// Creates a new <see cref="Mesh"/> representing a textured sphere with spherical mapping. /// </summary> /// <param name="device">The <see cref="Device"/> to create the mesh in</param> /// <param name="radius">The radius of the sphere.</param> /// <param name="slices">The number of vertical slices to divide the sphere into.</param> /// <param name="stacks">The number of horizontal stacks to divide the sphere into.</param> /// <remarks>The sphere is formed like the one created by <see cref="Mesh.CreateSphere"/>.</remarks> public static Mesh Sphere(Device device, float radius, int slices, int stacks) { #region Sanity checks if (device == null) { throw new ArgumentNullException(nameof(device)); } if (slices <= 0) { throw new ArgumentOutOfRangeException(nameof(slices)); } if (stacks <= 0) { throw new ArgumentOutOfRangeException(nameof(stacks)); } #endregion int numVertexes = (slices + 1) * (stacks + 1); int numFaces = slices * stacks * 2; int indexCount = numFaces * 3; var mesh = new Mesh(device, numFaces, numVertexes, MeshFlags.Managed, PositionNormalTextured.Format); #region Build sphere vertexes var vertexes = new PositionNormalTextured[mesh.VertexCount]; int vertIndex = 0; for (int slice = 0; slice <= slices; slice++) { float alphaY = (float)slice / slices * (float)Math.PI * 2.0f; // Angle around Y-axis for (int stack = 0; stack <= stacks; stack++) { if (slice == slices) { vertexes[vertIndex] = vertexes[stack]; } else { var pnt = new PositionNormalTextured(); float alphaZ = ((stack - stacks * 0.5f) / stacks) * (float)Math.PI * 1.0f; // Angle around Z-axis pnt.X = (float)(Math.Cos(alphaY) * radius) * (float)Math.Cos(alphaZ); pnt.Z = (float)(Math.Sin(alphaY) * radius) * (float)Math.Cos(alphaZ); pnt.Y = (float)(Math.Sin(alphaZ) * radius); pnt.Nx = pnt.X / radius; pnt.Ny = pnt.Y / radius; pnt.Nz = pnt.Z / radius; pnt.Tv = 0.5f - (float)(Math.Asin(pnt.Y / radius) / Math.PI); vertexes.SetValue(pnt, vertIndex); } vertexes[vertIndex++].Tu = (float)slice / slices; } } #endregion BufferHelper.WriteVertexBuffer(mesh, vertexes); #region Build index buffer var indexes = new short[indexCount]; int i = 0; for (short x = 0; x < slices; x++) { var leftVertex = (short)((stacks + 1) * x); var rightVertex = (short)(leftVertex + stacks + 1); for (int y = 0; y < stacks; y++) { indexes[i++] = rightVertex; indexes[i++] = leftVertex; indexes[i++] = (short)(leftVertex + 1); indexes[i++] = rightVertex; indexes[i++] = (short)(leftVertex + 1); indexes[i++] = (short)(rightVertex + 1); leftVertex++; rightVertex++; } } #endregion BufferHelper.WriteIndexBuffer(mesh, indexes); return(mesh); }
void ParseMesh(ModelMesh modelMesh, BabylonScene scene, BabylonSkeleton skeleton, bool rightToLeft) { var proxyID = ProxyMesh.CreateBabylonMesh(modelMesh.Name, scene); int indexName = 0; foreach (var part in modelMesh.MeshParts) { var material = exportedMaterials.First(m => m.Name == part.Effect.GetHashCode().ToString()); var indices = new ushort[part.PrimitiveCount * 3]; part.IndexBuffer.GetData(part.StartIndex * 2, indices, 0, indices.Length); if (rightToLeft) { for (int ib = 0; ib < indices.Length; ib += 3) // reverse winding of triangles { ushort ti = indices[ib]; indices[ib] = indices[ib + 2]; indices[ib + 2] = ti; } } if (part.VertexBuffer.VertexDeclaration.VertexStride >= PositionNormalTexturedWeights.Stride) { var mesh = new Mesh<PositionNormalTexturedWeights>(material); var vertices = new PositionNormalTexturedWeights[part.NumVertices]; part.VertexBuffer.GetData(part.VertexOffset * part.VertexBuffer.VertexDeclaration.VertexStride, vertices, 0, vertices.Length, part.VertexBuffer.VertexDeclaration.VertexStride); for (int index = 0; index < vertices.Length; index++) { vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y; if (rightToLeft) { vertices[index].Position.Z = -vertices[index].Position.Z; vertices[index].Normal.Z = -vertices[index].Normal.Z; } } mesh.AddPart(modelMesh.Name+"#"+indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList()); mesh.CreateBabylonMesh(scene, proxyID, skeleton); } else { if (part.VertexBuffer.VertexDeclaration.VertexStride < PositionNormalTextured.Stride) return; // Error: Not a PositionNormalTextured mesh! var mesh = new Mesh<PositionNormalTextured>(material); var vertices = new PositionNormalTextured[part.NumVertices]; part.VertexBuffer.GetData(part.VertexOffset * part.VertexBuffer.VertexDeclaration.VertexStride, vertices, 0, vertices.Length, part.VertexBuffer.VertexDeclaration.VertexStride); for (int index = 0; index < vertices.Length; index++) { vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y; if (rightToLeft) { vertices[index].Position.Z = -vertices[index].Position.Z; vertices[index].Normal.Z = -vertices[index].Normal.Z; } } mesh.AddPart(modelMesh.Name + "#" + indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList()); mesh.CreateBabylonMesh(scene, proxyID, skeleton); } indexName++; } }
void ParseMesh(ModelMesh modelMesh, BabylonScene scene, BabylonSkeleton skeleton) { var proxyID = ProxyMesh.CreateBabylonMesh(modelMesh.Name, scene); int indexName = 0; foreach (var part in modelMesh.MeshParts) { var material = exportedMaterials.First(m => m.Name == part.Effect.GetHashCode().ToString()); var indices = new ushort[part.PrimitiveCount * 3]; part.IndexBuffer.GetData(part.StartIndex * 2, indices, 0, indices.Length); if (part.VertexBuffer.VertexDeclaration.VertexStride >= PositionNormalTexturedWeights.Stride) { var mesh = new Mesh<PositionNormalTexturedWeights>(material); var vertices = new PositionNormalTexturedWeights[part.NumVertices]; part.VertexBuffer.GetData(part.VertexOffset * part.VertexBuffer.VertexDeclaration.VertexStride, vertices, 0, vertices.Length, part.VertexBuffer.VertexDeclaration.VertexStride); for (int index = 0; index < vertices.Length; index++) { vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y; } mesh.AddPart(indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList()); mesh.CreateBabylonMesh(scene, proxyID, skeleton); } else { var mesh = new Mesh<PositionNormalTextured>(material); var vertices = new PositionNormalTextured[part.NumVertices]; part.VertexBuffer.GetData(part.VertexOffset * PositionNormalTextured.Stride, vertices, 0, vertices.Length, PositionNormalTextured.Stride); for (int index = 0; index < vertices.Length; index++) { vertices[index].TextureCoordinates.Y = 1.0f - vertices[index].TextureCoordinates.Y; } mesh.AddPart(indexName.ToString(), vertices.ToList(), indices.Select(i => (int)i).ToList()); mesh.CreateBabylonMesh(scene, proxyID, skeleton); } indexName++; } }
public Mesh(PositionNormalTextured[] vertices, int[] indices) { this.vertices = vertices; this.indices = new uint[indices.Length]; for (int c = 0; c < indices.Length; c++) { this.indices[c] = (uint)indices[c]; } Vector3[] points = new Vector3[vertices.Length]; for (int i = 0; i < vertices.Length; ++i) points[i] = vertices[i].Position; boundingSphere = SharpDX.BoundingSphere.FromPoints(points); }
private void LoadMeshFrom3ds(string filename, float scale) { // Force garbage collection to ensure that unmanaged resources are released. // Temporary workaround until unmanaged resource leak is identified GC.Collect(); int i; ushort sectionID; uint sectionLength; string name = ""; string material = ""; int triangleCount = 0; int vertexCount = 0; List<PositionNormalTextured> vertexList = new List<PositionNormalTextured>(); List<int> indexList = new List<int>(); List<int> attribList = new List<int>(); //List<int[]> applyLists = new List<int[]>(); //List<int> applyListsIndex = new List<int>(); List<string> materialNames = new List<string>(); int currentMaterialIndex = -1; Material currentMaterial = new Material(); int attributeID = 0; int count = 0; UInt16 lastID = 0; bool exit = false; bool normalMapFound = false; float offsetX = 0; float offsetY = 0; float offsetZ = 0; List<ObjectNode> objects = new List<ObjectNode>(); ObjectNode currentObject = null; List<int> objHierarchy = new List<int>(); List<string> objNames = new List<string>(); Dictionary<string, ObjectNode> objectTable = new Dictionary<string, ObjectNode>(); int dummyCount = 0; using (Stream fs = new FileStream(filename, FileMode.Open)) { BinaryReader br = new BinaryReader(fs); long length = fs.Length - 1; int startMapIndex = 0; int startTriangleIndex = 0; while (br.BaseStream.Position < length && !exit) //Loop to scan the whole file { sectionID = br.ReadUInt16(); sectionLength = br.ReadUInt32(); switch (sectionID) { //This section the begining of the file case 0x4d4d: break; // This section marks the edit section containing the 3d models (3d3d get it? very punny!) case 0x3d3d: break; // Object section contains meshes, etc. case 0x4000: name = ""; Byte b; do { b = br.ReadByte(); if (b > 0) { name += (char)b; } } while (b != '\0'); currentObject = new ObjectNode(); currentObject.Name = name; objects.Add(currentObject); if (!objectTable.ContainsKey(currentObject.Name)) { objectTable.Add(currentObject.Name, currentObject); } break; // Marks the start of a mesh section case 0x4100: startMapIndex = vertexList.Count; startTriangleIndex = indexList.Count / 3; break; // This section has the vertex list.. Maps to Vertext buffer in Direct3d case 0x4110: vertexCount = br.ReadUInt16(); for (i = 0; i < vertexCount; i++) { float x = br.ReadSingle() - offsetX; float y = br.ReadSingle() - offsetY; float z = br.ReadSingle() - offsetZ; PositionNormalTextured vert = new PositionNormalTextured(x * scale, z * scale, y * scale, 0, 0, 0, 0, 0); vertexList.Add(vert); } break; // This section is a tiangle index list. Maps to Index Buffer in Direct3d case 0x4120: { int triCount = br.ReadUInt16(); triangleCount += triCount; for (i = 0; i < triCount; i++) { int aa = br.ReadUInt16() + startMapIndex; int bb = br.ReadUInt16() + startMapIndex; int cc = br.ReadUInt16() + startMapIndex; indexList.Add(cc); indexList.Add(bb); indexList.Add(aa); UInt16 flags = br.ReadUInt16(); } } break; // Material for face from start face to triCount case 0x4130: { material = ""; i = 0; byte b1; do { b1 = br.ReadByte(); if (b1 > 0) { material += (char)b1; } i++; } while (b1 != '\0'); int triCount = br.ReadUInt16(); int[] applyList = new int[triCount]; attributeID = GetMaterialID(material, materialNames); for (i = 0; i < triCount; i++) { applyList[i] = br.ReadUInt16() + startTriangleIndex; } currentObject.ApplyLists.Add(applyList); currentObject.ApplyListsIndex.Add(attributeID); } break; // Section for UV texture maps case 0x4140: count = br.ReadUInt16(); for (i = 0; i < count; i++) { PositionNormalTextured vert = vertexList[startMapIndex + i]; Vector2 texCoord = new Vector2(br.ReadSingle(), FlipV ? (1.0f - br.ReadSingle()) : (br.ReadSingle())); vertexList[startMapIndex + i] = new PositionNormalTextured(vert.Position, Vector3.Zero, texCoord); } break; // Section for Smoothing Groups //case 0x4150: // count = br.ReadUInt16(); // for (i = 0; i < count; i++) // { // CustomVertex.PositionNormalTextured vert = vertexList[startMapIndex + i]; // vertexList[startMapIndex + i] = new CustomVertex.PositionNormalTextured(vert.Position, new Vector3(0,0,0), br.ReadSingle(), FlipV ? (1.0f - br.ReadSingle() ) : (br.ReadSingle())); // } // break; case 0x4160: float[] mat = new float[12]; for (i = 0; i < 12; i++) { mat[i] = br.ReadSingle(); } //offsetX = mat[9]; //offsetY = mat[11]; //offsetZ = mat[10]; if (objectTable.ContainsKey(name)) { objectTable[name].LocalMat = new Matrix3d( mat[0], mat[1], mat[2], 0, mat[3], mat[4], mat[5], 0, mat[6], mat[7], mat[8], 0, mat[9], mat[10], mat[11], 1); objectTable[name].LocalMat.Invert(); //objectTable[name].PivotPoint = new Vector3(mat[9]*mat[0],mat[10]*mat[1],mat[11]*mat[2]); } break; // Materials library section case 0xAFFF: break; // Material Name case 0xA000: { string matName = ""; i = 0; byte b2; do { b2 = br.ReadByte(); if (b2 > 0) { matName += (char)b2; } i++; } while (b2 != '\0'); materialNames.Add(matName); if (currentMaterialIndex > -1) { addMaterial(currentMaterial); } currentMaterialIndex++; currentMaterial = new Material(); currentMaterial.Diffuse = System.Drawing.Color.White; currentMaterial.Ambient = System.Drawing.Color.White; currentMaterial.Specular = System.Drawing.Color.Black; currentMaterial.SpecularSharpness = 30.0f; currentMaterial.Opacity = 1.0f; } break; // Ambient color case 0xA010: currentMaterial.Ambient = LoadColorChunk(br); break; // Diffuse color case 0xA020: currentMaterial.Diffuse = LoadColorChunk(br); break; // Specular color case 0xA030: currentMaterial.Specular = LoadColorChunk(br); break; // Specular power case 0xA040: // This is just a reasonable guess at the mapping from percentage to // specular exponent used by 3D Studio. currentMaterial.SpecularSharpness = 1.0f + 2 * LoadPercentageChunk(br); // Minimum sharpness of 10 enforced here because of bad specular exponents // in ISS model. // TODO: Fix ISS and permit lower specular exponents here currentMaterial.SpecularSharpness = Math.Max(10.0f, currentMaterial.SpecularSharpness); break; //Texture map file case 0xA200: break; // Texture file name case 0xA300: { string textureFilename = ""; i = 0; byte b2; do { b2 = br.ReadByte(); if (b2 > 0) { textureFilename += (char)b2; } i++; } while (b2 != '\0'); string path = filename.Substring(0, filename.LastIndexOf('\\') + 1); try { Texture11 tex = LoadTexture(path + textureFilename); if (tex != null) { meshTextures.Add(tex); meshFilenames.Add(textureFilename); // The ISS model has black for the diffuse color; to work around this // we'll set the diffuse color to white when there's a texture present. // The correct fix is to modify the 3ds model of ISS. currentMaterial.Diffuse = System.Drawing.Color.White; } else { meshTextures.Add(null); } } catch { meshTextures.Add(null); } } break; // Bump map case 0xA230: { float percentage = LoadPercentageChunk(br); int nameId = br.ReadUInt16(); uint nameBlockLength = br.ReadUInt32(); string textureFilename = ""; i = 0; byte b2; do { b2 = br.ReadByte(); if (b2 > 0) { textureFilename += (char)b2; } i++; } while (b2 != '\0'); string path = filename.Substring(0, filename.LastIndexOf('\\') + 1); try { Texture11 tex = LoadTexture(path + textureFilename); if (tex != null) { meshNormalMaps.Add(tex); meshFilenames.Add(textureFilename); // Indicate that we have a normal map so that we know to generate tangent vectors for the mesh normalMapFound = true; } else { meshNormalMaps.Add(null); } } catch { meshNormalMaps.Add(null); } } break; // Specular map case 0xA204: { float strength = LoadPercentageChunk(br); int nameId = br.ReadUInt16(); uint nameBlockLength = br.ReadUInt32(); string textureFilename = ""; i = 0; byte b2; do { b2 = br.ReadByte(); if (b2 > 0) { textureFilename += (char)b2; } i++; } while (b2 != '\0'); string path = filename.Substring(0, filename.LastIndexOf('\\') + 1); try { Texture11 tex = LoadTexture(path + textureFilename); if (tex != null) { meshSpecularTextures.Add(tex); meshFilenames.Add(textureFilename); // Set the current specular color from the specular texture strength int gray = (int)(255.99f * strength / 100.0f); currentMaterial.Specular = System.Drawing.Color.FromArgb(255, gray, gray, gray); } else { meshSpecularTextures.Add(null); } } catch { meshSpecularTextures.Add(null); } } break; case 0xB000: break; case 0xB002: break; case 0xB010: { name = ""; i = 0; byte b1; do { b1 = br.ReadByte(); if (b1 > 0) { name += (char)b1; } i++; } while (b1 != '\0'); int dum1 = (int)br.ReadUInt16(); int dum2 = (int)br.ReadUInt16(); int level = (int)br.ReadUInt16(); if (level == 65535) { level = -1; } if (name.StartsWith("$")) { dummyCount++; } else { objNames.Add(name); } objHierarchy.Add(level); if (objectTable.ContainsKey(name)) { objectTable[name].Level = level; } } break; case 0xB011: { name = ""; i = 0; byte b1; do { b1 = br.ReadByte(); if (b1 > 0) { name += (char)b1; } i++; } while (b1 != '\0'); objNames.Add( "$$$" + name); } break; case 0xB013: //pivot point float[] points = new float[3]; for (i = 0; i < 3; i++) { points[i] = br.ReadSingle(); } if (objectTable.ContainsKey(name)) { objectTable[name].PivotPoint = -new Vector3(points[0], points[1], points[2]); } break; case 0xB020: { float[] pos = new float[8]; for (i = 0; i < 8; i++) { pos[i] = br.ReadSingle(); } } break; // If we don't recognize a section then jump over it. Subract the header from the section length default: br.BaseStream.Seek(sectionLength - 6, SeekOrigin.Current); break; } lastID = sectionID; } br.Close(); if (currentMaterialIndex > -1) { addMaterial(currentMaterial); } } ////debug //for ( i = 0; i < 99; i++) //{ // System.Diagnostics.Debug.WriteLine(objNames[i]); //} //foreach (ObjectNode node in objects) //{ // System.Diagnostics.Debug.WriteLine(node.Name); //} ////debug // Generate vertex normals // Vertex normals are computed by averaging the normals of all faces // with an angle between them less than the crease angle. By setting // the crease angle to 0 degrees, the model will have a faceted appearance. // Right now, the smooth flag selects between one of two crease angles, // but some smoothing is always applied. float creaseAngleRad = MathUtil.DegreesToRadians(Smooth ? 70.0f : 45.0f); Vector3[] vertexNormals = CalculateVertexNormalsMerged(vertexList, indexList, creaseAngleRad); List<PositionNormalTextured> newVertexList = new List<PositionNormalTextured>(); int newVertexCount = triangleCount * 3; for (int vertexIndex = 0; vertexIndex < newVertexCount; ++vertexIndex) { PositionNormalTextured v = vertexList[indexList[vertexIndex]]; v.Normal = vertexNormals[vertexIndex]; newVertexList.Add(v); } // Use the triangle mesh and material assignments to create a single // index list for the mesh. List<uint> newIndexList = new List<uint>(); foreach (ObjectNode node in objects) { List<Mesh.Group> materialGroups = new List<Mesh.Group>(); for (i = 0; i < node.ApplyLists.Count; i++) { int matId = node.ApplyListsIndex[i]; int startIndex = newIndexList.Count; foreach (int triangleIndex in node.ApplyLists[i]) { newIndexList.Add((uint)(triangleIndex * 3)); newIndexList.Add((uint)(triangleIndex * 3 + 1)); newIndexList.Add((uint)(triangleIndex * 3 + 2)); } var group = new Mesh.Group(); group.startIndex = startIndex; group.indexCount = node.ApplyLists[i].Length * 3; group.materialIndex = matId; materialGroups.Add(group); } node.DrawGroup = materialGroups; } // Turn objects into tree Stack<ObjectNode> nodeStack = new Stack<ObjectNode>(); List<ObjectNode> nodeTreeRoot = new List<ObjectNode>(); ObjectNode rootDummy = new ObjectNode(); rootDummy.Name = "Root"; rootDummy.Parent = null; rootDummy.Level = -1; rootDummy.DrawGroup = null; int currentLevel = -1; nodeStack.Push(rootDummy); nodeTreeRoot.Add(rootDummy); for (i = 0; i < objHierarchy.Count; i++) { int level = objHierarchy[i]; if (level <= currentLevel) { // pop out all the nodes to intended parent while (level <= nodeStack.Peek().Level && nodeStack.Count > 1) { nodeStack.Pop(); } currentLevel = level; } if (objNames[i].StartsWith("$$$")) { ObjectNode dummy = new ObjectNode(); dummy.Name = objNames[i].Replace("$$$", ""); dummy.Parent = nodeStack.Peek(); dummy.Parent.Children.Add(dummy); dummy.Level = currentLevel = level; dummy.DrawGroup = null; nodeStack.Push(dummy); } else { objectTable[objNames[i]].Level = currentLevel = level; objectTable[objNames[i]].Parent = nodeStack.Peek(); objectTable[objNames[i]].Parent.Children.Add(objectTable[objNames[i]]); nodeStack.Push(objectTable[objNames[i]]); } } if (objHierarchy.Count == 0) { foreach (ObjectNode node in objects) { rootDummy.Children.Add(node); node.Parent = rootDummy; } } if (normalMapFound) { // If we've got a normal map, we want to generate tangent vectors for the mesh // Mapping of vertices to geometry is extremely straightforward now, but this could // change when a mesh optimization step is introduced. var tangentIndexList = new List<uint>(); for (uint tangentIndex = 0; tangentIndex < newVertexCount; ++tangentIndex) { tangentIndexList.Add(tangentIndex); } Vector3[] tangents = CalculateVertexTangents(newVertexList, tangentIndexList, creaseAngleRad); // Copy the tangents in the vertex data list var vertices = new PositionNormalTexturedTangent[newVertexList.Count]; int vertexIndex = 0; foreach (PositionNormalTextured v in newVertexList) { PositionNormalTexturedTangent tvertex = new PositionNormalTexturedTangent(v.Position, v.Normal, new Vector2(v.Tu, v.Tv), tangents[vertexIndex]); vertices[vertexIndex] = tvertex; ++vertexIndex; } mesh = new Mesh(vertices, newIndexList.ToArray()); } else { mesh = new Mesh(newVertexList.ToArray(), newIndexList.ToArray()); } Objects = nodeTreeRoot; mesh.setObjects(nodeTreeRoot); mesh.commitToDevice(RenderContext11.PrepDevice); dirty = false; GC.Collect(); }
public Mesh(PositionNormalTextured[] vertices, uint[] indices) { this.vertices = vertices; this.indices = indices; var points = new Vector3[vertices.Length]; for (var i = 0; i < vertices.Length; ++i) points[i] = vertices[i].Position; boundingSphere = BoundingSphere.FromPoints(points); }
public SkyFace(string textureName, SkyFaceSide faceSide) { this.vertexBuffer = VertexBuffer.CreateGeneric <PositionNormalTextured>( GameEngine.Device, 4, Usage.WriteOnly, PositionNormalTextured.Format, Pool.Managed, null); this.corners = this.vertexBuffer.Lock <PositionNormalTextured>(0, 0, LockFlags.None); PositionNormalTextured[] data = new PositionNormalTextured[4]; switch (faceSide) { case SkyFaceSide.Top: //Y always 100; //back x -100; front X +100; //back Z -100; front Z +100 data[0].X = -100f; data[0].Y = 100f; data[0].Z = -100f; data[0].U = 0f; data[0].V = 1f; data[0].Nx = 0f; data[0].Ny = -1f; data[0].Nz = 0f; data[1].X = 100f; data[1].Y = 100f; data[1].Z = -100f; data[1].U = 0f; data[1].V = 0f; data[1].Nx = 0f; data[1].Ny = -1f; data[1].Nz = 0f; data[2].X = -100f; data[2].Y = 100f; data[2].Z = 100f; data[2].U = 1f; data[2].V = 1f; data[2].Nx = 0; data[2].Ny = -1f; data[2].Nz = 0f; data[3].X = 100f; data[2].Y = 100f; data[3].Z = 100f; data[3].U = 1f; data[3].V = 0f; data[3].Nx = 0f; data[3].Ny = -1f; data[3].Nz = 0f; break; case SkyFaceSide.Bottom: data[0].X = -100.0f; // nw data[0].Y = -100.0f; data[0].Z = 100.0f; data[0].U = 0.0f; data[0].V = 0.0f; data[0].Nx = 0.0f; data[0].Ny = 1.0f; data[0].Nz = 0.0f; data[1].X = 100.0f; // ne data[1].Y = -100.0f; data[1].Z = 100.0f; data[1].U = 1.0f; data[1].V = 1.0f; data[1].Nx = 0.0f; data[1].Ny = 1.0f; data[1].Nz = 0.0f; data[2].X = -100.0f; // sw data[2].Y = -100.0f; data[2].Z = -100.0f; data[2].U = 1.0f; data[2].V = 0.0f; data[2].Nx = 0.0f; data[2].Ny = 1.0f; data[2].Nz = 0.0f; data[3].X = 100.0f; // se data[3].Y = -100.0f; data[3].Z = -100.0f; data[3].U = 0.0f; data[3].V = 1.0f; data[3].Nx = 0.0f; data[3].Ny = 1.0f; data[3].Nz = 0.0f; break; case SkyFaceSide.Left: data[0].X = -100.0f; // upper south data[0].Y = 100.0f; data[0].Z = -100.0f; data[0].U = 0.0f; data[0].V = 0.0f; data[0].Nx = 1.0f; data[0].Ny = 0.0f; data[0].Nz = 0.0f; data[1].X = -100.0f; // upper north data[1].Y = 100.0f; data[1].Z = 100.0f; data[1].U = 1.0f; data[1].V = 0.0f; data[1].Nx = 1.0f; data[1].Ny = 0.0f; data[1].Nz = 0.0f; data[2].X = -100.0f; // lower south data[2].Y = -100.0f; data[2].Z = -100.0f; data[2].U = 0.0f; data[2].V = 1.0f; data[2].Nx = 1.0f; data[2].Ny = 0.0f; data[2].Nz = 0.0f; data[3].X = -100.0f; // lower north data[3].Y = -100.0f; data[3].Z = 100.0f; data[3].U = 1.0f; data[3].V = 1.0f; data[3].Nx = 1.0f; data[3].Ny = 0.0f; data[3].Nz = 0.0f; break; case SkyFaceSide.Right: data[0].X = 100.0f; // upper ne data[0].Y = 100.0f; data[0].Z = 100.0f; data[0].U = 0.0f; data[0].V = 0.0f; data[0].Nx = -1.0f; data[0].Ny = 0.0f; data[0].Nz = 0.0f; data[1].X = 100.0f; // upper se data[1].Y = 100.0f; data[1].Z = -100.0f; data[1].U = 1.0f; data[1].V = 0.0f; data[1].Nx = -1.0f; data[1].Ny = 0.0f; data[1].Nz = 0.0f; data[2].X = 100.0f; // lower ne data[2].Y = -100.0f; data[2].Z = 100.0f; data[2].U = 0.0f; data[2].V = 1.0f; data[2].Nx = -1.0f; data[2].Ny = 0.0f; data[2].Nz = 0.0f; data[3].X = 100.0f; // lower se data[3].Y = -100.0f; data[3].Z = -100.0f; data[3].U = 1.0f; data[3].V = 1.0f; data[3].Nx = -1.0f; data[3].Ny = 0.0f; data[3].Nz = 0.0f; break; case SkyFaceSide.Front: data[0].X = -100.0f; // upper nw data[0].Y = 100.0f; data[0].Z = 100.0f; data[0].U = 0.0f; data[0].V = 0.0f; data[0].Nx = 0.0f; data[0].Ny = 0.0f; data[0].Nz = -1.0f; data[1].X = 100.0f; // upper ne data[1].Y = 100.0f; data[1].Z = 100.0f; data[1].U = 1.0f; data[1].V = 0.0f; data[1].Nx = 0.0f; data[1].Ny = 0.0f; data[1].Nz = -1.0f; data[2].X = -100.0f; // lower nw data[2].Y = -100.0f; data[2].Z = 100.0f; data[2].U = 0.0f; data[2].V = 1.0f; data[2].Nx = 0.0f; data[2].Ny = 0.0f; data[2].Nz = -1.0f; data[3].X = 100.0f; // lower ne data[3].Y = -100.0f; data[3].Z = 100.0f; data[3].U = 1.0f; data[3].V = 1.0f; data[3].Nx = 0.0f; data[3].Ny = 0.0f; data[3].Nz = -1.0f; break; case SkyFaceSide.Back: data[0].X = 100.0f; // upper se data[0].Y = 100.0f; data[0].Z = -100.0f; data[0].U = 0.0f; data[0].V = 0.0f; data[0].Nx = 0.0f; data[0].Ny = 0.0f; data[0].Nz = -1.0f; data[1].X = -100.0f; // upper sw data[1].Y = 100.0f; data[1].Z = -100.0f; data[1].U = 1.0f; data[1].V = 0.0f; data[1].Nx = 0.0f; data[1].Ny = 0.0f; data[1].Nz = -1.0f; data[2].X = 100.0f; // lower se data[2].Y = -100.0f; data[2].Z = -100.0f; data[2].U = 0.0f; data[2].V = 1.0f; data[2].Nx = 0.0f; data[2].Ny = 0.0f; data[2].Nz = -1.0f; data[3].X = -100.0f; // lower sw data[3].Y = -100.0f; data[3].Z = -100.0f; data[3].U = 1.0f; data[3].V = 1.0f; data[3].Nx = 0.0f; data[3].Ny = 0.0f; data[3].Nz = -1.0f; break; } this.corners.Write(data); this.vertexBuffer.Unlock(); this.texture = new Texture(GameEngine.Device, textureName); this.valid = true; }