/// <summary> /// Loads this SBM model /// </summary> /// <returns></returns> public bool Load(out string err) { // Check the file exists if (!File.Exists(filename)) { err = "File not found"; return false; } // Load it using (FileStream strm = File.OpenRead(filename)) { // Create reader BinaryReader rdr = new BinaryReader(strm); // Read header string magic = new string(rdr.ReadChars(4)); if (magic != "SBM\0") { err = "Specified file is not an SBM file"; return false; } int version = rdr.ReadInt32(); if (version != 1) { err = "Unsupported SBM version"; return false; } int num_materials = rdr.ReadInt32(); int num_meshes = rdr.ReadInt32(); // Read all materials string[] materials = new string[num_materials]; for (int i = 0; i < num_materials; i++) materials[i] = rdr.ReadNullTerminatedString(); // Read all meshes meshes = new SBMMesh[num_meshes]; for (int i = 0; i < num_meshes; i++) { // Read mesh header int num_vertices = rdr.ReadInt32(); int num_submeshes = rdr.ReadInt32(); // Create mesh builder MeshBuilder builder = new MeshBuilder(); builder.UseNormals = true; builder.UseTexCoords = true; builder.UseTangents = true; // Read all vertices for (int j = 0; j < num_vertices; j++) { builder.AddPosition(new Vector3(rdr.ReadSingle(), rdr.ReadSingle(), rdr.ReadSingle())); builder.AddNormal(new Vector3(rdr.ReadSingle(), rdr.ReadSingle(), rdr.ReadSingle())); builder.AddTextureCoord(new Vector2(rdr.ReadSingle(), rdr.ReadSingle())); builder.AddTangent(new Vector3(rdr.ReadSingle(), rdr.ReadSingle(), rdr.ReadSingle())); } // Loop each submesh string[] meshmats = new string[num_submeshes]; for (int j = 0; j < num_submeshes; j++) { // Read submesh header int num_indices = rdr.ReadInt32(); int material_index = rdr.ReadInt32(); meshmats[j] = materials[material_index]; // Read all indices for (int k = 0; k < num_indices; k++) builder.AddIndex(j, rdr.ReadUInt32()); } // Add element to mesh array SBMMesh sbmmesh = new SBMMesh(); sbmmesh.Mesh = builder.Build(); sbmmesh.Materials = meshmats; meshes[i] = sbmmesh; } } // Success err = null; return true; }
public static Mesh BuildPlane(bool texcoords, bool tangents) { // Create mesh builder MeshBuilder builder = new MeshBuilder(); builder.UseNormals = true; builder.UseTexCoords = texcoords; builder.UseTangents = tangents; // Add vertices builder.AddPosition(new Vector3(0.0f, 0.0f, 0.0f)); builder.AddPosition(new Vector3(0.0f, 0.0f, 1.0f)); builder.AddPosition(new Vector3(1.0f, 0.0f, 1.0f)); builder.AddPosition(new Vector3(1.0f, 0.0f, 0.0f)); builder.AddNormal(Vector3.UnitY); builder.AddNormal(Vector3.UnitY); builder.AddNormal(Vector3.UnitY); builder.AddNormal(Vector3.UnitY); if (texcoords) { builder.AddTextureCoord(new Vector2(0.0f, 1.0f)); builder.AddTextureCoord(new Vector2(1.0f, 1.0f)); builder.AddTextureCoord(new Vector2(1.0f, 0.0f)); builder.AddTextureCoord(new Vector2(0.0f, 0.0f)); } if (tangents) { builder.AddTangent(new Vector3(1.0f, 0.0f, 0.0f)); builder.AddTangent(new Vector3(1.0f, 0.0f, 0.0f)); builder.AddTangent(new Vector3(1.0f, 0.0f, 0.0f)); builder.AddTangent(new Vector3(1.0f, 0.0f, 0.0f)); } // Add indices builder.AddIndex(0); builder.AddIndex(1); builder.AddIndex(2); builder.AddIndex(2); builder.AddIndex(3); builder.AddIndex(0); // Build mesh return builder.Build(); }
public static Mesh BuildSphere(float radius, int subdivisions, bool usetexcoords, bool usetangents) { // Starting points var A = new Vector3(-1.0f, -(1.0f / Root3), -(1.0f / Root6)); var B = new Vector3(0.0f, 2.0f / Root3, -1.0f / Root6); var C = new Vector3(1.0f, -(1.0f / Root3), -(1.0f / Root6)); var D = new Vector3(0.0f, 0.0f, 3.0f / Root6); // Build a triangular based pyramid var tris = new List<Triangle>(); tris.Add(new Triangle(A, B, C)); tris.Add(new Triangle(C, D, A)); tris.Add(new Triangle(B, D, C)); tris.Add(new Triangle(A, D, B)); var tmplist = new List<Triangle>(); // Run subdivide passes for (int i = 0; i < subdivisions; i++) { // Normalise all vertices for (int j = 0; j < tris.Count; j++) { Triangle tri = tris[j]; tri.A.Normalize(); tri.A *= radius; tri.B.Normalize(); tri.B *= radius; tri.C.Normalize(); tri.C *= radius; tris[j] = tri; } // Check for last pass if (i == subdivisions - 1) break; // Subdivide all triangles tmplist.Clear(); for (int j = 0; j < tris.Count; j++) { Triangle tri = tris[j]; Vector3 midAB = (tri.A + tri.B) * 0.5f; Vector3 midBC = (tri.B + tri.C) * 0.5f; Vector3 midCA = (tri.C + tri.A) * 0.5f; tmplist.Add(new Triangle(tri.A, midAB, midCA)); tmplist.Add(new Triangle(midAB, midBC, midCA)); tmplist.Add(new Triangle(midCA, midBC, tri.C)); tmplist.Add(new Triangle(midAB, tri.B, midBC)); } // Swap the lists var tmp = tris; tris = tmplist; tmplist = tmp; } // Create builder var builder = new MeshBuilder(); builder.UseNormals = true; builder.UseTexCoords = usetexcoords; builder.UseTangents = usetangents; for (int i = 0; i < tris.Count; i++) { Triangle tri = tris[i]; builder.AddPosition(tri.A); builder.AddPosition(tri.B); builder.AddPosition(tri.C); builder.AddNormal(GetNormal(tri.A)); builder.AddNormal(GetNormal(tri.B)); builder.AddNormal(GetNormal(tri.C)); if (usetangents) { builder.AddTangent(GetSphereTangent(tri.A)); builder.AddTangent(GetSphereTangent(tri.B)); builder.AddTangent(GetSphereTangent(tri.C)); } if (usetexcoords) { // TODO: This builder.AddTextureCoord(new Vector2(0.0f, 0.0f)); builder.AddTextureCoord(new Vector2(0.0f, 0.0f)); builder.AddTextureCoord(new Vector2(0.0f, 0.0f)); } builder.AddIndex((ushort)(i * 3)); builder.AddIndex((ushort)(i * 3 + 1)); builder.AddIndex((ushort)(i * 3 + 2)); } // Create mesh return builder.Build(); }
public static Mesh BuildHeightmap(HeightSampler sampler, int width, int height, float tilesize, int subdivide = 1) { // Determine sizes int totalW = width * subdivide; int totalH = height * subdivide; float invtotalW = 1.0f / totalW; float invtotalH = 1.0f / totalH; // Precache an array of heights float[,] heights = new float[totalW, totalH]; for (int x = 0; x < totalW; x++) { float fX = x * invtotalW * width; for (int y = 0; y < totalH; y++) { float fY = y * invtotalH * height; heights[x, y] = sampler(fX, fY); } } // Recreate the sampler to use the cache sampler = new HeightSampler((x, y) => { int ix = (int)(x * subdivide); int iy = (int)(y * subdivide); if (ix < 0) ix = 0; if (iy < 0) iy = 0; if (ix >= totalW) ix = totalW - 1; if (iy >= totalH) iy = totalH - 1; return heights[ix, iy]; }); // Prepare the builder MeshBuilder builder = new MeshBuilder(); builder.UseNormals = true; builder.UseTangents = true; // Perform the loop for (int x = 0; x < totalW; x++) { float fX = x * invtotalW * width; for (int y = 0; y < totalH; y++) { float fY = y * invtotalH * height; builder.AddPosition(new Vector3(fX * tilesize, sampler(fX, fY), fY * tilesize)); builder.AddNormal(CalculateNormal(sampler, fX, fY)); builder.AddTangent(CalculateTangent(sampler, fX, fY)); if ((x < totalW - 1) && (y < totalH - 1)) { int idx = (x * totalH) + y; builder.AddIndex((ushort)idx); builder.AddIndex((ushort)(idx + 1)); builder.AddIndex((ushort)(idx + totalH + 1)); builder.AddIndex((ushort)(idx + totalH + 1)); builder.AddIndex((ushort)(idx + totalH)); builder.AddIndex((ushort)idx); } } } return builder.Build(); }