예제 #1
0
 public override void AbcSetup(
     AlembicStream abcstream,
     AbcAPI.aiObject abcobj,
     AbcAPI.aiSchema abcschema)
 {
     base.AbcSetup(abcstream, abcobj, abcschema);
 }
예제 #2
0
 public override void AbcGetConfig(ref AbcAPI.aiConfig config)
 {
     if (m_aspectRatioMode != AbcAPI.aiAspectRatioModeOverride.InheritStreamSetting)
     {
         config.aspectRatio = AbcAPI.GetAspectRatio((AbcAPI.aiAspectRatioMode) m_aspectRatioMode);
     }
 }
예제 #3
0
    public override void AbcSetup(AlembicStream abcStream,
                                  AbcAPI.aiObject abcObj,
                                  AbcAPI.aiSchema abcSchema)
    {
        base.AbcSetup(abcStream, abcObj, abcSchema);

        m_camera = GetOrAddComponent<Camera>();
    }
예제 #4
0
 public override void AbcSetup(
     AlembicStream abcstream,
     AbcAPI.aiObject abcobj,
     AbcAPI.aiSchema abcschema)
 {
     base.AbcSetup(abcstream, abcobj, abcschema);
     m_trans = GetComponent<Transform>();
 }
예제 #5
0
    public override void AbcSetup(AlembicStream abcStream,
                                  AbcAPI.aiObject abcObj,
                                  AbcAPI.aiSchema abcSchema)
    {
        base.AbcSetup(abcStream, abcObj, abcSchema);

        Light light = GetOrAddComponent<Light>();

        // Disable component for now
        light.enabled = false;
    }
예제 #6
0
 // called by loading thread
 public override void AbcOnUpdateSample(AbcAPI.aiSample sample)
 {
     switch (m_abcstream.m_data_type)
     {
         case AlembicStream.MeshDataType.Texture:
             AbcOnUpdateSample_Texture(sample);
             break;
         case AlembicStream.MeshDataType.Mesh:
             AbcOnUpdateSample_Mesh(sample);
             break;
     }
 }
예제 #7
0
    // No config overrides on AlembicPoints

    public override void AbcSampleUpdated(AbcAPI.aiSample sample, bool topologyChanged)
    {
        if(m_abcPositions == null)
        {
            m_abcPeakVertexCount = AbcAPI.aiPointsGetPeakVertexCount(m_abcSchema);
            m_abcPositions = new Vector3[m_abcPeakVertexCount];
            m_abcIDs = new Int64[m_abcPeakVertexCount];

            m_abcData.positions = Marshal.UnsafeAddrOfPinnedArrayElement(m_abcPositions, 0);
            m_abcData.ids = Marshal.UnsafeAddrOfPinnedArrayElement(m_abcIDs, 0);
        }

        AbcAPI.aiPointsGetData(sample, ref m_abcData);
        AbcDirty();
    }
예제 #8
0
    Mesh AddMeshComponents(AbcAPI.aiObject abc, GameObject gameObject)
    {
        Mesh mesh = null;
        
        MeshFilter meshFilter = gameObject.GetComponent<MeshFilter>();
        
        if (meshFilter == null || meshFilter.sharedMesh == null)
        {
            mesh = new Mesh();
            mesh.MarkDynamic();

            if (meshFilter == null)
            {
                meshFilter = gameObject.AddComponent<MeshFilter>();
            }

            meshFilter.sharedMesh = mesh;

            MeshRenderer renderer = gameObject.GetComponent<MeshRenderer>();

            if (renderer == null)
            {
                renderer = gameObject.AddComponent<MeshRenderer>();
            }

#if UNITY_EDITOR
            Material material = UnityEngine.Object.Instantiate(AbcUtils.GetDefaultMaterial());
            material.name = "Material_0";
            renderer.sharedMaterial = material;
#endif
        }
        else
        {
            mesh = meshFilter.sharedMesh;
        }

        return mesh;
    }
