/// <summary> /// Gathers all the indices of the surfaces of a submesh /// </summary> /// <param name="subMesh"></param> /// <returns></returns> public static IEnumerable <int> GetAllIndices(this BXDAMesh.BXDASubMesh subMesh) { IEnumerable <int> indices = new List <int>(); subMesh.surfaces.ForEach((s) => indices = indices.Concat(s.indicies)); return(indices); }
public static void GetCombinedMesh(List <BXDAMesh.BXDASubMesh> meshes, HandleMesh handleMesh) { BXDAMesh.BXDASubMesh combinedMesh = new BXDAMesh.BXDASubMesh(); combinedMesh.verts = new double[0]; combinedMesh.norms = new double[0]; combinedMesh.surfaces = new List <BXDAMesh.BXDASurface>(); foreach (BXDAMesh.BXDASubMesh mesh in meshes) { double[] oldVertices = combinedMesh.verts; double[] newVertices = new double[oldVertices.Length + mesh.verts.Length]; oldVertices.CopyTo(newVertices, 0); mesh.verts.CopyTo(newVertices, oldVertices.Length); combinedMesh.verts = newVertices; double[] oldNorms = combinedMesh.verts; double[] newNorms = new double[oldNorms.Length + mesh.norms.Length]; oldNorms.CopyTo(newNorms, 0); mesh.norms.CopyTo(newNorms, oldNorms.Length); combinedMesh.norms = newNorms; combinedMesh.surfaces.AddRange(mesh.surfaces); } List <BXDAMesh.BXDASubMesh> combinedMeshes = new List <BXDAMesh.BXDASubMesh>(); combinedMeshes.Add(combinedMesh); ReadMeshSet(combinedMeshes, delegate(int id, BXDAMesh.BXDASubMesh subMesh, Mesh mesh) { handleMesh(id, subMesh, mesh); }); }
/// <summary> /// Used for creating a hull from the given BXDAMesh.BXDASubmesh. /// </summary> /// <param name="subMesh"></param> /// <param name="decompose"></param> /// <returns></returns> public static BXDAMesh.BXDASubMesh GetHull(BXDAMesh.BXDASubMesh subMesh) { List <int> indices = new List <int>(); foreach (BXDAMesh.BXDASurface surface in subMesh.surfaces) { indices.AddRange(surface.indicies); } IVHACD decomposer = new IVHACD(); ConvexLibraryWrapper.Parameters parameters = new ConvexLibraryWrapper.Parameters(); parameters.m_depth = 1; parameters.m_concavity = 1; if (!decomposer.Compute(Array.ConvertAll <double, float>(subMesh.verts, (d) => (float)d), 3, (uint)subMesh.verts.Length / 3, indices.ToArray(), 3, (uint)indices.Count / 3, parameters)) { return(null); } ConvexLibraryWrapper.ConvexHull result = decomposer.GetConvexHull(0); BXDAMesh.BXDASubMesh resultMesh = ExportSubMesh(Array.ConvertAll <double, float>(result.m_points, (d) => (float)d), result.m_nPoints, Array.ConvertAll <int, uint>(result.m_triangles, (i) => (uint)i), result.m_nTriangles); decomposer.Cancel(); decomposer.Clean(); decomposer.Release(); return(resultMesh); }
/// <summary> /// Gets all of the vertices referenced by the indices of all the surfaces in the mesh. /// </summary> /// <param name="mesh"></param> /// <returns></returns> public static Vector3[] GetindexedVertices(this BXDAMesh.BXDASubMesh mesh) { IEnumerable <int> indices = mesh.GetAllIndices(); Vector3[] verts = mesh.GetVertexData(); return((from int i in indices select verts[i]).ToArray()); }
/// <summary> /// Wraps the given raw mesh as a BXDA Submesh with a single surface. /// </summary> /// <param name="verts">The verticies. (3 elements per vertex)</param> /// <param name="vertCount">The vertex count.</param> /// <param name="inds">The index buffer. (3 element per triangle, zero based)</param> /// <param name="trisCount">The triangle count</param> /// <returns>The resulting mesh</returns> private static BXDAMesh.BXDASubMesh ExportSubMesh(float[] verts, uint vertCount, uint[] inds, uint trisCount) { Simplify(ref verts, ref vertCount, ref inds, ref trisCount); BXDAMesh.BXDASubMesh sub = new BXDAMesh.BXDASubMesh(); sub.norms = null; sub.verts = new double[verts.Length]; for (uint i2 = 0; i2 < vertCount * 3; i2++) { sub.verts[i2] = verts[i2]; } BXDAMesh.BXDASurface collisionSurface = new BXDAMesh.BXDASurface(); collisionSurface.indicies = new int[inds.Length]; for (uint i2 = 0; i2 < trisCount * 3; i2++) { collisionSurface.indicies[i2] = (int)inds[i2]; } sub.surfaces = new List <BXDAMesh.BXDASurface>(); sub.surfaces.Add(collisionSurface); return(sub); }
/// <summary> /// Adds the <see cref="outputVerts"/> and <see cref="outputMeshSurfaces"/> to the <see cref="outputMesh"/>. /// </summary> private void DumpOutputInternal() { if (outputVerts.count == 0 || outputMeshSurfaces.Count == 0) { return; } // Copy the output surface's vertices and normals into the new sub-object BXDAMesh.BXDASubMesh subObject = new BXDAMesh.BXDASubMesh(); subObject.verts = new double[outputVerts.count * 3]; subObject.norms = new double[outputVerts.count * 3]; Array.Copy(outputVerts.coordinates, 0, subObject.verts, 0, outputVerts.count * 3); Array.Copy(outputVerts.norms, 0, subObject.norms, 0, outputVerts.count * 3); // Copy the output surfaces into the new sub-object subObject.surfaces = new List <BXDAMesh.BXDASurface>(outputMeshSurfaces); // Add the sub-object to the output mesh lock (outputMesh) outputMesh.meshes.Add(subObject); // Empty temporary storage outputVerts.count = 0; outputMeshSurfaces.Clear(); }
private void DumpMeshBuffer() { // Make sure all index copy threads have completed. if (waitingThreads.Count > 0) { // Console.WriteLine("Got ahead of ourselves...."); System.Threading.WaitHandle.WaitAll(waitingThreads.ToArray()); waitingThreads.Clear(); } if (postSurface.vertCount == 0 || postSurface.facetCount == 0) { return; } BXDAMesh.BXDASubMesh subObject = new BXDAMesh.BXDASubMesh(); subObject.verts = new double[postSurface.vertCount * 3]; subObject.norms = new double[postSurface.vertCount * 3]; Array.Copy(postSurface.verts, 0, subObject.verts, 0, postSurface.vertCount * 3); Array.Copy(postSurface.norms, 0, subObject.norms, 0, postSurface.vertCount * 3); Console.WriteLine("Mesh segment " + outputMesh.meshes.Count + " has " + postSurface.vertCount + " verts and " + postSurface.facetCount + " facets"); subObject.surfaces = new List <BXDAMesh.BXDASurface>(postSurfaces); outputMesh.meshes.Add(subObject); postSurface.vertCount = 0; postSurface.facetCount = 0; postSurfaces = new List <BXDAMesh.BXDASurface>(); }
/// <summary> /// Gets the center of a sub mesh that uses the given vertices /// </summary> /// <param name="subMesh"></param> /// <param name="vertices"></param> /// <returns></returns> public static Vector3 MeshCenter(BXDAMesh.BXDASubMesh subMesh) { IEnumerable <int> indices = subMesh.GetAllIndices(); Vector3[] vertices = subMesh.GetVertexData(); return((from int i in indices select vertices[i]).Aggregate(Vector3.Add) / indices.Count()); }
/// <summary> /// Returns a bullet mesh centered around the origin /// </summary> /// <param name="subMesh"></param> /// <param name="vertices"></param> /// <returns></returns> public static StridingMeshInterface CenteredBulletShapeFromSubMesh(BXDAMesh.BXDASubMesh subMesh) { IEnumerable <int> indices = subMesh.GetAllIndices(); Vector3[] vertices = subMesh.GetVertexData(); Vector3 center = MeshCenter(from int i in indices select vertices[i]); return(BulletShapeFromSubMesh(subMesh, -center)); }
public Mesh(BXDAMesh.BXDASubMesh mesh, Vector3 position) { Vector3[] vertData = MeshUtilities.DataToVector(mesh.verts); Vector3[] normsData = MeshUtilities.DataToVector(mesh.norms); vertexData = mesh.verts; //Translate objects for (int i = 0; i < vertexData.Length;) { vertexData[i++] += position.X; vertexData[i++] += position.Y; vertexData[i++] += position.Z; } for (int i = 0; i < vertData.Length; i++) { vertData[i] *= 0.001f; } vertices = new List <Vertex>(); //for(int i = 0; i < vertData.Length; i++) //{ // Vertex toAdd = new Vertex() // { // position = vertData[i], // normal = normsData[i], // texCoord = new Vector2(0, 0) // }; // vertices.Add(toAdd); //} vertices = vertData.Zip(normsData, (v, n) => new Vertex { position = v, normal = n, texCoord = new Vector2(0, 0) }).ToList(); indices = new List <int>(); mesh.surfaces.ForEach((s) => indices = new List <int>(indices.Concat(s.indicies))); IEnumerable <double> temp = vertexData.Zip(indices, (v, i) => vertexData[i]); //vertexData = temp.ToArray(); textures = new List <Texture>(); setupMesh(); }
/// <summary> /// Turns a BXDA mesh into a CompoundShape centered around the origin /// </summary> /// <param name="mesh"></param> /// <returns></returns> private static CompoundShape GetShape(BXDAMesh mesh) { CompoundShape shape = new CompoundShape(); Vector3[] meshVertices = mesh.AllColliderVertices().ToArray(); for (int i = 0; i < mesh.colliders.Count; i++) { BXDAMesh.BXDASubMesh sub = mesh.colliders[i]; Vector3[] vertices = sub.GetVertexData(); StridingMeshInterface sMesh = MeshUtilities.CenteredBulletShapeFromSubMesh(sub); //Add the shape at a location relative to the compound shape such that the compound shape is centered at (0, 0) but child shapes are properly placed shape.AddChildShape(Matrix4.CreateTranslation(MeshUtilities.MeshCenterRelative(sub, mesh)), new ConvexTriangleMeshShape(sMesh)); Console.WriteLine("Successfully created and added sub shape"); } return(shape); }
public static void ReadMeshSet(List <BXDAMesh.BXDASubMesh> meshes, HandleMesh handleMesh, bool mirror = false) { for (int j = 0; j < meshes.Count; j++) { BXDAMesh.BXDASubMesh sub = meshes[j]; //takes all of the required information from the API (the API information is within "sub" above) Vector3[] vertices = sub.verts == null ? null : ArrayUtilities.WrapArray <Vector3>( delegate(double x, double y, double z) { return(new Vector3((float)x * (mirror ? -0.01f : 0.01f), (float)y * 0.01f, (float)z * 0.01f)); }, sub.verts); Vector3[] normals = sub.norms == null ? null : ArrayUtilities.WrapArray <Vector3>( delegate(double x, double y, double z) { return(new Vector3((float)x, (float)y, (float)z)); }, sub.norms); Mesh unityMesh = new Mesh(); unityMesh.vertices = vertices; unityMesh.normals = normals; unityMesh.uv = new Vector2[vertices.Length]; unityMesh.subMeshCount = sub.surfaces.Count; for (int i = 0; i < sub.surfaces.Count; i++) { int[] cpy = new int[sub.surfaces[i].indicies.Length]; Array.Copy(sub.surfaces[i].indicies, cpy, cpy.Length); if (mirror) { Array.Reverse(cpy); } unityMesh.SetTriangles(cpy, i); } if (normals != null) { unityMesh.RecalculateNormals(); } handleMesh(j, sub, unityMesh); } }
/// <summary> /// Returns a bullet mesh shape given a BXDA sub mesh and a list of vectors to index from /// </summary> /// <param name="subMesh"></param> /// <param name="vertices"></param> /// <returns></returns> public static StridingMeshInterface BulletShapeFromSubMesh(BXDAMesh.BXDASubMesh subMesh) { return(new TriangleIndexVertexArray(subMesh.GetAllIndices().ToArray(), subMesh.GetVertexData())); }
/// <summary> /// Executes the actual exporting. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void exporter_DoWork(object sender, DoWorkEventArgs e) { string directory = FIELD_FOLDER + fieldNameTextBox.Text; // Create directory if it does not exist if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } // Warn user of overwrite if it does exist else if (MessageBox.Show("A field with this name already exists. Continue?", "Overwrite Existing Field", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { e.Cancel = true; return; } FieldDefinition fieldDefinition = FieldDefinition.Factory(Guid.NewGuid(), Program.ASSEMBLY_DOCUMENT.DisplayName); foreach (PropertySet ps in Program.MAINWINDOW.GetPropertySetsTabControl().TranslateToPropertySets()) { fieldDefinition.AddPropertySet(ps); } SurfaceExporter surfaceExporter = new SurfaceExporter(); List <string> exportedMeshes = new List <string>(); List <string> exportedColliders = new List <string>(); StringBuilder pathBuilder = new StringBuilder(); int numOccurrences = Program.ASSEMBLY_DOCUMENT.ComponentDefinition.Occurrences.AllLeafOccurrences.Count; int progressPercent = 0; int currentOccurrenceID = 0; foreach (ComponentOccurrence currentOccurrence in Program.ASSEMBLY_DOCUMENT.ComponentDefinition.Occurrences.AllLeafOccurrences) { if (exporter.CancellationPending) { e.Cancel = true; return; } progressPercent = (int)Math.Floor((currentOccurrenceID / (double)numOccurrences) * 100.0); exporter.ReportProgress(progressPercent, "Exporting... " + progressPercent + "%"); if (currentOccurrence.Visible && currentOccurrence.ReferencedDocumentDescriptor != null && currentOccurrence.ReferencedDocumentDescriptor.ReferencedDocumentType == DocumentTypeEnum.kPartDocumentObject && currentOccurrence.SurfaceBodies.Count > 0) { FieldNode outputNode = new FieldNode(currentOccurrence.Name); outputNode.Position = Utilities.ToBXDVector(currentOccurrence.Transformation.Translation); outputNode.Rotation = Utilities.QuaternionFromMatrix(currentOccurrence.Transformation); if (!exportedMeshes.Contains(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName)) { surfaceExporter.Reset(); surfaceExporter.Export(((PartDocument)currentOccurrence.ReferencedDocumentDescriptor.ReferencedDocument).ComponentDefinition, false, true); BXDAMesh.BXDASubMesh outputMesh = surfaceExporter.GetOutput().meshes.First(); exportedMeshes.Add(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName); fieldDefinition.AddSubMesh(outputMesh); } outputNode.SubMeshID = exportedMeshes.IndexOf(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName); ComponentPropertiesTabPage componentProperties = Program.MAINWINDOW.GetPropertySetsTabControl().GetParentTabPage(currentOccurrence.Name); if (componentProperties != null) { outputNode.PropertySetID = componentProperties.Name; PropertySet propertySet = fieldDefinition.GetPropertySets()[outputNode.PropertySetID]; if (propertySet.Collider.CollisionType == PropertySet.PropertySetCollider.PropertySetCollisionType.MESH && ((PropertySet.MeshCollider)propertySet.Collider).Convex) { if (!exportedColliders.Contains(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName)) { exportedColliders.Add(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName); var test = fieldDefinition.GetSubMesh(outputNode.SubMeshID); fieldDefinition.AddCollisionMesh(ConvexHullCalculator.GetHull(fieldDefinition.GetSubMesh(outputNode.SubMeshID))); } outputNode.CollisionMeshID = exportedColliders.IndexOf(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName); } } pathBuilder.Clear(); foreach (ComponentOccurrence co in currentOccurrence.OccurrencePath) { pathBuilder.Append(co.Name + "/"); } pathBuilder.Length--; fieldDefinition.NodeGroup[pathBuilder.ToString()] = outputNode; } currentOccurrenceID++; } exporter.ReportProgress(100, "Export Successful!"); fieldDefinition.GetMeshOutput().WriteToFile(directory + "\\mesh.bxda"); // Field data such as spawnpoints and gamepieces ExportFieldData(directory); // Property sets BXDFProperties.WriteProperties(directory + "\\definition.bxdf", fieldDefinition); // Open the export directory when done if (openFolderCheckBox.Checked) { Process.Start("explorer.exe", "/select, " + directory); } }
public bool CreateMesh(string filePath) { BXDAMesh mesh = new BXDAMesh(); mesh.ReadFromFile(filePath, null); if (!mesh.GUID.Equals(GUID)) { return(false); } List <FieldNode> remainingNodes = new List <FieldNode>(NodeGroup.EnumerateAllLeafFieldNodes()); List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> > submeshes = new List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> >(); List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> > colliders = new List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> >(); // Create all submesh objects auxFunctions.ReadMeshSet(mesh.meshes, delegate(int id, BXDAMesh.BXDASubMesh sub, Mesh meshu) { submeshes.Add(new KeyValuePair <BXDAMesh.BXDASubMesh, Mesh>(sub, meshu)); }); // Create all collider objects auxFunctions.ReadMeshSet(mesh.colliders, delegate(int id, BXDAMesh.BXDASubMesh sub, Mesh meshu) { colliders.Add(new KeyValuePair <BXDAMesh.BXDASubMesh, Mesh>(sub, meshu)); }); foreach (FieldNode node in NodeGroup.EnumerateAllLeafFieldNodes()) { GameObject subObject = new GameObject(node.NodeID); //subObject.transform.parent = unityObject.transform; if (node.SubMeshID != -1) { KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> currentSubMesh = submeshes[node.SubMeshID]; BXDAMesh.BXDASubMesh sub = currentSubMesh.Key; Mesh meshu = currentSubMesh.Value; subObject.AddComponent <MeshFilter>().mesh = meshu; subObject.AddComponent <MeshRenderer>(); Material[] matls = new Material[meshu.subMeshCount]; for (int i = 0; i < matls.Length; i++) { matls[i] = sub.surfaces[i].AsMaterial(); } subObject.GetComponent <MeshRenderer>().materials = matls; } if (GetPropertySets().ContainsKey(node.PropertySetID)) { PropertySet currentPropertySet = GetPropertySets()[node.PropertySetID]; PropertySet.PropertySetCollider psCollider = currentPropertySet.Collider; Collider unityCollider = null; Debug.Log(psCollider == null); switch (psCollider.CollisionType) { case PropertySet.PropertySetCollider.PropertySetCollisionType.BOX: PropertySet.BoxCollider psBoxCollider = (PropertySet.BoxCollider)psCollider; BoxCollider unityBoxCollider = subObject.AddComponent <BoxCollider>(); //unityBoxCollider.size.Scale(new Vector3(psBoxCollider.Scale.x, psBoxCollider.Scale.y, psBoxCollider.Scale.z)); unityBoxCollider.size = new Vector3( unityBoxCollider.size.x * psBoxCollider.Scale.x, unityBoxCollider.size.y * psBoxCollider.Scale.y, unityBoxCollider.size.z * psBoxCollider.Scale.z); unityCollider = unityBoxCollider; break; case PropertySet.PropertySetCollider.PropertySetCollisionType.SPHERE: PropertySet.SphereCollider psSphereCollider = (PropertySet.SphereCollider)psCollider; SphereCollider unitySphereCollider = subObject.AddComponent <SphereCollider>(); unitySphereCollider.radius *= psSphereCollider.Scale; unityCollider = unitySphereCollider; break; case PropertySet.PropertySetCollider.PropertySetCollisionType.MESH: if (node.CollisionMeshID != -1) { KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> currentSubMesh = colliders[node.CollisionMeshID]; BXDAMesh.BXDASubMesh sub = currentSubMesh.Key; Mesh meshu = currentSubMesh.Value; MeshCollider unityMeshCollider = subObject.AddComponent <MeshCollider>(); unityMeshCollider.sharedMesh = meshu; unityMeshCollider.convex = true; unityCollider = unityMeshCollider; } break; } if (unityCollider != null) { unityCollider.material.dynamicFriction = unityCollider.material.staticFriction = currentPropertySet.Friction / 100f; unityCollider.material.frictionCombine = PhysicMaterialCombine.Minimum; Rigidbody rb = unityCollider.gameObject.AddComponent <Rigidbody>(); if (currentPropertySet.Mass > 0) { rb.mass = (float)currentPropertySet.Mass * Init.PHYSICS_MASS_MULTIPLIER; } else { rb.constraints = RigidbodyConstraints.FreezeAll; rb.isKinematic = true; } } } // Invert the x-axis to compensate for Unity's inverted coordinate system. subObject.transform.localScale = new Vector3(-1f, 1f, 1f); // Set the position of the object (scaled by 1/100 to match Unity's scaling correctly). subObject.transform.position = new Vector3(-node.Position.x * 0.01f, node.Position.y * 0.01f, node.Position.z * 0.01f); // Set the rotation of the object (the x and w properties are inverted to once again compensate for Unity's differences). subObject.transform.rotation = new Quaternion(-node.Rotation.X, node.Rotation.Y, node.Rotation.Z, -node.Rotation.W); } #region Free mesh foreach (var list in new List <BXDAMesh.BXDASubMesh>[] { mesh.meshes, mesh.colliders }) { foreach (BXDAMesh.BXDASubMesh sub in list) { sub.verts = null; sub.norms = null; foreach (BXDAMesh.BXDASurface surf in sub.surfaces) { surf.indicies = null; } } for (int i = 0; i < list.Count; i++) { list[i] = null; } } mesh = null; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); #endregion return(true); }
/// <summary> /// Executes the actual exporting. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void exporter_DoWork(object sender, DoWorkEventArgs e) { FieldDefinition fieldDefinition = FieldDefinition.Factory(Guid.NewGuid(), Program.ASSEMBLY_DOCUMENT.DisplayName); foreach (PropertySet ps in Program.MAINWINDOW.GetPropertySetsTabControl().TranslateToPropertySets()) { fieldDefinition.AddPropertySet(ps); } SurfaceExporter surfaceExporter = new SurfaceExporter(); List <string> exportedMeshes = new List <string>(); List <string> exportedColliders = new List <string>(); StringBuilder pathBuilder = new StringBuilder(); int numOccurrences = Program.ASSEMBLY_DOCUMENT.ComponentDefinition.Occurrences.AllLeafOccurrences.Count; int progressPercent = 0; int currentOccurrenceID = 0; foreach (ComponentOccurrence currentOccurrence in Program.ASSEMBLY_DOCUMENT.ComponentDefinition.Occurrences.AllLeafOccurrences) { if (exporter.CancellationPending) { e.Cancel = true; return; } progressPercent = (int)Math.Floor((currentOccurrenceID / (double)numOccurrences) * 100.0); exporter.ReportProgress(progressPercent, "Exporting... " + progressPercent + "%"); if (currentOccurrence.Visible && currentOccurrence.ReferencedDocumentDescriptor != null && currentOccurrence.ReferencedDocumentDescriptor.ReferencedDocumentType == DocumentTypeEnum.kPartDocumentObject && currentOccurrence.SurfaceBodies.Count > 0) { FieldNode outputNode = new FieldNode(currentOccurrence.Name); outputNode.Position = Utilities.ToBXDVector(currentOccurrence.Transformation.Translation); outputNode.Rotation = Utilities.QuaternionFromMatrix(currentOccurrence.Transformation); if (!exportedMeshes.Contains(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName)) { surfaceExporter.Reset(); surfaceExporter.Export(((PartDocument)currentOccurrence.ReferencedDocumentDescriptor.ReferencedDocument).ComponentDefinition, false, true); BXDAMesh.BXDASubMesh outputMesh = surfaceExporter.GetOutput().meshes.First(); exportedMeshes.Add(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName); fieldDefinition.AddSubMesh(outputMesh); } outputNode.SubMeshID = exportedMeshes.IndexOf(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName); ComponentPropertiesTabPage componentProperties = Program.MAINWINDOW.GetPropertySetsTabControl().GetParentTabPage(currentOccurrence.Name); if (componentProperties != null) { outputNode.PropertySetID = componentProperties.Name; PropertySet propertySet = fieldDefinition.GetPropertySets()[outputNode.PropertySetID]; if (propertySet.Collider.CollisionType == PropertySet.PropertySetCollider.PropertySetCollisionType.MESH && ((PropertySet.MeshCollider)propertySet.Collider).Convex) { if (!exportedColliders.Contains(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName)) { exportedColliders.Add(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName); fieldDefinition.AddCollisionMesh(ConvexHullCalculator.GetHull(fieldDefinition.GetSubMesh(outputNode.SubMeshID))); } outputNode.CollisionMeshID = exportedColliders.IndexOf(currentOccurrence.ReferencedDocumentDescriptor.FullDocumentName); } } pathBuilder.Clear(); foreach (ComponentOccurrence co in currentOccurrence.OccurrencePath) { pathBuilder.Append(co.Name + "/"); } pathBuilder.Length--; fieldDefinition.NodeGroup[pathBuilder.ToString()] = outputNode; } currentOccurrenceID++; } exporter.ReportProgress(100, "Export Successful!"); fieldDefinition.GetMeshOutput().WriteToFile(filePathTextBox.Text + "\\mesh.bxda"); BXDFProperties.WriteProperties(filePathTextBox.Text + "\\definition.bxdf", fieldDefinition); // Use the commented code below for debugging. /** / * string result; * FieldDefinition readDefinition = BXDFProperties.ReadProperties(filePathTextBox.Text + "\\definition.bxdf", out result); * MessageBox.Show(result); * /**/ }
public bool CreateMesh(string filePath) { BXDAMesh mesh = new BXDAMesh(); mesh.ReadFromFile(filePath, null); if (!mesh.GUID.Equals(GUID)) { return(false); } List <FieldNode> remainingNodes = new List <FieldNode>(NodeGroup.EnumerateAllLeafFieldNodes()); List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> > submeshes = new List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> >(); List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> > colliders = new List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> >(); // Create all submesh objects AuxFunctions.ReadMeshSet(mesh.meshes, delegate(int id, BXDAMesh.BXDASubMesh sub, Mesh meshu) { submeshes.Add(new KeyValuePair <BXDAMesh.BXDASubMesh, Mesh>(sub, meshu)); }); // Create all collider objects AuxFunctions.ReadMeshSet(mesh.colliders, delegate(int id, BXDAMesh.BXDASubMesh sub, Mesh meshu) { colliders.Add(new KeyValuePair <BXDAMesh.BXDASubMesh, Mesh>(sub, meshu)); }); foreach (FieldNode node in NodeGroup.EnumerateAllLeafFieldNodes()) { GameObject subObject = new GameObject(node.NodeID); subObject.transform.parent = unityObject.transform; GameObject meshObject = new GameObject(node.NodeID + "-mesh"); if (node.SubMeshID != -1) { KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> currentSubMesh = submeshes[node.SubMeshID]; BXDAMesh.BXDASubMesh sub = currentSubMesh.Key; Mesh meshu = currentSubMesh.Value; meshObject.AddComponent <MeshFilter>().mesh = meshu; meshObject.AddComponent <MeshRenderer>(); Material[] matls = new Material[meshu.subMeshCount]; for (int i = 0; i < matls.Length; i++) { matls[i] = sub.surfaces[i].AsMaterial(); } meshObject.GetComponent <MeshRenderer>().materials = matls; } // Invert the x-axis to compensate for Unity's inverted coordinate system. meshObject.transform.localScale = new Vector3(-1f, 1f, 1f); // Set the rotation of the object (the x and w properties are inverted to once again compensate for Unity's differences). meshObject.transform.localRotation = new Quaternion(-node.Rotation.X, node.Rotation.Y, node.Rotation.Z, -node.Rotation.W); // Set the position of the object (scaled by 1/100 to match Unity's scaling correctly). meshObject.transform.position = new Vector3(-node.Position.x * 0.01f, node.Position.y * 0.01f, node.Position.z * 0.01f); if (GetPropertySets().ContainsKey(node.PropertySetID)) { PropertySet currentPropertySet = GetPropertySets()[node.PropertySetID]; PropertySet.PropertySetCollider psCollider = currentPropertySet.Collider; switch (psCollider.CollisionType) { case PropertySet.PropertySetCollider.PropertySetCollisionType.BOX: PropertySet.BoxCollider psBoxCollider = (PropertySet.BoxCollider)psCollider; BoxCollider dummyBoxCollider = meshObject.AddComponent <BoxCollider>(); subObject.transform.localRotation = meshObject.transform.localRotation; subObject.transform.position = meshObject.transform.TransformPoint(dummyBoxCollider.center); BBoxShape boxShape = subObject.AddComponent <BBoxShape>(); boxShape.Extents = new Vector3( dummyBoxCollider.size.x * 0.5f * psBoxCollider.Scale.x, dummyBoxCollider.size.y * 0.5f * psBoxCollider.Scale.y, dummyBoxCollider.size.z * 0.5f * psBoxCollider.Scale.z); //meshObject.AddComponent<MouseListener>(); UnityEngine.Object.Destroy(dummyBoxCollider); break; case PropertySet.PropertySetCollider.PropertySetCollisionType.SPHERE: PropertySet.SphereCollider psSphereCollider = (PropertySet.SphereCollider)psCollider; SphereCollider dummySphereCollider = meshObject.AddComponent <SphereCollider>(); subObject.transform.position = meshObject.transform.TransformPoint(dummySphereCollider.center); BSphereShape sphereShape = subObject.AddComponent <BSphereShape>(); sphereShape.Radius = dummySphereCollider.radius * psSphereCollider.Scale; //meshObject.AddComponent<MouseListener>(); UnityEngine.Object.Destroy(dummySphereCollider); break; case PropertySet.PropertySetCollider.PropertySetCollisionType.MESH: PropertySet.MeshCollider psMeshCollider = (PropertySet.MeshCollider)psCollider; if (psMeshCollider.Convex || currentPropertySet.Mass != 0) { MeshCollider dummyMeshCollider = subObject.AddComponent <MeshCollider>(); dummyMeshCollider.sharedMesh = meshObject.GetComponent <MeshFilter>().mesh; subObject.transform.position = meshObject.transform.TransformPoint(dummyMeshCollider.bounds.center); subObject.transform.rotation = meshObject.transform.rotation; BConvexHullShape hullshape = subObject.AddComponent <BConvexHullShape>(); hullshape.HullMesh = AuxFunctions.GenerateCollisionMesh(meshObject.GetComponent <MeshFilter>().mesh, dummyMeshCollider.sharedMesh.bounds.center); hullshape.GetCollisionShape().Margin = 0f; //subObject.AddComponent<MouseListener>(); UnityEngine.Object.Destroy(dummyMeshCollider); } else { subObject.transform.position = meshObject.transform.position; subObject.transform.rotation = meshObject.transform.rotation; BBvhTriangleMeshShape meshShape = subObject.AddComponent <BBvhTriangleMeshShape>(); meshShape.HullMesh = meshObject.GetComponent <MeshFilter>().mesh.GetScaledCopy(-1f, 1f, 1f); meshShape.GetCollisionShape().Margin = 0f; } // TODO: Find a way to implement embedded margins. See https://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=2358 break; } BRigidBody rb = subObject.AddComponent <BRigidBody>(); rb.friction = currentPropertySet.Friction * FRICTION_SCALE; rb.mass = currentPropertySet.Mass; if (currentPropertySet.Mass == 0) { rb.collisionFlags = BulletSharp.CollisionFlags.StaticObject; } else { subObject.AddComponent <Tracker>(); } meshObject.transform.parent = subObject.transform; } else { meshObject.transform.parent = unityObject.transform; } } #region Free mesh foreach (var list in new List <BXDAMesh.BXDASubMesh>[] { mesh.meshes, mesh.colliders }) { foreach (BXDAMesh.BXDASubMesh sub in list) { sub.verts = null; sub.norms = null; foreach (BXDAMesh.BXDASurface surf in sub.surfaces) { surf.indicies = null; } } for (int i = 0; i < list.Count; i++) { list[i] = null; } } mesh = null; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); #endregion return(true); }
public VBOMesh(BXDAMesh.BXDASubMesh subMesh) { this.subMesh = subMesh; }
/// <summary> /// Used for adding a submesh and creating a sub mesh ID for the given node. /// </summary> /// <param name="subMesh"></param> /// <param name="node"></param> public void AddSubMesh(BXDAMesh.BXDASubMesh subMesh) { mesh.meshes.Add(subMesh); }
/// <summary> /// Returns a bullet mesh shape offset relative to its starting position /// </summary> /// <param name="subMesh"></param> /// <param name="vertices"></param> /// <param name="offset"></param> /// <returns></returns> public static StridingMeshInterface BulletShapeFromSubMesh(BXDAMesh.BXDASubMesh subMesh, Vector3 offset) { Vector3[] vertices = subMesh.GetVertexData(); return(new TriangleIndexVertexArray(subMesh.GetAllIndices().ToArray(), (from Vector3 v in vertices select v + offset).ToArray())); }
/// <summary> /// Used for adding a collision mesh and creating a collision mesh ID for the given node. /// </summary> /// <param name="collisionMesh"></param> /// <param name="node"></param> public void AddCollisionMesh(BXDAMesh.BXDASubMesh collisionMesh) { mesh.colliders.Add(collisionMesh); }
public bool CreateMesh(string filePath, bool multiplayer = false, bool host = false) { BXDAMesh mesh = new BXDAMesh(); mesh.ReadFromFile(filePath, null); if (!mesh.GUID.Equals(GUID)) { return(false); } List <FieldNode> remainingNodes = new List <FieldNode>(NodeGroup.EnumerateAllLeafFieldNodes()); List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> > submeshes = new List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> >(); List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> > colliders = new List <KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> >(); // Create all submesh objects Auxiliary.ReadMeshSet(mesh.meshes, delegate(int id, BXDAMesh.BXDASubMesh sub, Mesh meshu) { submeshes.Add(new KeyValuePair <BXDAMesh.BXDASubMesh, Mesh>(sub, meshu)); }); // Create all collider objects Auxiliary.ReadMeshSet(mesh.colliders, delegate(int id, BXDAMesh.BXDASubMesh sub, Mesh meshu) { colliders.Add(new KeyValuePair <BXDAMesh.BXDASubMesh, Mesh>(sub, meshu)); }); //Dictionary<string, NetworkElement> networkElements = new Dictionary<string, NetworkElement>(); //foreach (NetworkElement ne in Resources.FindObjectsOfTypeAll<NetworkElement>()) // networkElements[ne.NodeID] = ne; foreach (FieldNode node in NodeGroup.EnumerateAllLeafFieldNodes()) { PropertySet?propertySet = null; if (GetPropertySets().ContainsKey(node.PropertySetID)) { propertySet = GetPropertySets()[node.PropertySetID]; } GameObject subObject; //if (multiplayer && propertySet.HasValue && propertySet.Value.Mass != 0) //{ // if (host) // { // subObject = (GameObject)UnityEngine.Object.Instantiate(Resources.Load("prefabs/NetworkElement"), unityObject.transform); // subObject.GetComponent<NetworkElement>().NodeID = node.NodeID; // subObject.name = node.NodeID; // NetworkServer.Spawn(subObject); // } // else // { // subObject = networkElements[node.NodeID].gameObject; // subObject.name = node.NodeID; // } //} //else //{ // subObject = new GameObject(node.NodeID); //} subObject = new GameObject(node.NodeID); subObject.transform.parent = unityObject.transform; GameObject meshObject = new GameObject(node.NodeID + "-mesh"); if (node.SubMeshID != -1) { KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> currentSubMesh = submeshes[node.SubMeshID]; BXDAMesh.BXDASubMesh sub = currentSubMesh.Key; Mesh meshu = currentSubMesh.Value; meshObject.AddComponent <MeshFilter>().mesh = meshu; meshObject.AddComponent <MeshRenderer>(); Material[] matls = new Material[meshu.subMeshCount]; for (int i = 0; i < matls.Length; i++) { matls[i] = sub.surfaces[i].AsMaterial(); } meshObject.GetComponent <MeshRenderer>().materials = matls; } // Invert the x-axis to compensate for Unity's inverted coordinate system. meshObject.transform.localScale = new Vector3(-1f, 1f, 1f); // Set the rotation of the object (the x and w properties are inverted to once again compensate for Unity's differences). meshObject.transform.localRotation = new Quaternion(-node.Rotation.X, node.Rotation.Y, node.Rotation.Z, -node.Rotation.W); // Set the position of the object (scaled by 1/100 to match Unity's scaling correctly). meshObject.transform.position = new Vector3(-node.Position.x * 0.01f, node.Position.y * 0.01f, node.Position.z * 0.01f); if (GetPropertySets().ContainsKey(node.PropertySetID)) { PropertySet currentPropertySet = GetPropertySets()[node.PropertySetID]; PropertySet.PropertySetCollider psCollider = currentPropertySet.Collider; switch (psCollider.CollisionType) { case PropertySet.PropertySetCollider.PropertySetCollisionType.BOX: PropertySet.BoxCollider psBoxCollider = (PropertySet.BoxCollider)psCollider; BoxCollider dummyBoxCollider = meshObject.AddComponent <BoxCollider>(); subObject.transform.localRotation = meshObject.transform.localRotation; subObject.transform.position = meshObject.transform.TransformPoint(dummyBoxCollider.center); BBoxShape boxShape = subObject.AddComponent <BBoxShape>(); boxShape.Extents = new Vector3( dummyBoxCollider.size.x * 0.5f * psBoxCollider.Scale.x, dummyBoxCollider.size.y * 0.5f * psBoxCollider.Scale.y, dummyBoxCollider.size.z * 0.5f * psBoxCollider.Scale.z); //meshObject.AddComponent<MouseListener>(); UnityEngine.Object.Destroy(dummyBoxCollider); break; case PropertySet.PropertySetCollider.PropertySetCollisionType.SPHERE: PropertySet.SphereCollider psSphereCollider = (PropertySet.SphereCollider)psCollider; SphereCollider dummySphereCollider = meshObject.AddComponent <SphereCollider>(); subObject.transform.position = meshObject.transform.TransformPoint(dummySphereCollider.center); BSphereShape sphereShape = subObject.AddComponent <BSphereShape>(); sphereShape.Radius = dummySphereCollider.radius * psSphereCollider.Scale; //meshObject.AddComponent<MouseListener>(); UnityEngine.Object.Destroy(dummySphereCollider); break; case PropertySet.PropertySetCollider.PropertySetCollisionType.MESH: PropertySet.MeshCollider psMeshCollider = (PropertySet.MeshCollider)psCollider; if (psMeshCollider.Convex || currentPropertySet.Mass != 0) { MeshCollider dummyMeshCollider = subObject.AddComponent <MeshCollider>(); dummyMeshCollider.sharedMesh = meshObject.GetComponent <MeshFilter>().mesh; subObject.transform.position = meshObject.transform.TransformPoint(dummyMeshCollider.bounds.center); subObject.transform.rotation = meshObject.transform.rotation; BConvexHullShape hullshape = subObject.AddComponent <BConvexHullShape>(); hullshape.HullMesh = Auxiliary.GenerateCollisionMesh(meshObject.GetComponent <MeshFilter>().mesh, dummyMeshCollider.sharedMesh.bounds.center, 0f /*CollisionMargin*/); hullshape.GetCollisionShape().Margin = CollisionMargin; //subObject.AddComponent<MouseListener>(); UnityEngine.Object.Destroy(dummyMeshCollider); } else { subObject.transform.position = meshObject.transform.position; subObject.transform.rotation = meshObject.transform.rotation; BBvhTriangleMeshShape meshShape = subObject.AddComponent <BBvhTriangleMeshShape>(); meshShape.HullMesh = meshObject.GetComponent <MeshFilter>().mesh.GetScaledCopy(-1f, 1f, 1f); meshShape.GetCollisionShape().Margin = CollisionMargin; } break; } BRigidBody rb = subObject.AddComponent <BRigidBody>(); rb.friction = currentPropertySet.Friction * FrictionScale; rb.rollingFriction = currentPropertySet.Friction * RollingFrictionScale; rb.mass = currentPropertySet.Mass; if (currentPropertySet.Mass == 0) { rb.collisionFlags = BulletSharp.CollisionFlags.StaticObject; } else { subObject.AddComponent <Tracker>(); subObject.name = currentPropertySet.PropertySetID; //sets game elements to the same name as the property set - used to identify proper colliders } meshObject.transform.parent = subObject.transform; } else { meshObject.transform.parent = unityObject.transform; } } //if (!host) // foreach (NetworkElement ne in networkElements.Values) // ne.gameObject.AddComponent<NetworkMesh>(); #region Free mesh foreach (var list in new List <BXDAMesh.BXDASubMesh>[] { mesh.meshes, mesh.colliders }) { foreach (BXDAMesh.BXDASubMesh sub in list) { sub.verts = null; sub.norms = null; foreach (BXDAMesh.BXDASurface surf in sub.surfaces) { surf.indicies = null; } } for (int i = 0; i < list.Count; i++) { list[i] = null; } } mesh = null; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); #endregion return(true); }
/// <summary> /// Gets the center of a sub mesh relative to the entire BXDA mesh /// </summary> /// <param name="subMesh"></param> /// <param name="vertices"></param> /// <returns></returns> public static Vector3 MeshCenterRelative(BXDAMesh.BXDASubMesh subMesh, BXDAMesh mesh) { return(MeshCenter(subMesh) - MeshCenter(mesh.AllColliderVertices())); }
/// <summary> /// Gets all of the unordered vertex data from the submesh /// </summary> /// <param name="mesh"></param> /// <returns></returns> public static Vector3[] GetVertexData(this BXDAMesh.BXDASubMesh mesh) { return(MeshUtilities.DataToVector(mesh.verts)); }