diff --git a/Assets/vfx-graph-gs/SplatData.cs b/Assets/vfx-graph-gs/SplatData.cs index 01f0494..305e96c 100644 --- a/Assets/vfx-graph-gs/SplatData.cs +++ b/Assets/vfx-graph-gs/SplatData.cs @@ -10,16 +10,22 @@ public sealed class SplatData : ScriptableObject public int SplatCount => PositionArray.Length; public GraphicsBuffer PositionBuffer => GetCachedBuffers().position; - public GraphicsBuffer AxisBuffer => GetCachedBuffers().axis; + public GraphicsBuffer ScaleBuffer => GetCachedBuffers().scale; + public GraphicsBuffer RotationBuffer => GetCachedBuffers().rotation; public GraphicsBuffer ColorBuffer => GetCachedBuffers().color; + public GraphicsBuffer OpacityBuffer => GetCachedBuffers().opacity; + public GraphicsBuffer SHBuffer => GetCachedBuffers().sh; #endregion #region Serialized data [field:SerializeField] public Vector3[] PositionArray { get; set; } - [field:SerializeField] public Vector3[] AxisArray { get; set; } + [field:SerializeField] public Vector3[] ScaleArray { get; set; } + [field:SerializeField] public Quaternion[] RotationArray { get; set; } [field:SerializeField] public Color[] ColorArray { get; set; } + [field:SerializeField] public float[] OpacityArray { get; set; } + [field:SerializeField] public float[][] SHArray { get; set; } #endregion @@ -28,32 +34,43 @@ public sealed class SplatData : ScriptableObject public void ReleaseGpuResources() { _cachedBuffers.position?.Release(); - _cachedBuffers.axis?.Release(); + _cachedBuffers.scale?.Release(); + _cachedBuffers.rotation?.Release(); _cachedBuffers.color?.Release(); - _cachedBuffers = (null, null, null); + _cachedBuffers.opacity?.Release(); + _cachedBuffers = (null, null, null, null, null, null); } #endregion #region GPU resource management - (GraphicsBuffer position, GraphicsBuffer axis, GraphicsBuffer color) + (GraphicsBuffer position, GraphicsBuffer scale, GraphicsBuffer rotation, + GraphicsBuffer color, GraphicsBuffer opacity, GraphicsBuffer sh) _cachedBuffers; static unsafe GraphicsBuffer NewBuffer(int count) where T : unmanaged => new GraphicsBuffer(GraphicsBuffer.Target.Structured, count, sizeof(T)); - (GraphicsBuffer position, GraphicsBuffer axis, GraphicsBuffer color) + (GraphicsBuffer position, GraphicsBuffer scale, GraphicsBuffer rotation, + GraphicsBuffer color, GraphicsBuffer opacity, GraphicsBuffer sh) GetCachedBuffers() { if (_cachedBuffers.position == null) { _cachedBuffers.position = NewBuffer(SplatCount); - _cachedBuffers.axis = NewBuffer(SplatCount * 3); + _cachedBuffers.scale = NewBuffer(SplatCount); + _cachedBuffers.rotation = NewBuffer(SplatCount); _cachedBuffers.color = NewBuffer(SplatCount); + _cachedBuffers.opacity = NewBuffer(SplatCount); + _cachedBuffers.sh = NewBuffer(SplatCount * 45); + _cachedBuffers.position.SetData(PositionArray); - _cachedBuffers.axis.SetData(AxisArray); + _cachedBuffers.scale.SetData(ScaleArray); + _cachedBuffers.rotation.SetData(RotationArray); _cachedBuffers.color.SetData(ColorArray); + _cachedBuffers.opacity.SetData(OpacityArray); + _cachedBuffers.sh.SetData(SHArray); } return _cachedBuffers; } @@ -67,4 +84,4 @@ public sealed class SplatData : ScriptableObject #endregion } -} // namespace SplatVfx +} diff --git a/Assets/vfx-graph-gs/SplatDataBinder.cs b/Assets/vfx-graph-gs/SplatDataBinder.cs.0 similarity index 100% rename from Assets/vfx-graph-gs/SplatDataBinder.cs rename to Assets/vfx-graph-gs/SplatDataBinder.cs.0 diff --git a/Assets/vfx-graph-gs/SplatDataBinder.cs.meta b/Assets/vfx-graph-gs/SplatDataBinder.cs.0.meta similarity index 100% rename from Assets/vfx-graph-gs/SplatDataBinder.cs.meta rename to Assets/vfx-graph-gs/SplatDataBinder.cs.0.meta diff --git a/Assets/vfx-graph-gs/SplatImporter.cs b/Assets/vfx-graph-gs/SplatImporter.cs index e10ce88..598406d 100644 --- a/Assets/vfx-graph-gs/SplatImporter.cs +++ b/Assets/vfx-graph-gs/SplatImporter.cs @@ -9,112 +9,148 @@ using UnityEditor.Experimental; using System; using System.IO; using System.Runtime.InteropServices; +using System.Text; +using UnityEditor.Rendering.LookDev; +using System.Linq; namespace SplatVfx.Editor { -[ScriptedImporter(1, "splat"), BurstCompile] +[ScriptedImporter(1, "ply"), BurstCompile] public sealed class SplatImporter : ScriptedImporter { #region ScriptedImporter implementation public override void OnImportAsset(AssetImportContext context) { - var data = ImportAsSplatData(context.assetPath); - var prefab = CreatePrefab(data); - context.AddObjectToAsset("prefab", prefab); - context.AddObjectToAsset("data", data); - context.SetMainObject(prefab); + _ = ParsePLYFile(context.assetPath); + // var data = ImportAsSplatData(context.assetPath); + // var prefab = CreatePrefab(data); + // context.AddObjectToAsset("prefab", prefab); + // context.AddObjectToAsset("data", data); + // context.SetMainObject(prefab); } #endregion #region Prefab construction - const string DefaultVfxPath = "Packages/jp.keijiro.splat-vfx/VFX/Splat.vfx"; + // const string DefaultVfxPath = "Packages/jp.keijiro.splat-vfx/VFX/Splat.vfx"; - GameObject CreatePrefab(SplatData data) - { - var go = new GameObject(); + // GameObject CreatePrefab(SplatData data) + // { + // var go = new GameObject(); - var vfx = go.AddComponent(); - vfx.visualEffectAsset = EditorResources.Load(DefaultVfxPath); + // var vfx = go.AddComponent(); + // vfx.visualEffectAsset = EditorResources.Load(DefaultVfxPath); - var binderBase = go.AddComponent(); - var binder = binderBase.AddPropertyBinder(); - binder.SplatData = data; + // var binderBase = go.AddComponent(); + // var binder = binderBase.AddPropertyBinder(); + // binder.SplatData = data; - return go; - } + // return go; + // } #endregion #region Reader implementation - SplatData ImportAsSplatData(string path) + (string header, byte[] binaryData) ParsePLYFile(string filePath) { - var data = ScriptableObject.CreateInstance(); - data.name = Path.GetFileNameWithoutExtension(path); + using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + using (var reader = new StreamReader(fileStream)) + { + StringBuilder headerBuilder = new StringBuilder(); + string line; - var arrays = LoadDataArrays(path); - data.PositionArray = arrays.position; - data.AxisArray = arrays.axis; - data.ColorArray = arrays.color; - data.ReleaseGpuResources(); + while ((line = reader.ReadLine()) != null) + { + headerBuilder.AppendLine(line); + if (line.Trim() == "end_header") + { + break; + } + } - return data; + long endHeaderPosition = headerBuilder.Length - headerBuilder.ToString().Split('\n').Length + 1; + fileStream.Seek(endHeaderPosition, SeekOrigin.Begin); + + byte[] binaryData = new byte[fileStream.Length - endHeaderPosition]; + + return (headerBuilder.ToString(), binaryData); + } } - #pragma warning disable CS0649 + /* + get number of elements - struct ReadData - { - public float px, py, pz; - public float sx, sy, sz; - public byte r, g, b, a; - public byte rw, rx, ry, rz; - } + run down header, building list of data mappings + + for element + for data mapping + write data + */ - #pragma warning restore CS0649 + // SplatData ImportAsSplatData(string path) + // { + // var data = ScriptableObject.CreateInstance(); + // data.name = Path.GetFileNameWithoutExtension(path); - (Vector3[] position, Vector3[] axis, Color[] color) - LoadDataArrays(string path) - { - var bytes = (Span)File.ReadAllBytes(path); - var count = bytes.Length / 32; + // var arrays = LoadDataArrays(path); + // data.PositionArray = arrays.position; + // data.AxisArray = arrays.axis; + // data.ColorArray = arrays.color; + // data.ReleaseGpuResources(); - var source = MemoryMarshal.Cast(bytes); + // return data; + // } - var position = new Vector3[count]; - var axis = new Vector3[count * 3]; - var color = new Color[count]; + // struct ReadData + // { + // public float px, py, pz; + // public float sx, sy, sz; + // public byte r, g, b, a; + // public byte rw, rx, ry, rz; + // } - for (var i = 0; i < count; i++) - ParseReadData(source[i], - out position[i], - out axis[i * 3], - out axis[i * 3 + 1], - out axis[i * 3 + 2], - out color[i]); + // (Vector3[] position, Vector3[] axis, Color[] color) + // LoadDataArrays(string path) + // { + // var bytes = (Span)File.ReadAllBytes(path); + // var count = bytes.Length / 32; - return (position, axis, color); - } + // var source = MemoryMarshal.Cast(bytes); - [BurstCompile] - void ParseReadData(in ReadData src, - out Vector3 position, - out Vector3 axis1, - out Vector3 axis2, - out Vector3 axis3, - out Color color) - { - var rv = (math.float4(src.rx, src.ry, src.rz, src.rw) - 128) / 128; - var q = math.quaternion(-rv.x, -rv.y, rv.z, rv.w); - position = math.float3(src.px, src.py, -src.pz); - axis1 = math.mul(q, math.float3(src.sx, 0, 0)); - axis2 = math.mul(q, math.float3(0, src.sy, 0)); - axis3 = math.mul(q, math.float3(0, 0, src.sz)); - color = (Vector4)math.float4(src.r, src.g, src.b, src.a) / 255; - } + // var position = new Vector3[count]; + // var axis = new Vector3[count * 3]; + // var color = new Color[count]; + + // for (var i = 0; i < count; i++) + // ParseReadData(source[i], + // out position[i], + // out axis[i * 3], + // out axis[i * 3 + 1], + // out axis[i * 3 + 2], + // out color[i]); + + // return (position, axis, color); + // } + + // [BurstCompile] + // void ParseReadData(in ReadData src, + // out Vector3 position, + // out Vector3 axis1, + // out Vector3 axis2, + // out Vector3 axis3, + // out Color color) + // { + // var rv = (math.float4(src.rx, src.ry, src.rz, src.rw) - 128) / 128; + // var q = math.quaternion(-rv.x, -rv.y, rv.z, rv.w); + // position = math.float3(src.px, src.py, -src.pz); + // axis1 = math.mul(q, math.float3(src.sx, 0, 0)); + // axis2 = math.mul(q, math.float3(0, src.sy, 0)); + // axis3 = math.mul(q, math.float3(0, 0, src.sz)); + // color = (Vector4)math.float4(src.r, src.g, src.b, src.a) / 255; + // } #endregion }