예제 #9
0
    public override void AbcSampleUpdated(AbcAPI.aiSample sample, bool topologyChanged)
    {
        AlembicMaterial abcMaterials = m_trans.GetComponent<AlembicMaterial>();

        if (abcMaterials != null)
        {
            if (abcMaterials.HasFacesetsChanged())
            {
                AbcVerboseLog("AlembicMesh.AbcSampleUpdated: Facesets updated, force topology update");
                topologyChanged = true;
            }

            hasFacesets = (abcMaterials.GetFacesetsCount() > 0);
        }
        else if (hasFacesets)
        {
            AbcVerboseLog("AlembicMesh.AbcSampleUpdated: Facesets cleared, force topology update");
            topologyChanged = true;
            hasFacesets = false;
        }

        if (m_freshSetup)
        {
            topologyChanged = true;

            m_freshSetup = false;
        }

        AbcAPI.aiPolyMeshGetSampleSummary(sample, ref m_sampleSummary, topologyChanged);

        AbcAPI.aiMeshSampleData vertexData = default(AbcAPI.aiMeshSampleData);

        UpdateSplits(m_sampleSummary.splitCount);

        for (int s=0; s<m_sampleSummary.splitCount; ++s)
        {
            Split split = m_splits[s];

            split.clear = topologyChanged;
            split.active = true;

            int vertexCount = AbcAPI.aiPolyMeshGetVertexBufferLength(sample, s);

            Array.Resize(ref split.positionCache, vertexCount);
            vertexData.positions = GetArrayPtr(split.positionCache);

            if (m_sampleSummary.hasNormals)
            {
                Array.Resize(ref split.normalCache, vertexCount);
                vertexData.normals = GetArrayPtr(split.normalCache);
            }
            else
            {
                Array.Resize(ref split.normalCache, 0);
                vertexData.normals = IntPtr.Zero;
            }

            if (m_sampleSummary.hasUVs)
            {
                Array.Resize(ref split.uvCache, vertexCount);
                vertexData.uvs = GetArrayPtr(split.uvCache);
            }
            else
            {
                Array.Resize(ref split.uvCache, 0);
                vertexData.uvs = IntPtr.Zero;
            }

            if (m_sampleSummary.hasTangents)
            {
                Array.Resize(ref split.tangentCache, vertexCount);
                vertexData.tangents = GetArrayPtr(split.tangentCache);
            }
            else
            {
                Array.Resize(ref split.tangentCache, 0);
                vertexData.tangents = IntPtr.Zero;
            }

            AbcAPI.aiPolyMeshFillVertexBuffer(sample, s, ref vertexData);

            split.center = vertexData.center;
            split.size = vertexData.size;
        }

        if (topologyChanged)
        {
            AbcAPI.aiFacesets facesets = default(AbcAPI.aiFacesets);
            AbcAPI.aiSubmeshSummary submeshSummary = default(AbcAPI.aiSubmeshSummary);
            AbcAPI.aiSubmeshData submeshData = default(AbcAPI.aiSubmeshData);

            if (abcMaterials != null)
            {
                abcMaterials.GetFacesets(ref facesets);
            }
            
            int numSubmeshes = AbcAPI.aiPolyMeshPrepareSubmeshes(sample, ref facesets);

            if (m_submeshes.Count > numSubmeshes)
            {
                m_submeshes.RemoveRange(numSubmeshes, m_submeshes.Count - numSubmeshes);
            }
            
            for (int s=0; s<m_sampleSummary.splitCount; ++s)
            {
                m_splits[s].submeshCount = AbcAPI.aiPolyMeshGetSplitSubmeshCount(sample, s);
            }

            while (AbcAPI.aiPolyMeshGetNextSubmesh(sample, ref submeshSummary))
            {
                if (submeshSummary.splitIndex >= m_splits.Count)
                {
                    Debug.Log("Invalid split index");
                    continue;
                }

                Submesh submesh = null;

                if (submeshSummary.index < m_submeshes.Count)
                {
                    submesh = m_submeshes[submeshSummary.index];
                }
                else
                {
                    submesh = new Submesh
                    {
                        indexCache = new int[0],
                        facesetIndex = -1,
                        splitIndex = -1,
                        index = -1,
                        update = true
                    };

                    m_submeshes.Add(submesh);
                }

                submesh.facesetIndex = submeshSummary.facesetIndex;
                submesh.splitIndex = submeshSummary.splitIndex;
                submesh.index = submeshSummary.splitSubmeshIndex;
                submesh.update = true;

                Array.Resize(ref submesh.indexCache, 3 * submeshSummary.triangleCount);

                submeshData.indices = GetArrayPtr(submesh.indexCache);

                AbcAPI.aiPolyMeshFillSubmeshIndices(sample, ref submeshSummary, ref submeshData);
            }
            
            if (abcMaterials != null)
            {
                abcMaterials.AknowledgeFacesetsChanges();
            }
        }
        else
        {
            for (int i=0; i<m_submeshes.Count; ++i)
            {
                m_submeshes[i].update = false;
            }
        }

        AbcDirty();
    }
