From 378b3837130652d6a22fb631e9845d1164b6996a Mon Sep 17 00:00:00 2001 From: Vlad-Andrei Lazar Date: Wed, 30 Nov 2022 13:18:43 -0500 Subject: [PATCH 1/7] first commit --- Source/abci/Importer/AlembicImporter.h | 4 + Source/abci/Importer/aiMeshSchema.h | 77 ++++++++++++++++++- .../Runtime/Scripts/Importer/AbcAPI.cs | 3 + .../Runtime/Scripts/Importer/AlembicMesh.cs | 45 +++++++++++ .../Unity.Formats.Alembic.Runtime.asmdef | 3 +- com.unity.formats.alembic/package.json | 7 +- 6 files changed, 132 insertions(+), 7 deletions(-) diff --git a/Source/abci/Importer/AlembicImporter.h b/Source/abci/Importer/AlembicImporter.h index 2bfa5e673..d09f8ec7f 100644 --- a/Source/abci/Importer/AlembicImporter.h +++ b/Source/abci/Importer/AlembicImporter.h @@ -148,6 +148,7 @@ struct aiMeshSummary bool constant_uv1 = false; bool constant_rgba = false; bool constant_rgb = false; + int numV2FVertexProperties = 0; }; struct aiMeshSampleSummary @@ -189,6 +190,7 @@ struct aiPolyMeshData abcV2 *uv1 = nullptr; abcV4 *rgba = nullptr; abcV4 *rgb = nullptr; + void **v2fParams = nullptr; int *indices = nullptr; int vertex_count = 0; @@ -196,6 +198,8 @@ struct aiPolyMeshData abcV3 center = { 0.0f, 0.0f, 0.0f }; abcV3 extents = { 0.0f, 0.0f, 0.0f }; + + // need the data for c# }; struct aiSubmeshData diff --git a/Source/abci/Importer/aiMeshSchema.h b/Source/abci/Importer/aiMeshSchema.h index 5fa830d25..e92a8f1f6 100644 --- a/Source/abci/Importer/aiMeshSchema.h +++ b/Source/abci/Importer/aiMeshSchema.h @@ -64,6 +64,8 @@ class aiMeshTopology RawVector m_remap_rgba; RawVector m_remap_rgb; + std::vector> m_remap_m_IV2fGeomParam; + int m_vertex_count = 0; int m_index_count = 0; // triangulated }; @@ -95,6 +97,10 @@ class aiMeshSample : public aiSample AbcGeom::IC3fGeomParam::Sample m_rgb_sp, m_rgb_sp2; Abc::Box3d m_bounds; + std::vector m_IV2fGeomParam_sp; + std::vector > m_IV2fGeomParam_ref; + std::vector >m_IV2fGeomParam; + IArray m_points_ref; IArray m_velocities_ref; IArray m_uv0_ref, m_uv1_ref; @@ -112,6 +118,8 @@ class aiMeshSample : public aiSample RawVector m_rgba, m_rgba2, m_rgba_int; RawVector m_rgb, m_rgb2, m_rgb_int; + //// props + TopologyPtr m_topology; bool m_topology_changed = false; @@ -147,13 +155,15 @@ class aiMeshSchema : public aiTSchema protected: virtual AbcGeom::IN3fGeomParam readNormalsParam(); aiMeshSummaryInternal m_summary; - AbcGeom::IV2fGeomParam m_uv1_param; + AbcGeom::IV2fGeomParam m_uv1_param; // obsolete AbcGeom::IC4fGeomParam m_rgba_param; AbcGeom::IC3fGeomParam m_rgb_param; TopologyPtr m_shared_topology; abcFaceSetSchemas m_facesets; bool m_varying_topology = false; + + std::vector m_IV2fGeomParam; }; template @@ -190,7 +200,12 @@ inline aiMeshSchema::aiMeshSchema(aiObject * parent, const abcObject & abc // uv if (AbcGeom::IV2fGeomParam::matches(header)) { - m_uv1_param = AbcGeom::IV2fGeomParam(geom_params, header.getName()); + m_uv1_param = AbcGeom::IV2fGeomParam(geom_params, header.getName()); // obsolete + } + + if (AbcGeom::IV2fGeomParam::matches(header)) + { + m_IV2fGeomParam.push_back(AbcGeom::IV2fGeomParam(geom_params, header.getName())); // obsolete } } } @@ -422,6 +437,8 @@ void aiMeshSchema::updateSummary() if (summary.has_rgb_prop && !summary.constant_rgb) summary.interpolate_rgb = true; } + + summary.numV2FVertexProperties = m_IV2fGeomParam.size(); } template @@ -539,6 +556,24 @@ void aiMeshSchema::readSampleBody(U& sample, uint64_t idx) } } + if (sample.m_IV2fGeomParam_sp.size() !=m_IV2fGeomParam.size() ) + { + sample.m_IV2fGeomParam_sp = std::vector(m_IV2fGeomParam.size()); + } + + if (sample.m_IV2fGeomParam_ref.size() !=m_IV2fGeomParam.size() ) + { + sample.m_IV2fGeomParam_ref = std::vector >(m_IV2fGeomParam.size()); + } + + for (int i=0;im_schema.getSelfBoundsProperty(); if (bounds_param && bounds_param.getNumSamples() > 0) bounds_param.get(sample.m_bounds, ss); @@ -562,7 +597,7 @@ void aiMeshSchema::cookSampleBody(U& sample) { onTopologyChange(sample); } - else if (this->m_sample_index_changed) + else if (this->m_sample_index_changed) // Not happening in solutions { onTopologyDetermined(); @@ -966,6 +1001,42 @@ void aiMeshSchema::onTopologyChange(U& sample) } + /// Arbitrary V2f attributes + if (sample.m_IV2fGeomParam.size() != sample.m_IV2fGeomParam_sp.size()) + { + sample.m_IV2fGeomParam = std::vector>(sample.m_IV2fGeomParam_sp.size()); + } + + if (topology.m_remap_m_IV2fGeomParam.size() != sample.m_IV2fGeomParam_sp.size()) + { + topology.m_remap_m_IV2fGeomParam = std::vector>(sample.m_IV2fGeomParam_sp.size()); + } + + for (int i=0;i src{sp.getVals()->get(), sp.getVals()->size()}; + auto &dst = sample.m_IV2fGeomParam[i]; + + if (sp.isIndexed() && sp.getIndices()->size() == refiner.indices.size()) + { + IArray indices{(int *) sp.getIndices()->get(), sp.getIndices()->size()}; + refiner.template addIndexedAttribute(src, indices, dst, topology.m_remap_m_IV2fGeomParam[i]); + } + else if (src.size() == refiner.indices.size()) + { + refiner.template addExpandedAttribute(src, dst, topology.m_remap_m_IV2fGeomParam[i]); + } + else if (src.size() == refiner.points.size()) + { + refiner.template addIndexedAttribute(src, refiner.indices, dst, topology.m_remap_m_IV2fGeomParam[i]); + } + } + } + /// + refiner.refine(); refiner.retopology(config.swap_face_winding); diff --git a/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs b/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs index f98350f04..9eed8c8c4 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs @@ -158,6 +158,7 @@ struct aiMeshSummary public Bool constantUV1 { get; set; } public Bool constantRgba { get; set; } public Bool constantRgb { get; set; } + public int numV2FVertexProperties { get; set; } } [StructLayout(LayoutKind.Sequential)] @@ -202,6 +203,8 @@ unsafe struct aiPolyMeshData public void* uv1; public void* rgba; public void* rgb; + public void* v2fProps; + public IntPtr indices; diff --git a/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs b/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs index a40a4125d..bc1de2b87 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs @@ -36,6 +36,7 @@ internal class Split : IDisposable public NativeArray uv1; public NativeArray rgba; public NativeArray rgb; + public UnsafeList> v2fParams; public Mesh mesh; public GameObject host; @@ -61,6 +62,18 @@ public void Dispose() uv1.DisposeIfPossible(); rgba.DisposeIfPossible(); rgb.DisposeIfPossible(); + + if (v2fParams.IsCreated) + { + foreach (var t in v2fParams) + { + var v2FParam = t; + v2FParam.DisposeIfPossible(); + } + + v2fParams.Dispose(); + } + if (mesh != null && (mesh.hideFlags & HideFlags.DontSave) != 0) { DestroyUnityObject(mesh); @@ -255,6 +268,38 @@ public override unsafe void AbcSyncDataBegin() } vertexData.rgb = split.rgb.GetPointer(); + if (m_summary.numV2FVertexProperties > 0 && topologyChanged) + { + if (!split.v2fParams.IsCreated) + { + split.v2fParams = + new UnsafeList>(m_summary.numV2FVertexProperties, + Allocator.Persistent); + } + + var prevSize = split.v2fParams.Length; + split.v2fParams.Resize(m_summary.numV2FVertexProperties); + for (var i = prevSize; i < split.v2fParams.Length; ++i) + { + split.v2fParams[i] = new NativeArray(0, Allocator.Persistent); + } + + + using (var v2fs = new NativeArray(m_summary.numV2FVertexProperties, Allocator.Temp)) + { + for (var i = 0; i < m_summary.numV2FVertexProperties; ++i) + { + var arr = split.v2fParams[i]; + arr.ResizeIfNeeded(vertexCount); + var nativeArray = v2fs; + nativeArray[i] = new IntPtr(arr.GetPointer()); + split.v2fParams[i] = arr; + } + + vertexData.v2fProps = v2fs.GetUnsafePtr(); + } + } + m_splitData[spi] = vertexData; } diff --git a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.asmdef b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.asmdef index fa057d1d6..8dde43781 100644 --- a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.asmdef +++ b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.asmdef @@ -3,7 +3,8 @@ "rootNamespace": "", "references": [ "Unity.Timeline", - "Unity.Burst" + "Unity.Burst", + "Unity.Collections" ], "includePlatforms": [ "Editor", diff --git a/com.unity.formats.alembic/package.json b/com.unity.formats.alembic/package.json index 0c39f6fdf..213c2d419 100644 --- a/com.unity.formats.alembic/package.json +++ b/com.unity.formats.alembic/package.json @@ -2,7 +2,8 @@ "dependencies": { "com.unity.timeline": "1.0.0", "com.unity.modules.unityanalytics": "1.0.0", - "com.unity.modules.cloth": "1.0.0" + "com.unity.modules.cloth": "1.0.0", + "com.unity.collections" : "1.0.0" }, "description": "Import and export Alembic files (.abc), record and stream animations in the Alembic format directly in Unity.\nNOTE: Supported build platforms: only Windows 64, MacOS X, Linux 64, and Stadia.\n\nThe Alembic format is commonly used in animation to transfer facial, cloth, and other simulation between applications in the form of baked data.", "displayName": "Alembic", @@ -15,6 +16,6 @@ "simulation" ], "name": "com.unity.formats.alembic", - "unity": "2019.4", - "version": "2.3.1" + "unity": "2023.1", + "version": "2.4.0-pre.1" } From 5ddc728043da5d08e08358227edcb6669ceaaa32 Mon Sep 17 00:00:00 2001 From: Vlad-Andrei Lazar Date: Thu, 1 Dec 2022 08:49:26 -0500 Subject: [PATCH 2/7] Got strings --- Source/abci/Importer/AlembicImporter.cpp | 7 ++++ Source/abci/Importer/AlembicImporter.h | 7 +++- Source/abci/Importer/aiMeshSchema.cpp | 2 + Source/abci/Importer/aiMeshSchema.h | 40 ++++++++++++++++++- .../Runtime/Scripts/Exporter/AbcAPI.cs | 2 + .../Runtime/Scripts/Importer/AbcAPI.cs | 11 ++++- .../Runtime/Scripts/Importer/AlembicMesh.cs | 25 ++++++++++++ .../Importer/Behaviours/AlembicCustomData.cs | 10 +++++ .../Runtime/Unity.Formats.Alembic.Runtime.api | 6 +++ 9 files changed, 107 insertions(+), 3 deletions(-) diff --git a/Source/abci/Importer/AlembicImporter.cpp b/Source/abci/Importer/AlembicImporter.cpp index 2f5eb2693..463af7d2c 100644 --- a/Source/abci/Importer/AlembicImporter.cpp +++ b/Source/abci/Importer/AlembicImporter.cpp @@ -254,6 +254,13 @@ abciAPI void aiPolyMeshFillVertexBuffer(aiPolyMeshSample* sample, aiPolyMeshData sample->fillVertexBuffer(vbs, ibs); } +abciAPI char* aiPolyMeshReadPropertyName(aiPolyMeshSample* sample, int idx) +{ + if (sample) + return sample->readPropertyName(idx); + return "\0"; +} + abciAPI void aiSubDGetSummary(aiSubD* schema, aiMeshSummary* dst) { if (schema) diff --git a/Source/abci/Importer/AlembicImporter.h b/Source/abci/Importer/AlembicImporter.h index d09f8ec7f..f48bd06d2 100644 --- a/Source/abci/Importer/AlembicImporter.h +++ b/Source/abci/Importer/AlembicImporter.h @@ -16,6 +16,7 @@ class aiPolyMeshSample; // : aiSample class aiSubDSample; // : aiSample class aiPointsSample; // : aiSample class aiCurves; +struct FixedString128; #else // force make castable using aiSchema = void; @@ -190,7 +191,8 @@ struct aiPolyMeshData abcV2 *uv1 = nullptr; abcV4 *rgba = nullptr; abcV4 *rgb = nullptr; - void **v2fParams = nullptr; + abcV2 **v2fParams = nullptr; + // FixedString128* v2fParamNames = nullptr; int *indices = nullptr; int vertex_count = 0; @@ -326,6 +328,7 @@ abciAPI void aiPolyMeshGetSampleSummary(aiPolyMeshSample* sample, aiM abciAPI void aiPolyMeshGetSplitSummaries(aiPolyMeshSample* sample, aiMeshSplitSummary *dst); abciAPI void aiPolyMeshGetSubmeshSummaries(aiPolyMeshSample* sample, aiSubmeshSummary* dst); abciAPI void aiPolyMeshFillVertexBuffer(aiPolyMeshSample* sample, aiPolyMeshData* vbs, aiSubmeshData* ibs); +abciAPI char* aiPolyMeshReadPropertyName(aiPolyMeshSample* sample, int idx); abciAPI void aiSubDGetSummary(aiSubD* schema, aiMeshSummary* dst); abciAPI void aiSubDGetSampleSummary(aiSubDSample* sample, aiMeshSampleSummary* dst); @@ -347,3 +350,5 @@ abciAPI void aiPointsFillData(aiPointsSample* sample, aiPointsData *d abciAPI const char* aiPropertyGetName(aiProperty* prop); abciAPI aiPropertyType aiPropertyGetType(aiProperty* prop); abciAPI void aiPropertyCopyData(aiProperty* prop, const abcSampleSelector *ss, aiPropertyData *dst); + + diff --git a/Source/abci/Importer/aiMeshSchema.cpp b/Source/abci/Importer/aiMeshSchema.cpp index d0d386490..9a736ce2c 100644 --- a/Source/abci/Importer/aiMeshSchema.cpp +++ b/Source/abci/Importer/aiMeshSchema.cpp @@ -7,6 +7,8 @@ #include "aiMeshSchema.h" #include "aiSubD.h" + constexpr size_t FixedString128::MaxLength; + aiMeshTopology::aiMeshTopology() { } diff --git a/Source/abci/Importer/aiMeshSchema.h b/Source/abci/Importer/aiMeshSchema.h index e92a8f1f6..14fbe2b9d 100644 --- a/Source/abci/Importer/aiMeshSchema.h +++ b/Source/abci/Importer/aiMeshSchema.h @@ -1,4 +1,5 @@ #pragma once +#include #include "aiMeshOps.h" namespace @@ -13,6 +14,15 @@ namespace } } } + +struct FixedString128 +{ + static constexpr size_t MaxLength = 126; + unsigned short Length; + char String[MaxLength]; +}; + + using abcFaceSetSchemas = std::vector; using abcFaceSetSamples = std::vector; @@ -86,6 +96,7 @@ class aiMeshSample : public aiSample void fillSplitVertices(int split_index, aiPolyMeshData &data) const; void fillSubmeshIndices(int submesh_index, aiSubmeshData &data) const; void fillVertexBuffer(aiPolyMeshData* vbs, aiSubmeshData* ibs); + char* readPropertyName(int index); public: Abc::P3fArraySamplePtr m_points_sp, m_points_sp2; @@ -98,7 +109,8 @@ class aiMeshSample : public aiSample Abc::Box3d m_bounds; std::vector m_IV2fGeomParam_sp; - std::vector > m_IV2fGeomParam_ref; + std::vector m_IV2fGeomParamName; + std::vector> m_IV2fGeomParam_ref; // useless for now std::vector >m_IV2fGeomParam; IArray m_points_ref; @@ -566,9 +578,16 @@ void aiMeshSchema::readSampleBody(U& sample, uint64_t idx) sample.m_IV2fGeomParam_ref = std::vector >(m_IV2fGeomParam.size()); } + if (sample.m_IV2fGeomParamName.size() !=m_IV2fGeomParam.size() ) + { + sample.m_IV2fGeomParamName = std::vector(m_IV2fGeomParam.size()); + } + for (int i=0;i::onTopologyChange(U& sample) for (int i=0;i::fillSplitVertices(int split_index, aiPolyMeshData &data) c copy_or_clear(data.uv1, m_uv1_ref, split); copy_or_clear((abcC4*)data.rgba, m_rgba_ref, split); copy_or_clear_3_to_4((abcC4*)data.rgb, m_rgb_ref, split); + + for (int i=0;i @@ -1274,3 +1306,9 @@ void aiMeshSample::fillVertexBuffer(aiPolyMeshData * vbs, aiSubmeshData * ibs for (int smi = 0; smi < (int)refiner.submeshes.size(); ++smi) fillSubmeshIndices(smi, ibs[smi]); } + +template +char* aiMeshSample::readPropertyName(int idx) +{ + return &(m_IV2fGeomParamName[idx].String[0]); +} \ No newline at end of file diff --git a/com.unity.formats.alembic/Runtime/Scripts/Exporter/AbcAPI.cs b/com.unity.formats.alembic/Runtime/Scripts/Exporter/AbcAPI.cs index b56b1006d..d387508aa 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Exporter/AbcAPI.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Exporter/AbcAPI.cs @@ -411,6 +411,8 @@ static class NativeMethods [DllImport(Abci.Lib)] public static extern void aiPolyMeshGetSubmeshSummaries(IntPtr sample, IntPtr dst); [DllImport(Abci.Lib)] public static extern void aiPolyMeshFillVertexBuffer(IntPtr sample, IntPtr vbs, IntPtr ibs); + [DllImport(Abci.Lib)] public static extern unsafe char* aiPolyMeshReadPropertyName(IntPtr sample, int idx); + [DllImport(Abci.Lib)] public static extern void aiPointsGetSampleSummary(IntPtr sample, ref aiPointsSampleSummary dst); [DllImport(Abci.Lib)] public static extern void aiPointsFillData(IntPtr sample, IntPtr dst); diff --git a/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs b/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs index 9eed8c8c4..25ff0e904 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs @@ -204,7 +204,7 @@ unsafe struct aiPolyMeshData public void* rgba; public void* rgb; public void* v2fProps; - + // public void* v2fPropsNames; public IntPtr indices; @@ -554,6 +554,15 @@ internal void FillVertexBuffer(NativeArray vbs, NativeArray rgba; public NativeArray rgb; public UnsafeList> v2fParams; + public NativeArray v2fParamsNames; public Mesh mesh; public GameObject host; @@ -74,6 +75,11 @@ public void Dispose() v2fParams.Dispose(); } + if (v2fParamsNames.IsCreated) + { + v2fParamsNames.Dispose(); + } + if (mesh != null && (mesh.hideFlags & HideFlags.DontSave) != 0) { DestroyUnityObject(mesh); @@ -284,6 +290,13 @@ public override unsafe void AbcSyncDataBegin() split.v2fParams[i] = new NativeArray(0, Allocator.Persistent); } + if (!split.v2fParamsNames.IsCreated) + { + split.v2fParamsNames = + new NativeArray(m_summary.numV2FVertexProperties, + Allocator.Persistent); + } + using (var v2fs = new NativeArray(m_summary.numV2FVertexProperties, Allocator.Temp)) { @@ -298,6 +311,7 @@ public override unsafe void AbcSyncDataBegin() vertexData.v2fProps = v2fs.GetUnsafePtr(); } + // vertexData.v2fPropsNames = split.v2fParamsNames.GetUnsafePtr(); } m_splitData[spi] = vertexData; @@ -468,6 +482,17 @@ public override void AbcSyncDataEnd() else if (split.rgb.Length > 0) split.mesh.SetColors(split.rgb); + if (split.v2fParams.Length > 0) + { + // FixedString128Bytes name = new FixedString128Bytes(); + var customData = split.host.GetOrAddComponent(); + // foreach (var param in split.v2fParamsNames) + { + var name = m_abcSchema.sample.PolyMeshReadPropertyName(0); + Debug.Log(name); + } + } + // update the bounds var data = m_splitData[s]; split.mesh.bounds = new Bounds(data.center, data.extents); diff --git a/com.unity.formats.alembic/Runtime/Scripts/Importer/Behaviours/AlembicCustomData.cs b/com.unity.formats.alembic/Runtime/Scripts/Importer/Behaviours/AlembicCustomData.cs index 0f1a1d619..a2be03d8f 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Importer/Behaviours/AlembicCustomData.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Importer/Behaviours/AlembicCustomData.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using Unity.Collections; namespace UnityEngine.Formats.Alembic.Importer { @@ -15,6 +17,14 @@ public class AlembicCustomData : MonoBehaviour /// public List FaceSetNames => faceSetNames; + public struct V2FAttribute + { + public FixedString128Bytes Name; + public NativeArray Data; + } + + public List VertexAttributes; + internal void SetFacesetNames(List names) { faceSetNames = names; diff --git a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api index b03eda716..f9f3897a8 100644 --- a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api +++ b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api @@ -37,8 +37,14 @@ namespace UnityEngine.Formats.Alembic.Importer public class AlembicCustomData : UnityEngine.MonoBehaviour { + public System.Collections.Generic.List VertexAttributes; public System.Collections.Generic.List FaceSetNames { get; } public AlembicCustomData() {} + public struct V2FAttribute + { + public Unity.Collections.NativeArray Data; + public Unity.Collections.FixedString128Bytes Name; + } } [UnityEngine.ExecuteInEditMode] public class AlembicPointsCloud : UnityEngine.MonoBehaviour From 57a7835e1ef9351ae0f503d76b8f4d520514f276 Mon Sep 17 00:00:00 2001 From: Vlad-Andrei Lazar Date: Thu, 1 Dec 2022 09:39:18 -0500 Subject: [PATCH 3/7] Works but crashes --- .../Assets/AlembicMeshCustomDataMapper.cs | 56 +++++++++++++++++++ .../AlembicMeshCustomDataMapper.cs.meta | 11 ++++ .../Runtime/Scripts/Importer/AlembicMesh.cs | 27 +++------ .../Importer/Behaviours/AlembicCustomData.cs | 25 ++++++++- .../Runtime/Unity.Formats.Alembic.Runtime.api | 1 + 5 files changed, 100 insertions(+), 20 deletions(-) create mode 100644 TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs create mode 100644 TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs.meta diff --git a/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs b/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs new file mode 100644 index 000000000..d9351190a --- /dev/null +++ b/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs @@ -0,0 +1,56 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Formats.Alembic.Importer; + +[ExecuteInEditMode] +public class AlembicMeshCustomDataMapper : MonoBehaviour +{ + AlembicCustomData customData; + + Mesh mesh; + // Start is called before the first frame update + + // Update is called once per frame + void LateUpdate() + { + customData = GetComponent(); + var mf = GetComponent(); + if (mf != null) + { + mesh = mf.sharedMesh; + } + + if (customData == null || mesh == null) + { + return; + } + + // Make sure the Alembic is up to date; + var asp = GetComponentInParent(); + asp.UpdateImmediately(asp.CurrentTime); + + foreach (var attribute in customData.VertexAttributes) + { + + if (attribute.Name == "furUVs") + { + mesh.SetUVs(1, attribute.Data); + } + else if (attribute.Name == "rigUVs") + { + mesh.SetUVs(3, attribute.Data); + } + else if (attribute.Name == "transferUVs") + { + mesh.SetUVs(2, attribute.Data); + } + else + { + Debug.LogWarning($"Unhandled Attribute: {attribute.Name.Value}"); + } + + + } + } +} diff --git a/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs.meta b/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs.meta new file mode 100644 index 000000000..b5e2071fd --- /dev/null +++ b/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e71c42918b3e4a5c88636e40b1f4c56 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs b/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs index 4cae5d2c1..0b8654e6d 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs @@ -37,7 +37,6 @@ internal class Split : IDisposable public NativeArray rgba; public NativeArray rgb; public UnsafeList> v2fParams; - public NativeArray v2fParamsNames; public Mesh mesh; public GameObject host; @@ -75,11 +74,6 @@ public void Dispose() v2fParams.Dispose(); } - if (v2fParamsNames.IsCreated) - { - v2fParamsNames.Dispose(); - } - if (mesh != null && (mesh.hideFlags & HideFlags.DontSave) != 0) { DestroyUnityObject(mesh); @@ -290,13 +284,6 @@ public override unsafe void AbcSyncDataBegin() split.v2fParams[i] = new NativeArray(0, Allocator.Persistent); } - if (!split.v2fParamsNames.IsCreated) - { - split.v2fParamsNames = - new NativeArray(m_summary.numV2FVertexProperties, - Allocator.Persistent); - } - using (var v2fs = new NativeArray(m_summary.numV2FVertexProperties, Allocator.Temp)) { @@ -468,8 +455,8 @@ public override void AbcSyncDataEnd() split.mesh.SetTangents(split.tangents); if (split.uv0.Length > 0) split.mesh.SetUVs(0, split.uv0); - if (split.uv1.Length > 0) - split.mesh.SetUVs(1, split.uv1); + /* if (split.uv1.Length > 0) + split.mesh.SetUVs(1, split.uv1);*/ if (split.velocities.Length > 0) { m_PostProcessJobs[s].Complete(); @@ -484,12 +471,14 @@ public override void AbcSyncDataEnd() if (split.v2fParams.Length > 0) { - // FixedString128Bytes name = new FixedString128Bytes(); var customData = split.host.GetOrAddComponent(); - // foreach (var param in split.v2fParamsNames) + customData.ClearCustomAttributes(); + for (var i=0;i Data; + + public V2FAttribute(FixedString128Bytes name, NativeArray data) + { + Name = name; + Data = new NativeArray(data.Length, Allocator.Persistent); + Data.CopyFrom(data); + } + } + + public List VertexAttributes = new(); + + void OnDisable() + { + ClearCustomAttributes(); } - public List VertexAttributes; + internal void ClearCustomAttributes() + { + foreach (var attribute in VertexAttributes) + { + var v2FAttribute = attribute; + v2FAttribute.Data.DisposeIfPossible(); + } + + VertexAttributes.Clear(); + } internal void SetFacesetNames(List names) { diff --git a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api index f9f3897a8..2268f5925 100644 --- a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api +++ b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api @@ -44,6 +44,7 @@ namespace UnityEngine.Formats.Alembic.Importer { public Unity.Collections.NativeArray Data; public Unity.Collections.FixedString128Bytes Name; + public V2FAttribute(Unity.Collections.FixedString128Bytes name, Unity.Collections.NativeArray data) {} } } From 476631e23312e8e6981c081bc607c1b579c340e3 Mon Sep 17 00:00:00 2001 From: Vlad-Andrei Lazar Date: Thu, 1 Dec 2022 10:55:33 -0500 Subject: [PATCH 4/7] Cleanup and crash fix --- Source/abci/Importer/aiMeshSchema.h | 35 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/Source/abci/Importer/aiMeshSchema.h b/Source/abci/Importer/aiMeshSchema.h index 14fbe2b9d..e1af80c59 100644 --- a/Source/abci/Importer/aiMeshSchema.h +++ b/Source/abci/Importer/aiMeshSchema.h @@ -110,7 +110,6 @@ class aiMeshSample : public aiSample std::vector m_IV2fGeomParam_sp; std::vector m_IV2fGeomParamName; - std::vector> m_IV2fGeomParam_ref; // useless for now std::vector >m_IV2fGeomParam; IArray m_points_ref; @@ -251,6 +250,18 @@ static inline void copy_or_clear(T* dst, const IArray& src, const MeshRefiner } } +template +static inline void copy_or_clear(T* dst, const RawVector& src, const MeshRefiner::Split& split) +{ + if (dst) + { + if (!src.empty()) + memcpy(dst, src.data() + split.vertex_offset, sizeof(T) * split.vertex_count); + else + memset(dst, 0, split.vertex_count * sizeof(T)); + } +} + template static inline void copy_or_clear_3_to_4(T1* dst, const IArray& src, const MeshRefiner::Split& split) { @@ -573,11 +584,6 @@ void aiMeshSchema::readSampleBody(U& sample, uint64_t idx) sample.m_IV2fGeomParam_sp = std::vector(m_IV2fGeomParam.size()); } - if (sample.m_IV2fGeomParam_ref.size() !=m_IV2fGeomParam.size() ) - { - sample.m_IV2fGeomParam_ref = std::vector >(m_IV2fGeomParam.size()); - } - if (sample.m_IV2fGeomParamName.size() !=m_IV2fGeomParam.size() ) { sample.m_IV2fGeomParamName = std::vector(m_IV2fGeomParam.size()); @@ -1033,7 +1039,6 @@ void aiMeshSchema::onTopologyChange(U& sample) for (int i=0;i::fillSplitVertices(int split_index, aiPolyMeshData &data) c copy_or_clear((abcC4*)data.rgba, m_rgba_ref, split); copy_or_clear_3_to_4((abcC4*)data.rgb, m_rgb_ref, split); - for (int i=0;i Date: Mon, 5 Dec 2022 09:41:22 -0500 Subject: [PATCH 5/7] Changelog --- com.unity.formats.alembic/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/com.unity.formats.alembic/CHANGELOG.md b/com.unity.formats.alembic/CHANGELOG.md index d83cc9f76..8bf80e89d 100644 --- a/com.unity.formats.alembic/CHANGELOG.md +++ b/com.unity.formats.alembic/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.4.0-pre.1] - 2022-12-05 +### Added +- Added support for custom Vector2 Mesh vertex attributes. +### Changed +### Fixed + ## [2.3.1] - 2022-12-06 ### Added ### Changed From 399e8e196fa332e9c5a32ebb755ef078edcae5fa Mon Sep 17 00:00:00 2001 From: Vlad-Andrei Lazar Date: Mon, 5 Dec 2022 09:42:34 -0500 Subject: [PATCH 6/7] Default CustomData drawer for prop names. --- .../Editor/Importer/AlembicCustomDataEditor.cs | 14 ++++++++++++++ .../Editor/Unity.Formats.Alembic.Editor.asmdef | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/com.unity.formats.alembic/Editor/Importer/AlembicCustomDataEditor.cs b/com.unity.formats.alembic/Editor/Importer/AlembicCustomDataEditor.cs index 96c1aef28..c23721fcd 100644 --- a/com.unity.formats.alembic/Editor/Importer/AlembicCustomDataEditor.cs +++ b/com.unity.formats.alembic/Editor/Importer/AlembicCustomDataEditor.cs @@ -1,3 +1,4 @@ +using Unity.Collections; using UnityEngine.Formats.Alembic.Importer; namespace UnityEditor.Formats.Alembic.Importer @@ -5,11 +6,24 @@ namespace UnityEditor.Formats.Alembic.Importer [CustomEditor(typeof(AlembicCustomData))] class AlembicCustomDataEditor : Editor { + bool v2fParams; public override void OnInspectorGUI() { using (new EditorGUI.DisabledScope(true)) { base.OnInspectorGUI(); + v2fParams = EditorGUILayout.Foldout(v2fParams, "VertexParams"); + if (v2fParams) + { + using (new EditorGUI.IndentLevelScope()) + { + var customData = target as AlembicCustomData; + foreach (var v2f in customData.VertexAttributes) + { + EditorGUILayout.LabelField(v2f.Name.Value); + } + } + } } } } diff --git a/com.unity.formats.alembic/Editor/Unity.Formats.Alembic.Editor.asmdef b/com.unity.formats.alembic/Editor/Unity.Formats.Alembic.Editor.asmdef index e1448a58d..2bd769578 100644 --- a/com.unity.formats.alembic/Editor/Unity.Formats.Alembic.Editor.asmdef +++ b/com.unity.formats.alembic/Editor/Unity.Formats.Alembic.Editor.asmdef @@ -5,7 +5,8 @@ "Unity.Formats.Alembic.Runtime", "Unity.Timeline", "Unity.Recorder.Editor", - "Unity.Timeline.Editor" + "Unity.Timeline.Editor", + "Unity.Collections" ], "includePlatforms": [ "Editor" @@ -29,4 +30,4 @@ } ], "noEngineReferences": false -} +} \ No newline at end of file From 9199246aaf103bfd6b16844beaad2a1c173c598f Mon Sep 17 00:00:00 2001 From: "noreply@unity3d.com" Date: Mon, 5 Dec 2022 14:47:47 +0000 Subject: [PATCH 7/7] Apply formatting changes --- Source/abci/Importer/AlembicImporter.h | 4 +--- Source/abci/Importer/aiMeshSchema.cpp | 2 +- Source/abci/Importer/aiMeshSchema.h | 23 +++++++++---------- .../Runtime/Scripts/Importer/AbcAPI.cs | 2 +- .../Runtime/Scripts/Importer/AlembicMesh.cs | 8 +++---- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/Source/abci/Importer/AlembicImporter.h b/Source/abci/Importer/AlembicImporter.h index f48bd06d2..e1fbb919d 100644 --- a/Source/abci/Importer/AlembicImporter.h +++ b/Source/abci/Importer/AlembicImporter.h @@ -192,7 +192,7 @@ struct aiPolyMeshData abcV4 *rgba = nullptr; abcV4 *rgb = nullptr; abcV2 **v2fParams = nullptr; - // FixedString128* v2fParamNames = nullptr; + // FixedString128* v2fParamNames = nullptr; int *indices = nullptr; int vertex_count = 0; @@ -350,5 +350,3 @@ abciAPI void aiPointsFillData(aiPointsSample* sample, aiPointsData *d abciAPI const char* aiPropertyGetName(aiProperty* prop); abciAPI aiPropertyType aiPropertyGetType(aiProperty* prop); abciAPI void aiPropertyCopyData(aiProperty* prop, const abcSampleSelector *ss, aiPropertyData *dst); - - diff --git a/Source/abci/Importer/aiMeshSchema.cpp b/Source/abci/Importer/aiMeshSchema.cpp index 9a736ce2c..a5d874bd8 100644 --- a/Source/abci/Importer/aiMeshSchema.cpp +++ b/Source/abci/Importer/aiMeshSchema.cpp @@ -7,7 +7,7 @@ #include "aiMeshSchema.h" #include "aiSubD.h" - constexpr size_t FixedString128::MaxLength; +constexpr size_t FixedString128::MaxLength; aiMeshTopology::aiMeshTopology() { diff --git a/Source/abci/Importer/aiMeshSchema.h b/Source/abci/Importer/aiMeshSchema.h index e1af80c59..3e71f81fa 100644 --- a/Source/abci/Importer/aiMeshSchema.h +++ b/Source/abci/Importer/aiMeshSchema.h @@ -74,7 +74,7 @@ class aiMeshTopology RawVector m_remap_rgba; RawVector m_remap_rgb; - std::vector> m_remap_m_IV2fGeomParam; + std::vector > m_remap_m_IV2fGeomParam; int m_vertex_count = 0; int m_index_count = 0; // triangulated @@ -110,7 +110,7 @@ class aiMeshSample : public aiSample std::vector m_IV2fGeomParam_sp; std::vector m_IV2fGeomParamName; - std::vector >m_IV2fGeomParam; + std::vector > m_IV2fGeomParam; IArray m_points_ref; IArray m_velocities_ref; @@ -579,24 +579,23 @@ void aiMeshSchema::readSampleBody(U& sample, uint64_t idx) } } - if (sample.m_IV2fGeomParam_sp.size() !=m_IV2fGeomParam.size() ) + if (sample.m_IV2fGeomParam_sp.size() != m_IV2fGeomParam.size()) { sample.m_IV2fGeomParam_sp = std::vector(m_IV2fGeomParam.size()); } - if (sample.m_IV2fGeomParamName.size() !=m_IV2fGeomParam.size() ) + if (sample.m_IV2fGeomParamName.size() != m_IV2fGeomParam.size()) { sample.m_IV2fGeomParamName = std::vector(m_IV2fGeomParam.size()); } - for (int i=0;im_schema.getSelfBoundsProperty(); @@ -1029,15 +1028,15 @@ void aiMeshSchema::onTopologyChange(U& sample) /// Arbitrary V2f attributes if (sample.m_IV2fGeomParam.size() != sample.m_IV2fGeomParam_sp.size()) { - sample.m_IV2fGeomParam = std::vector>(sample.m_IV2fGeomParam_sp.size()); + sample.m_IV2fGeomParam = std::vector >(sample.m_IV2fGeomParam_sp.size()); } if (topology.m_remap_m_IV2fGeomParam.size() != sample.m_IV2fGeomParam_sp.size()) { - topology.m_remap_m_IV2fGeomParam = std::vector>(sample.m_IV2fGeomParam_sp.size()); + topology.m_remap_m_IV2fGeomParam = std::vector >(sample.m_IV2fGeomParam_sp.size()); } - for (int i=0;i::onTopologyChange(U& sample) if (sp.isIndexed() && sp.getIndices()->size() == refiner.indices.size()) { - IArray indices{(int *) sp.getIndices()->get(), sp.getIndices()->size()}; + IArray indices{(int *)sp.getIndices()->get(), sp.getIndices()->size()}; refiner.template addIndexedAttribute(src, indices, dst, topology.m_remap_m_IV2fGeomParam[i]); } else if (src.size() == refiner.indices.size()) @@ -1316,4 +1315,4 @@ template char* aiMeshSample::readPropertyName(int idx) { return &(m_IV2fGeomParamName[idx].String[0]); -} \ No newline at end of file +} diff --git a/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs b/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs index 25ff0e904..99d7a802a 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs @@ -204,7 +204,7 @@ unsafe struct aiPolyMeshData public void* rgba; public void* rgb; public void* v2fProps; - // public void* v2fPropsNames; + // public void* v2fPropsNames; public IntPtr indices; diff --git a/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs b/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs index 0b8654e6d..733585138 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Importer/AlembicMesh.cs @@ -298,7 +298,7 @@ public override unsafe void AbcSyncDataBegin() vertexData.v2fProps = v2fs.GetUnsafePtr(); } - // vertexData.v2fPropsNames = split.v2fParamsNames.GetUnsafePtr(); + // vertexData.v2fPropsNames = split.v2fParamsNames.GetUnsafePtr(); } m_splitData[spi] = vertexData; @@ -455,8 +455,8 @@ public override void AbcSyncDataEnd() split.mesh.SetTangents(split.tangents); if (split.uv0.Length > 0) split.mesh.SetUVs(0, split.uv0); - /* if (split.uv1.Length > 0) - split.mesh.SetUVs(1, split.uv1);*/ + /* if (split.uv1.Length > 0) + split.mesh.SetUVs(1, split.uv1);*/ if (split.velocities.Length > 0) { m_PostProcessJobs[s].Complete(); @@ -473,7 +473,7 @@ public override void AbcSyncDataEnd() { var customData = split.host.GetOrAddComponent(); customData.ClearCustomAttributes(); - for (var i=0;i