public aiNode ToAssimp(Module.Export.Assimp.Context context, Scene scene, aiNode parent) { uint index = 0; aiNode node_object = new aiNode(name); // Set parent node_object.mParent = parent; // Set transform using (aiVector3D assimp_scale = Assimp.Convert.UnityToAssimp.Vector3(scale)) { using (aiQuaternion assimp_rotation = Assimp.Convert.UnityToAssimp.Quaternion(rotation)) { using (aiVector3D assimp_position = Assimp.Convert.UnityToAssimp.Vector3(position)) { using (aiMatrix4x4 matrix = new aiMatrix4x4(assimp_scale, assimp_rotation, assimp_position)) { node_object.mTransformation = matrix.Unmanaged(); } } } } // Parse the children nodes if (children != null && children.Length > 0) { using (aiNodeArray assimp_children = node_object.Children) { assimp_children.Reserve((uint)children.Length, true); index = 0; foreach (Node child in children) { using (aiNode assimp_child = child.ToAssimp(context, scene, node_object)) { if (assimp_child != null) { assimp_children.Set(index++, assimp_child.Unmanaged()); } } } } } // Parse the mesh objects if (meshes != null && meshes.Length > 0) { using (aiUIntArray assimp_meshes = node_object.Meshes) { assimp_meshes.Reserve((uint)meshes.Length, true); index = 0; foreach (GraphicMesh graphic_mesh in meshes) { Mesh mesh = scene.meshes[graphic_mesh.meshIndex]; int nb_materials = (graphic_mesh.materialsIndexes != null ? graphic_mesh.materialsIndexes.Length : 0); // Handle unity submeshes by creating new meshes for each submesh for (int i = 0; i < mesh.SubMeshesCount; i++) { // Assimp meshes can only have one material. Therefore, mutliple instances of one mesh // using different materials must be detected and replaced by different output meshes. uint assimp_mesh_index; int mat_index = (i < nb_materials ? graphic_mesh.materialsIndexes[i] : 0 /*Assimp default*/); Module.Export.Assimp.Mesh key = new Module.Export.Assimp.Mesh(graphic_mesh.meshIndex, i, mat_index); if (!context.meshes.TryGetValue(key, out assimp_mesh_index)) { assimp_mesh_index = (uint)context.meshes.Count; context.meshes.Add(key, assimp_mesh_index); } assimp_meshes.Set(index++, assimp_mesh_index); } } } } // Parse the node metadata if (components != null) { foreach (UnityComponent component in components) { aiMetadata assimp_meta = component.ToAssimpMetadata(); if (assimp_meta != null) { node_object.mMetaData = assimp_meta.Unmanaged(); break; } } } context.progress.Update(ASSIMP_PROGRESS_FACTOR); return(node_object); }
public static UnityComponent FromAssimpMetadata(aiMetadata meta) { UnityComponent metadata = null; if (meta != null && meta.Keys != null) { uint size = meta.Keys.Size(); if (meta.Values != null && meta.Values.Size() == size) { if (size > 0) { Dictionary <string, object> storage = new Dictionary <string, object>(); for (uint i = 0; i < size; ++i) { using (aiString key = meta.Keys.Get(i)) { using (aiMetadataEntry entry = meta.Values.Get(i)) { object value = null; switch (entry.mType) { case aiMetadataType.AI_BOOL: value = entry.GetBool(); break; case aiMetadataType.AI_INT32: value = entry.GetInt32(); break; case aiMetadataType.AI_UINT64: value = entry.GetUInt64(); break; case aiMetadataType.AI_FLOAT: value = entry.GetFloat(); break; case aiMetadataType.AI_DOUBLE: value = entry.GetDouble(); break; case aiMetadataType.AI_AISTRING: value = entry.GetString().C_Str(); break; case aiMetadataType.AI_AIVECTOR3D: value = Assimp.Convert.AssimpToUnity.Vector3(entry.GetVector3D()); break; } storage.Add(key.C_Str(), value); } } } metadata = new UnityComponent { type = typeof(Metadata) }; metadata.CreateBackend(); AssimpMetadataSerializationContext context = new AssimpMetadataSerializationContext(metadata.type, storage); ((BackendBinarySerializable)metadata.backend).serialized = Module.Import.Binary.serializer.Serialize(context.Callback); } } else { Debug.LogError("The number of metadata keys and values does not match."); } } return(metadata); }
public static Node FromAssimp(Module.Import.Assimp.Context context, aiScene scene, aiNode assimp_node) { // Create new node object Node node = new Node(); // Get node ID node.id = context.id++; // Get node name node.name = Assimp.Convert.Name(assimp_node.mName, "node"); // Get node metadata using (aiMetadata meta = assimp_node.mMetaData) { UnityComponent metadata = UnityComponent.FromAssimpMetadata(meta); if (metadata != null) { node.components = new UnityComponent[] { metadata }; } } // Parse children recursively using (aiNodeArray children = assimp_node.Children) { uint children_size = children.Size(); if (children_size > 0) { node.children = new Node[children_size]; for (uint i = 0; i < children_size; i++) { aiNode child = children.Get(i); // ParseNode must dispose of the given node afterward // We must use a proxy method for saving the result into the array because the index i is captured by the lambda otherwise and it's value is indefinite across multiple threads. context.threads.ExecAndSaveToArray(node.children, (int)i, () => FromAssimp(context, scene, child)); } } } // Parse meshes associated to this node using (aiUIntArray meshes = assimp_node.Meshes) { uint meshes_size = meshes.Size(); if (meshes_size > 0) { int global_meshes_size = (int)scene.Meshes.Size(); node.meshes = new GraphicMesh[meshes_size]; for (uint j = 0; j < meshes_size; j++) { node.meshes[j] = new GraphicMesh(); if (j < global_meshes_size) { uint mesh_index = meshes.Get(j); node.meshes[j].meshIndex = (int)mesh_index; } } } } // Get the transform of this node using (aiVector3D position = new aiVector3D()) { using (aiVector3D scaling = new aiVector3D()) { using (aiQuaternion rotation = new aiQuaternion()) { assimp_node.mTransformation.Decompose(scaling, rotation, position); node.position = Assimp.Convert.AssimpToUnity.Vector3(position); node.rotation = Assimp.Convert.AssimpToUnity.Quaternion(rotation); node.scale = Assimp.Convert.AssimpToUnity.Vector3(scaling); } } } // We must dispose of the given parameter to avoid memory leaks assimp_node.Dispose(); context.progress.Update(ASSIMP_PROGRESS_FACTOR); return(node); }
public aiMetadata ToAssimpMetadata() { aiMetadata assimp_meta = null; if (typeof(Metadata).IsAssignableFrom(type)) { Dictionary <string, object> data = (Dictionary <string, object>)Module.Import.Binary.serializer.Deserialize(((BackendBinarySerializable)backend).serialized); if (data != null && data.Count > 0) { uint count = 0; // Get the number of valid metadata that can be exported foreach (KeyValuePair <string, object> pair in data) { if (!string.IsNullOrEmpty(pair.Key) && pair.Value != null) { count++; } } // Allocate memory for metadata assimp_meta = aiMetadata.Alloc(count); uint index = 0; // Export all valid metadata foreach (KeyValuePair <string, object> pair in data) { if (!string.IsNullOrEmpty(pair.Key) && pair.Value != null) { System.Type type = pair.Value.GetType(); if (type == typeof(bool)) { assimp_meta.SetBool(index++, pair.Key, (bool)pair.Value); } else if (type == typeof(int)) { assimp_meta.SetInt32(index++, pair.Key, (int)pair.Value); } else if (type == typeof(ulong)) { assimp_meta.SetUInt64(index++, pair.Key, (ulong)pair.Value); } else if (type == typeof(float)) { assimp_meta.SetFloat(index++, pair.Key, (float)pair.Value); } else if (type == typeof(double)) { assimp_meta.SetDouble(index++, pair.Key, (double)pair.Value); } else if (type == typeof(string)) { assimp_meta.SetString(index++, pair.Key, new aiString((string)pair.Value).Unmanaged()); } else if (type == typeof(Vector3)) { assimp_meta.SetVector3D(index++, pair.Key, Assimp.Convert.UnityToAssimp.Vector3((Vector3)pair.Value).Unmanaged()); } else { Debug.LogErrorFormat("Unsupported metadata of type '{0}'.", type); } } } } } return(assimp_meta); }