예제 #10
0
    public override void AbcGetConfig(ref AbcAPI.aiConfig config)
    {
        if (m_normalsMode != AbcAPI.aiNormalsModeOverride.InheritStreamSetting)
        {
            config.normalsMode = (AbcAPI.aiNormalsMode) m_normalsMode;
        }

        if (m_tangentsMode != AbcAPI.aiTangentsModeOverride.InheritStreamSetting)
        {
            config.tangentsMode = (AbcAPI.aiTangentsMode) m_tangentsMode;
        }

        if (m_faceWinding != AbcAPI.aiFaceWindingOverride.InheritStreamSetting)
        {
            config.swapFaceWinding = (m_faceWinding == AbcAPI.aiFaceWindingOverride.Swap);
        }

        config.cacheTangentsSplits = m_cacheTangentsSplits;

        // if 'forceUpdate' is set true, even if alembic sample data do not change at all
        // AbcSampleUpdated will still be called (topologyChanged will be false)

        AlembicMaterial abcMaterials = m_trans.GetComponent<AlembicMaterial>();

        config.forceUpdate = m_freshSetup || (abcMaterials != null ? abcMaterials.HasFacesetsChanged() : hasFacesets);
    }
예제 #11
0
    public override void AbcSetup(AlembicStream abcStream,
                                  AbcAPI.aiObject abcObj,
                                  AbcAPI.aiSchema abcSchema)
    {
        base.AbcSetup(abcStream, abcObj, abcSchema);

        AbcAPI.aiPolyMeshGetSummary(abcSchema, ref m_summary);

        m_freshSetup = true;
    }
예제 #12
0
    // No config override

    public override void AbcSampleUpdated(AbcAPI.aiSample sample, bool topologyChanged)
    {
        // ToDo
    }
예제 #13
0
    // No config overrides on AlembicXForm

    public override void AbcSampleUpdated(AbcAPI.aiSample sample, bool topologyChanged)
    {
        AbcAPI.aiXFormGetData(sample, ref m_abcData);

        AbcDirty();
    }
예제 #14
0
 public override void AbcOnUpdateSample(AbcAPI.aiSample sample)
 {
 }
