Пример #1
0
        public UnityComponent GetUnityComponent(Component component, Func <Scene, Component, UnityComponent> creator_callback)
        {
            UnityComponent result = null;

            if (component != null && !unityComponents.TryGetValue(component, out result))
            {
                result = creator_callback(this, component);

                unityComponents[component] = result;
            }

            return(result);
        }
Пример #2
0
        private static UnityComponent FromUnityCreator(Scene scene, Component component)
        {
            UnityComponent result = new UnityComponent();

            result.type = component.GetType();
            result.CreateBackend();

            if (component is ISerializationCallbackReceiver)
            {
                ((ISerializationCallbackReceiver)component).OnBeforeSerialize();
            }

            result.backend.FromUnity(scene, component, result.type);

            return(result);
        }
Пример #3
0
        private string ComputeHash(Scene scene, Transform trans)
        {
            Binary.Buffer buffer = Module.Import.Binary.serializer.GetBuffer(5 * 1024);             // Start with 5 Ko buffer

            uint written = 0;

            foreach (Component component in trans.GetComponents <Component>())
            {
                if (SerializedComponent(component))
                {
                    written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, UnityComponent.FromUnity(scene, component));
                }
            }

            uint size = (uint)System.Text.Encoding.UTF8.GetByteCount(name);

            size += 2 * Binary.Size(Binary.SupportedTypes.UNITY_VECTOR3);
            size += Binary.Size(Binary.SupportedTypes.UNITY_QUATERNION);

            Module.Import.Binary.serializer.ResizeBuffer(ref buffer, written + size);

            written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, trans.name);
            written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, trans.localPosition);
            written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, trans.localRotation);
            written += Module.Import.Binary.serializer.ToBytes(ref buffer, written, trans.localScale);

            return(Hash.ComputeHash(buffer.Data, 0, (int)written));
        }
Пример #4
0
        public static IEnumerator FromUnity(Scene scene, Transform node, Action <Node> callback, Progress progress = null, LinkedList <Transform> meshes_nodes = null)
        {
            if (scene != null && node != null && callback != null)
            {
                // Create a new node
                Node current = new Node();

                // Handle easy stuff
                current.id        = scene.IdMapping.GetNewId();
                current.name      = node.name;
                current.tag       = node.tag;
                current.layer     = node.gameObject.layer;
                current.active    = node.gameObject.activeSelf;
                current.hideFlags = node.gameObject.hideFlags;
                current.position  = node.localPosition;
                current.rotation  = node.localRotation;
                current.scale     = node.localScale;

                // Update mapping
                scene.IdMapping.Add(node.gameObject, current.id);

                // Handle components
                current.components = node.gameObject.GetComponents <Component>()
                                     .Where(SerializedComponent)
                                     .Select(c => UnityComponent.FromUnity(scene, c))
                                     .ToArray();

                // Handle meshes and materials
                List <GraphicMesh> graphic_meshes = new List <GraphicMesh>();

                FromUnityMeshAndMaterials(scene, node, ref graphic_meshes);

                if (meshes_nodes != null)
                {
                    foreach (Transform t in meshes_nodes)
                    {
                        FromUnityMeshAndMaterials(scene, t, ref graphic_meshes);
                    }
                }

                if (graphic_meshes.Count > 0)
                {
                    current.meshes = graphic_meshes.ToArray();
                }

                // Handle children
                if (node.childCount > 0)
                {
                    Dictionary <string, LinkedList <Transform> > children_sorted = new Dictionary <string, LinkedList <Transform> >();

                    // Group all children by hash, i.e. same name, transform, components and metadata
                    foreach (Transform child in node)
                    {
                        LinkedList <Transform> group;

                        string hash = current.ComputeHash(scene, child);

                        if (!children_sorted.TryGetValue(hash, out group))
                        {
                            group = new LinkedList <Transform>();

                            children_sorted.Add(hash, group);
                        }

                        group.AddLast(child);
                    }

                    List <Node> children_nodes = new List <Node>(children_sorted.Count);

                    foreach (KeyValuePair <string, LinkedList <Transform> > pair in children_sorted)
                    {
                        // For each hash, check how many children have a descendancy
                        int child_count = pair.Value.Count(t => t.childCount > 0);

                        // Only one with descendancy ? The nodes must be grouped as they are only different meshes of the original unique node
                        if (child_count <= 1)
                        {
                            Transform main_child = null;

                            // No families at all ? Select the first one of the meshes to serve as the main one
                            if (child_count <= 0 || pair.Value.First.Value.childCount > 0)
                            {
                                main_child = pair.Value.First.Value;

                                pair.Value.RemoveFirst();
                            }
                            else // Main child is not he first one. We need to manually search for it.
                            {
                                LinkedListNode <Transform> list_node = pair.Value.First;
                                LinkedListNode <Transform> list_end  = pair.Value.Last;

                                while (list_node.Value.childCount <= 0 && list_node != list_end)
                                {
                                    list_node = list_node.Next;
                                }

                                if (list_node.Value.childCount > 0)
                                {
                                    main_child = list_node.Value;

                                    pair.Value.Remove(list_node);
                                }
                            }

                            if (main_child != null)
                            {
                                pair.Value.Remove(main_child);

                                IEnumerator it_progress = FromUnity(scene, main_child, children_nodes.Add, progress, pair.Value);

                                while (it_progress.MoveNext())
                                {
                                    yield return(it_progress.Current);
                                }
                            }
                        }
                        else                         // Many families ? We don't have sufficient information to group the nodes together
                        {
                            foreach (Transform child in pair.Value)
                            {
                                IEnumerator it = FromUnity(scene, child, children_nodes.Add, progress);

                                while (it.MoveNext())
                                {
                                    yield return(it.Current);
                                }
                            }
                        }

                        // Yield between each children nodes
                        yield return(null);
                    }

                    if (children_nodes.Count > 0)
                    {
                        current.children = children_nodes.ToArray();
                    }
                }

                callback(current);

                if (progress != null)
                {
                    progress.Update(1);
                }
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }