diff --git a/src/SharpGLTF.Core/Schema2/gltf.Buffer.cs b/src/SharpGLTF.Core/Schema2/gltf.Buffer.cs index 417cd2ef..df4d0946 100644 --- a/src/SharpGLTF.Core/Schema2/gltf.Buffer.cs +++ b/src/SharpGLTF.Core/Schema2/gltf.Buffer.cs @@ -220,7 +220,8 @@ public void MergeBuffers() // begin merge - var sbbuilder = new _StaticBufferBuilder(0); + var reservedMemory = (int) (totalLen * 1.01); // increase by 1% + var sbbuilder = new _StaticBufferBuilder(0, reservedMemory); foreach (var bv in views) bv._IsolateBufferMemory(sbbuilder); diff --git a/src/SharpGLTF.Core/Schema2/gltf.BufferView.cs b/src/SharpGLTF.Core/Schema2/gltf.BufferView.cs index d09f86da..db3d1f55 100644 --- a/src/SharpGLTF.Core/Schema2/gltf.BufferView.cs +++ b/src/SharpGLTF.Core/Schema2/gltf.BufferView.cs @@ -347,9 +347,10 @@ sealed class _StaticBufferBuilder { #region lifecycle - public _StaticBufferBuilder(int bufferIndex) + public _StaticBufferBuilder(int bufferIndex, int initialCapacity = 0) { _BufferIndex = bufferIndex; + _Data = new List(initialCapacity); } #endregion @@ -360,7 +361,7 @@ public _StaticBufferBuilder(int bufferIndex) private readonly int _BufferIndex; // accumulated data - private readonly List _Data = new List(); + private readonly List _Data; #endregion diff --git a/tests/SharpGLTF.ThirdParty.Tests/MeltyPlayerTests.cs b/tests/SharpGLTF.ThirdParty.Tests/MeltyPlayerTests.cs index 67992dfa..15df3714 100644 --- a/tests/SharpGLTF.ThirdParty.Tests/MeltyPlayerTests.cs +++ b/tests/SharpGLTF.ThirdParty.Tests/MeltyPlayerTests.cs @@ -1,13 +1,18 @@ using System; -using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; using System.Linq; using System.Numerics; -using System.Text; -using System.Threading.Tasks; using NUnit.Framework; - +using SharpGLTF.Geometry; +using SharpGLTF.Geometry.VertexTypes; +using SharpGLTF.Materials; +using SharpGLTF.Memory; +using SharpGLTF.Scenes; using SharpGLTF.Schema2; +using SharpGLTF.Transforms; namespace SharpGLTF.ThirdParty { @@ -76,5 +81,97 @@ void addNodeMesh(string name, Matrix4x4 xform) Assert.AreEqual(4, satellites.Length); } + + [Test] + public void TestHugeSceneViaBuilders() + { + // create a scene + + var mesh = new MeshBuilder(); + + var gridSize = 1000; + + // generate texture + var diffuseImageSize = 2 * gridSize; + var occlusionImageSize = gridSize; + + MemoryImage diffuseImage, occlusionImage; + { + var img = new Bitmap(diffuseImageSize, diffuseImageSize, PixelFormat.Format32bppArgb); + + using var mem = new MemoryStream(); + img.Save(mem, ImageFormat.Png); + + mem.TryGetBuffer(out var bytes); + diffuseImage = new MemoryImage(bytes); + } + { + var img = new Bitmap(occlusionImageSize, occlusionImageSize, PixelFormat.Format32bppArgb); + + using var mem = new MemoryStream(); + img.Save(mem, ImageFormat.Png); + + mem.TryGetBuffer(out var bytes); + occlusionImage = new MemoryImage(bytes); + } + + var material = MaterialBuilder.CreateDefault().WithSpecularGlossinessShader(); + material.UseChannel(KnownChannel.Diffuse) + .UseTexture() + .WithPrimaryImage(ImageBuilder.From(diffuseImage)) + .WithCoordinateSet(0); + material.UseChannel(KnownChannel.Occlusion) + .UseTexture() + .WithPrimaryImage(ImageBuilder.From(occlusionImage)) + .WithCoordinateSet(0); + + // generate heightmap + + for (var y = 0; y < gridSize; ++y) { + for (var x = 0; x < gridSize; ++x) { + var vertices = new (float X, float Y)[] + { + (x, y), + (x + 1, y), + (x, y + 1), + (x + 1, y + 1) + }.Select(pos => VertexBuilder + .Create(new Vector3(pos.X, pos.Y, 0), new Vector3(x, y, 0)) + .WithMaterial(new Vector4(pos.X / gridSize, pos.Y / gridSize, 0, 1), + new Vector4(0, pos.X / gridSize, pos.Y / gridSize, 1), + new Vector2(pos.X / gridSize, pos.Y / gridSize), + new Vector2(pos.X / gridSize, pos.Y / gridSize)) + .WithSkinning(SparseWeight8.Create((0, 1)))) + .ToArray(); + + mesh.UsePrimitive(material).AddTriangle(vertices[0], vertices[1], vertices[2]); + mesh.UsePrimitive(material).AddTriangle(vertices[1], vertices[2], vertices[3]); + } + } + + var scene = new SceneBuilder(); + scene.AddSkinnedMesh(mesh, Matrix4x4.Identity, new NodeBuilder()); + + // convert to gltf + + var gltf = scene.ToGltf2(); + + Assert.AreEqual(1, gltf.LogicalMeshes.Count); + + var outFiles = new[] + { + "huge_scene.glb", + "huge_scene.gltf", + "huge_scene.obj", + }; + + foreach (var outFile in outFiles) { + gltf.AttachToCurrentTest(outFile); + + GC.WaitForPendingFinalizers(); + GC.Collect(); + GC.WaitForFullGCComplete(); + } + } } } diff --git a/tests/SharpGLTF.ThirdParty.Tests/SharpGLTF.ThirdParty.Tests.csproj b/tests/SharpGLTF.ThirdParty.Tests/SharpGLTF.ThirdParty.Tests.csproj index 0e73bfd5..b584e09d 100644 --- a/tests/SharpGLTF.ThirdParty.Tests/SharpGLTF.ThirdParty.Tests.csproj +++ b/tests/SharpGLTF.ThirdParty.Tests/SharpGLTF.ThirdParty.Tests.csproj @@ -18,7 +18,8 @@ - + +