예제 #15
0
    public override void AbcSetup(
        AlembicStream abcstream,
        AbcAPI.aiObject abcobj,
        AbcAPI.aiSchema abcschema)
    {
        base.AbcSetup(abcstream, abcobj, abcschema);
        m_trans = GetComponent<Transform>();

        AbcAPI.aiPolyMeshGetSchemaSummary(abcschema, ref m_schema_summary);
        int peak_index_count = (int)m_schema_summary.peak_index_count;
        int peak_vertex_count = (int)m_schema_summary.peak_vertex_count;

        if(GetComponent<MeshRenderer>()==null)
        {
            int num_mesh_objects = AlembicUtils.ceildiv(peak_index_count, max_indices);

            AddMeshComponents(abcobj, m_trans, abcstream.m_data_type);
            var entry = new AlembicMesh.Entry
            {
                host = m_trans.gameObject,
                mesh = GetComponent<MeshFilter>().sharedMesh,
                renderer = GetComponent<MeshRenderer>(),
            };
            m_meshes.Add(entry);
        #if UNITY_EDITOR
            if (abcstream.m_data_type == AlembicStream.MeshDataType.Mesh)
            {
                GetComponent<MeshRenderer>().sharedMaterial = GetDefaultMaterial();
            }
            else if(abcstream.m_data_type == AlembicStream.MeshDataType.Texture)
            {
                GetComponent<MeshRenderer>().sharedMaterial = AssetDatabase.LoadAssetAtPath<Material>("Assets/AlembicImporter/Materials/AlembicStandard.mat");
            }
        #endif

            for (int i = 1; i < num_mesh_objects; ++i)
            {
                string name = "Submesh_" + i;

                GameObject go = new GameObject();
                Transform child = go.GetComponent<Transform>();
                go.name = name;
                child.parent = m_trans;
                child.localPosition = Vector3.zero;
                child.localEulerAngles = Vector3.zero;
                child.localScale = Vector3.one;
                Mesh mesh = AddMeshComponents(abcobj, child, m_abcstream.m_data_type);
                mesh.name = name;
                child.GetComponent<MeshRenderer>().sharedMaterial = GetComponent<MeshRenderer>().sharedMaterial;

                entry = new Entry
                {
                    host = go,
                    mesh = mesh,
                    renderer = child.GetComponent<MeshRenderer>(),
                };
                m_meshes.Add(entry);
            }
        }

        if (abcstream.m_data_type == AlembicStream.MeshDataType.Mesh)
        {
            for (int i = 0; i < m_meshes.Count; ++i)
            {
                m_meshes[i].buf_indices = new int[0];
                m_meshes[i].buf_vertices = new Vector3[0];
                m_meshes[i].buf_normals = new Vector3[0];
                m_meshes[i].buf_uvs = new Vector2[0];
            }
        }
        else if (abcstream.m_data_type == AlembicStream.MeshDataType.Texture)
        {
            m_mtex = new TextureMeshData();
            m_abc_mtex = new AbcAPI.aiTextureMeshData();
            m_abc_mtex.tex_width = MeshTextureWidth;

            m_mtex.indices = CreateDataTexture(peak_index_count, 1, RenderTextureFormat.RInt);
            m_abc_mtex.tex_indices = m_mtex.indices.GetNativeTexturePtr();

            m_mtex.vertices = CreateDataTexture(peak_vertex_count, 3, RenderTextureFormat.RFloat);
            m_abc_mtex.tex_vertices = m_mtex.vertices.GetNativeTexturePtr();

            if (m_schema_summary.has_normals != 0)
            {
                int normal_count = m_schema_summary.is_normals_indexed != 0 ? peak_vertex_count : peak_index_count;
                m_mtex.normals = CreateDataTexture(normal_count, 3, RenderTextureFormat.RFloat);
                m_abc_mtex.tex_normals = m_mtex.normals.GetNativeTexturePtr();
            }
            if (m_schema_summary.has_uvs != 0)
            {
                int uv_count = m_schema_summary.is_uvs_indexed != 0 ? peak_vertex_count : peak_index_count;
                m_mtex.uvs = CreateDataTexture(uv_count, 2, RenderTextureFormat.RFloat);
                m_abc_mtex.tex_uvs = m_mtex.uvs.GetNativeTexturePtr();
            }
            if (m_schema_summary.has_velocities != 0)
            {
                m_mtex.velocities = CreateDataTexture(peak_vertex_count, 3, RenderTextureFormat.RFloat);
                m_abc_mtex.tex_velocities = m_mtex.velocities.GetNativeTexturePtr();
            }

            for (int i = 0; i < m_meshes.Count; ++i)
            {
                m_meshes[i].mpb = new MaterialPropertyBlock();
                m_meshes[i].mpb.SetVector("_DrawData", Vector4.zero);

                m_meshes[i].mpb.SetTexture("_Indices", m_mtex.indices);
                m_meshes[i].mpb.SetTexture("_Vertices", m_mtex.vertices);
                if (m_mtex.normals != null) { m_meshes[i].mpb.SetTexture("_Normals", m_mtex.normals); }
                if (m_mtex.uvs != null) { m_meshes[i].mpb.SetTexture("_UVs", m_mtex.uvs); }
                if (m_mtex.velocities != null) { m_meshes[i].mpb.SetTexture("_Velocities", m_mtex.velocities); }

                m_meshes[i].renderer.SetPropertyBlock(m_meshes[i].mpb);
            }
        }
    }
