public PropertySet ToLegacy() { PropertySet.PropertySetCollider col = null; switch (colliderType) { case ColliderType.Sphere: col = new PropertySet.SphereCollider((float)Scale); break; case ColliderType.Box: col = new PropertySet.BoxCollider(new BXDVector3(X, Y, Z)); break; case ColliderType.Mesh: col = new PropertySet.MeshCollider(false); break; } if (Dynamic) { return(new PropertySet(Name, col, (int)Friction, (float)Mass)); } else { return(new PropertySet(Name, col, (int)Friction)); } }
/// <summary> /// Write the MeshCollider to an XML file with the given XmlWriter. /// </summary> /// <param name="writer"></param> /// <param name="meshCollider"></param> private static void WriteMeshCollider(XmlWriter writer, PropertySet.MeshCollider meshCollider) { writer.WriteStartElement("MeshCollider"); writer.WriteElementString("Convex", meshCollider.Convex.ToString().ToLower()); writer.WriteEndElement(); }
/// <summary> /// Reads a MeshCollider with the given XmlReader. /// </summary> /// <param name="reader"></param> /// <returns></returns> private static PropertySet.MeshCollider ReadMeshCollider_2_2(XmlReader reader) { // Create the MeshCollider. PropertySet.MeshCollider meshCollider = null; foreach (string name in IOUtilities.AllElements(reader)) { switch (name) { case "Convex": // Reads the convex property and initializes the MeshCollider. meshCollider = new PropertySet.MeshCollider(reader.ReadElementContentAsBoolean()); break; } } return(meshCollider); }
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); }
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); }
private void CreateMesh(string filePath) { Bodies = new List <RigidBody>(); VisualMeshes = new List <Mesh>(); BXDAMesh mesh = new BXDAMesh(); mesh.ReadFromFile(filePath); foreach (FieldNode node in NodeGroup.EnumerateAllLeafFieldNodes()) { if (!GetPropertySets().ContainsKey(node.PropertySetID)) { return; } PropertySet current = GetPropertySets()[node.PropertySetID]; CollisionShape subShape = null; switch (current.Collider.CollisionType) { case PropertySet.PropertySetCollider.PropertySetCollisionType.BOX: { //Create a box shape //This is a mess, though I was told that this is how it works Vector3[] vertices = MeshUtilities.DataToVector(mesh.meshes[node.SubMeshID].verts); StridingMeshInterface temp = MeshUtilities.BulletShapeFromSubMesh(mesh.meshes[node.SubMeshID]); Vector3 min, max; temp.CalculateAabbBruteForce(out min, out max); PropertySet.BoxCollider colliderInfo = (PropertySet.BoxCollider)current.Collider; subShape = new BoxShape((max - min) * colliderInfo.Scale.Convert() * 0.5f); if (debug) { Console.WriteLine("Created Box"); } break; } case PropertySet.PropertySetCollider.PropertySetCollisionType.SPHERE: { //Create a sphere shape PropertySet.SphereCollider colliderInfo = (PropertySet.SphereCollider)current.Collider; subShape = new SphereShape(colliderInfo.Scale); if (debug) { Console.WriteLine("Created Sphere"); } break; } case PropertySet.PropertySetCollider.PropertySetCollisionType.MESH: { //Create a mesh shape if (node.CollisionMeshID == -1) { break; } PropertySet.MeshCollider colliderInfo = (PropertySet.MeshCollider)current.Collider; Vector3[] vertices = MeshUtilities.DataToVector(mesh.colliders[node.CollisionMeshID].verts); if (colliderInfo.Convex) { subShape = new ConvexHullShape(vertices); if (debug) { Console.WriteLine("Created Convex Mesh"); } } else { StridingMeshInterface sMesh = MeshUtilities.BulletShapeFromSubMesh(mesh.colliders[node.CollisionMeshID]); subShape = new ConvexTriangleMeshShape(sMesh, true); //still not really concave if (debug) { Console.WriteLine("Created Concave Mesh"); } } break; } } if (null == subShape) { return; } //set sub shape local position/rotation and add it to the compound shape Vector3 Translation = node.Position.Convert(); Quaternion rotation = node.Rotation.Convert(); DefaultMotionState motion = new DefaultMotionState(Matrix4.CreateFromQuaternion(rotation) * Matrix4.CreateTranslation(Translation)); motion.CenterOfMassOffset = Matrix4.CreateTranslation(mesh.physics.centerOfMass.Convert()); RigidBodyConstructionInfo info = new RigidBodyConstructionInfo(current.Mass, motion, subShape, subShape.CalculateLocalInertia(current.Mass)); info.Friction = current.Friction; Bodies.Add(new RigidBody(info)); VisualMeshes.Add(new Mesh(mesh.meshes[node.SubMeshID], Translation)); if (debug) { Console.WriteLine("Created " + node.PropertySetID); } } }
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: PropertySet.MeshCollider psMeshCollider = (PropertySet.MeshCollider)psCollider; KeyValuePair <BXDAMesh.BXDASubMesh, Mesh> currentSubMesh = psMeshCollider.Convex ? colliders[node.CollisionMeshID] : submeshes[node.SubMeshID]; MeshCollider unityMeshCollider = subObject.AddComponent <MeshCollider>(); unityMeshCollider.sharedMesh = currentSubMesh.Value; unityMeshCollider.convex = psMeshCollider.Convex; 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); }