예제 #16
0
        /// <summary>
        /// Writes the current frame to the Alembic archive. Recording should have been previously started.
        /// </summary>

        public void ProcessRecording()
        {
            if (!m_recording)
            {
                return;
            }

            float begin_time = Time.realtimeSinceStartup;

            // check if there are new GameObjects to capture
            UpdateCaptureNodes();
            if (m_frameCount > 0 && m_newNodes.Count > 0)
            {
                // add invisible sample
                m_ctx.MarkFrameBegin();
                foreach (var node in m_newNodes)
                {
                    node.MarkForceInvisible();
                    node.Capture();
                }
                m_ctx.MarkFrameEnd();
            }
            m_newNodes.Clear();

            // do capture
            m_ctx.MarkFrameBegin();
            m_ctx.AddTime(m_time);
            foreach (var kvp in m_nodes)
            {
                var node = kvp.Value;
                node.Capture();
                if (node.transform == null)
                {
                    m_iidToRemove.Add(node.instanceID);
                }
            }
            m_ctx.MarkFrameEnd();

            // remove deleted GameObjects
            foreach (int iid in m_iidToRemove)
            {
                m_nodes.Remove(iid);
            }
            m_iidToRemove.Clear();

            // advance time
            ++m_frameCount;
            m_timePrev = m_time;
            switch (m_settings.ExportOptions.TimeSamplingType)
            {
            case TimeSamplingType.Uniform:
                m_time = (1.0f / m_settings.ExportOptions.FrameRate) * m_frameCount;
                break;

            case TimeSamplingType.Acyclic:
                m_time += Time.deltaTime;
                break;
            }
            m_elapsed = Time.realtimeSinceStartup - begin_time;

            // wait maximumDeltaTime if timeSamplingType is uniform
            if (m_settings.ExportOptions.TimeSamplingType == TimeSamplingType.Uniform && m_settings.FixDeltaTime)
            {
                AbcAPI.aeWaitMaxDeltaTime();
            }

            if (m_settings.DetailedLog)
            {
                Debug.Log("AlembicRecorder: frame " + m_frameCount + " (" + (m_elapsed * 1000.0f) + " ms)");
            }
        }
예제 #17
0
    // No config overrides on AlembicXForm

    public override void AbcSampleUpdated(AbcAPI.aiSample sample, bool topologyChanged)
    {
        AbcAPI.aiXFormGetData(sample, ref m_abcData);
        
        AbcDirty();
    }
예제 #18
0
    // called by loading thread
    void AbcOnUpdateSample_Mesh(AbcAPI.aiSample sample)
    {
        var schema = m_abcschema;
        var smi_prev = default(AbcAPI.aiSplitedMeshInfo);
        var smi = default(AbcAPI.aiSplitedMeshInfo);
        AbcAPI.aiPolyMeshGetSampleSummary(sample, ref m_mesh_summary);

        int nth_submesh = 0;
        for (; ; )
        {
            smi_prev = smi;
            smi = default(AbcAPI.aiSplitedMeshInfo);
            bool is_end = AbcAPI.aiPolyMeshGetSplitedMeshInfo(sample, ref smi, ref smi_prev, max_vertices);

            AlembicMesh.Entry entry;
            if (nth_submesh < m_meshes.Count)
            {
                entry = m_meshes[nth_submesh];
                entry.active = true;
            }
            else
            {
                Debug.Log("AlembicMesh: not enough submeshes!");
                break;
            }

            entry.update_index = entry.buf_indices.Length == 0 ||
                m_schema_summary.topology_variance == AbcAPI.aiTopologyVariance.Heterogeneous;

            Array.Resize(ref entry.buf_vertices, (int)smi.vertex_count);
            smi.dst_vertices = Marshal.UnsafeAddrOfPinnedArrayElement(entry.buf_vertices, 0);

            if (m_mesh_summary.has_normals != 0)
            {
                Array.Resize(ref entry.buf_normals, (int)smi.vertex_count);
                smi.dst_normals = Marshal.UnsafeAddrOfPinnedArrayElement(entry.buf_normals, 0);
            }

            if (entry.update_index)
            {
                if (m_mesh_summary.has_uvs != 0)
                {
                    Array.Resize(ref entry.buf_uvs, (int)smi.vertex_count);
                    smi.dst_uvs = Marshal.UnsafeAddrOfPinnedArrayElement(entry.buf_uvs, 0);
                }

                Array.Resize(ref entry.buf_indices, (int)smi.triangulated_index_count);
                smi.dst_indices = Marshal.UnsafeAddrOfPinnedArrayElement(entry.buf_indices, 0);
            }

            AbcAPI.aiPolyMeshCopySplitedMesh(sample, ref smi);

            ++nth_submesh;
            if (is_end) { break; }
        }

        for (int i = nth_submesh + 1; i < m_meshes.Count; ++i)
        {
            m_meshes[i].active = false;
        }
    }
예제 #19
0
    static Mesh AddMeshComponents(AbcAPI.aiObject abc, Transform trans, AlembicStream.MeshDataType mdt)
    {
        Mesh mesh = null;

        var mesh_filter = trans.GetComponent<MeshFilter>();
        var mesh_renderer = trans.GetComponent<MeshRenderer>();
        if (mesh_filter == null)
        {
            mesh_filter = trans.gameObject.AddComponent<MeshFilter>();
        }
        if (mesh_renderer == null)
        {
            trans.gameObject.AddComponent<MeshRenderer>();
        }

        if (mdt == AlembicStream.MeshDataType.Texture)
        {
        #if UNITY_EDITOR
            mesh = AssetDatabase.LoadAssetAtPath<Mesh>("Assets/AlembicImporter/Meshes/IndexOnlyMesh.asset");
        #endif
        }
        else
        {
            mesh = new Mesh();
            mesh.name = AbcAPI.aiGetName(abc);
            mesh.MarkDynamic();
        }
        mesh_filter.sharedMesh = mesh;

        return mesh;
    }
예제 #20
0
 public void GetFacesets(ref AbcAPI.aiFacesets facesets)
 {
     facesets.count = facesetsCache.faceCounts.Length;
     facesets.faceCounts = Marshal.UnsafeAddrOfPinnedArrayElement(facesetsCache.faceCounts, 0);
     facesets.faceIndices = Marshal.UnsafeAddrOfPinnedArrayElement(facesetsCache.faceIndices, 0);
 }
 public override void CreateAbcObject(AbcAPI.aeObject parent)
 {
     m_abc = AbcAPI.aeNewPoints(parent, gameObject.name);
 }
 public abstract void CreateAbcObject(AbcAPI.aeObject parent);
예제 #23
0
 // called by loading thread
 void AbcOnUpdateSample_Texture(AbcAPI.aiSample sample)
 {
 }
 public override void CreateAbcObject(AbcAPI.aeObject parent)
 {
     m_abc = AbcAPI.aeNewPoints(parent, gameObject.name);
 }
예제 #25
0
 public override void AbcOnUpdateSample(AbcAPI.aiSample sample)
 {
     AbcAPI.aiCameraGetData(sample, ref m_abcdata);
 }
예제 #26
0
    public override void AbcSampleUpdated(AbcAPI.aiSample sample, bool topologyChanged)
    {
        AlembicMaterial abcMaterials = m_trans.GetComponent <AlembicMaterial>();

        if (abcMaterials != null)
        {
            if (abcMaterials.HasFacesetsChanged())
            {
                AbcVerboseLog("AlembicMesh.AbcSampleUpdated: Facesets updated, force topology update");
                topologyChanged = true;
            }

            hasFacesets = (abcMaterials.GetFacesetsCount() > 0);
        }
        else if (hasFacesets)
        {
            AbcVerboseLog("AlembicMesh.AbcSampleUpdated: Facesets cleared, force topology update");
            topologyChanged = true;
            hasFacesets     = false;
        }

        if (m_freshSetup)
        {
            topologyChanged = true;

            m_freshSetup = false;
        }

        AbcAPI.aiPolyMeshGetSampleSummary(sample, ref m_sampleSummary, topologyChanged);

        AbcAPI.aiPolyMeshData vertexData = default(AbcAPI.aiPolyMeshData);

        UpdateSplits(m_sampleSummary.splitCount);

        for (int s = 0; s < m_sampleSummary.splitCount; ++s)
        {
            Split split = m_splits[s];

            split.clear  = topologyChanged;
            split.active = true;

            int vertexCount = AbcAPI.aiPolyMeshGetVertexBufferLength(sample, s);

            Array.Resize(ref split.positionCache, vertexCount);
            vertexData.positions = GetArrayPtr(split.positionCache);

            if (m_sampleSummary.hasNormals)
            {
                Array.Resize(ref split.normalCache, vertexCount);
                vertexData.normals = GetArrayPtr(split.normalCache);
            }
            else
            {
                Array.Resize(ref split.normalCache, 0);
                vertexData.normals = IntPtr.Zero;
            }

            if (m_sampleSummary.hasUVs)
            {
                Array.Resize(ref split.uvCache, vertexCount);
                vertexData.uvs = GetArrayPtr(split.uvCache);
            }
            else
            {
                Array.Resize(ref split.uvCache, 0);
                vertexData.uvs = IntPtr.Zero;
            }

            if (m_sampleSummary.hasTangents)
            {
                Array.Resize(ref split.tangentCache, vertexCount);
                vertexData.tangents = GetArrayPtr(split.tangentCache);
            }
            else
            {
                Array.Resize(ref split.tangentCache, 0);
                vertexData.tangents = IntPtr.Zero;
            }

            AbcAPI.aiPolyMeshFillVertexBuffer(sample, s, ref vertexData);

            split.center = vertexData.center;
            split.size   = vertexData.size;
        }

        if (topologyChanged)
        {
            AbcAPI.aiFacesets       facesets       = default(AbcAPI.aiFacesets);
            AbcAPI.aiSubmeshSummary submeshSummary = default(AbcAPI.aiSubmeshSummary);
            AbcAPI.aiSubmeshData    submeshData    = default(AbcAPI.aiSubmeshData);

            if (abcMaterials != null)
            {
                abcMaterials.GetFacesets(ref facesets);
            }

            int numSubmeshes = AbcAPI.aiPolyMeshPrepareSubmeshes(sample, ref facesets);

            if (m_submeshes.Count > numSubmeshes)
            {
                m_submeshes.RemoveRange(numSubmeshes, m_submeshes.Count - numSubmeshes);
            }

            for (int s = 0; s < m_sampleSummary.splitCount; ++s)
            {
                m_splits[s].submeshCount = AbcAPI.aiPolyMeshGetSplitSubmeshCount(sample, s);
            }

            while (AbcAPI.aiPolyMeshGetNextSubmesh(sample, ref submeshSummary))
            {
                if (submeshSummary.splitIndex >= m_splits.Count)
                {
                    Debug.Log("Invalid split index");
                    continue;
                }

                Submesh submesh = null;

                if (submeshSummary.index < m_submeshes.Count)
                {
                    submesh = m_submeshes[submeshSummary.index];
                }
                else
                {
                    submesh = new Submesh
                    {
                        indexCache   = new int[0],
                        facesetIndex = -1,
                        splitIndex   = -1,
                        index        = -1,
                        update       = true
                    };

                    m_submeshes.Add(submesh);
                }

                submesh.facesetIndex = submeshSummary.facesetIndex;
                submesh.splitIndex   = submeshSummary.splitIndex;
                submesh.index        = submeshSummary.splitSubmeshIndex;
                submesh.update       = true;

                Array.Resize(ref submesh.indexCache, 3 * submeshSummary.triangleCount);

                submeshData.indices = GetArrayPtr(submesh.indexCache);

                AbcAPI.aiPolyMeshFillSubmeshIndices(sample, ref submeshSummary, ref submeshData);
            }

            if (abcMaterials != null)
            {
                abcMaterials.AknowledgeFacesetsChanges();
            }
        }
        else
        {
            for (int i = 0; i < m_submeshes.Count; ++i)
            {
                m_submeshes[i].update = false;
            }
        }

        AbcDirty();
    }