I have a scene which re-uses the same texture file for multiple meshes in the scene. I create only 1 instance of the texture, and point multiple nodes / meshes at it; but the more instances of the texture I apply, the (linearly) bigger the file gets. Is there a way to signal to Aspose that you want the same texture instance to be re-used between nodes so that the GLB only contains 1 instance of the texture data?
Would you kindly share your sample source file(s) along with complete sample code snippet. We will test the scenario in our environment and address it accordingly.
Here is the code that verifies that multiple uses of the same texture leads to multiple copies of that texture emitted in a GLB. It creates 2 scenes in parallel, adding an identical mesh to each scene 4 times, and saving the intermediary results. The second scene gets the same texture/material applied to each node, and shows how every time I add a mesh which references the same material, that material’s texture gets duplicated in the resulting file.
using System;
using Aspose.ThreeD;
using Aspose.ThreeD.Utilities;
using Aspose.ThreeD.Entities;
using System.Drawing;
using Aspose.ThreeD.Shading;
using System.IO;
namespace Aspose3dTest
{
class Program
{
static void Main(string[] args)
{
//Console.WriteLine("Setting license");
Aspose.ThreeD.License license = new Aspose.ThreeD.License();
license.SetLicense("Aspose.3D.lic");
System.Reflection.Assembly asm = System.Reflection.Assembly.GetAssembly(typeof(Aspose.ThreeD.Scene));
Console.WriteLine("Aspose.3d Version: " + asm.FullName);
asm = System.Reflection.Assembly.GetAssembly(typeof(System.Int32));
Console.WriteLine(".Net Core Version: " + asm.FullName);
//create the texture image
int textureSize = 500;
System.Drawing.Bitmap textureBitmap = new Bitmap(textureSize, textureSize);
Random rnd = new Random();
for (int x = 0; x < textureSize; x++)
for (int y = 0; y < textureSize; y++)
textureBitmap.SetPixel(x, y, Color.FromArgb(rnd.Next()));
byte[] textureData = default(byte[]);
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
textureBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
textureData = ms.ToArray();
}
System.IO.File.WriteAllBytes("TheTexture.jpg", textureData);
int textureFileSize = (int)new FileInfo("TheTexture.jpg").Length;
Console.WriteLine($"Size of texture in bytes: {textureFileSize}");
var texture = new Texture("TheTexture")
{
Content = textureData,
FileName = "TheTexture.jpg"
};
Scene sceneNoTexture = new Scene();
Scene sceneWithTexture = new Scene();
var GLTFSaveOptions = new Aspose.ThreeD.Formats.GLTFSaveOptions(Aspose.ThreeD.FileContentType.Binary)
{
EmbedAssets = true,
SaveExtras = true
};
var material = new Aspose.ThreeD.Shading.PbrMaterial(System.Drawing.Color.White);
material.SetTexture(Aspose.ThreeD.Shading.Material.MapDiffuse, texture);
Console.WriteLine("Meshes\t!Text\tText\tDelta\tImageCopiesInFile");
for (int meshCount = 1; meshCount < 5; meshCount++)
{
Console.Write($"{meshCount}\t");
Vector3 randomTranslation = new Vector3(rnd.NextDouble() * 20, rnd.NextDouble() * 20, rnd.NextDouble() * 20);
var node = sceneNoTexture.RootNode.CreateChildNode(meshCount.ToString());
node.Transform.Translation = randomTranslation;
node.Entity = MakeBoxMesh();
var noTextureFileName = $"noTexture{meshCount}.glb";
sceneNoTexture.Save(noTextureFileName, GLTFSaveOptions);
int noTextureSize = (int)new FileInfo(noTextureFileName).Length;
Console.Write($"{noTextureSize}\t");
node = sceneWithTexture.RootNode.CreateChildNode(meshCount.ToString());
node.Transform.Translation = randomTranslation;
node.Entity = MakeBoxMesh();
node.Material = material;
var withTextureFileName = $"withTexture{meshCount}.glb";
sceneWithTexture.Save(withTextureFileName, GLTFSaveOptions);
int withTextureSize = (int)new FileInfo(withTextureFileName).Length;
Console.Write($"{withTextureSize}\t");
int delta = withTextureSize - noTextureSize;
int imageCopiesInFile = delta / textureFileSize;
Console.WriteLine($"{delta}\t{imageCopiesInFile}");
}
}
private static Mesh MakeBoxMesh()
{
var box = new Mesh();
var controlPoints = box.ControlPoints;
controlPoints.Add(new Vector4(-5.0, 0.0, 5.0, 1.0));
controlPoints.Add(new Vector4(5.0, 0.0, 5.0, 1.0));
controlPoints.Add(new Vector4(5.0, 10.0, 5.0, 1.0));
controlPoints.Add(new Vector4(-5.0, 10.0, 5.0, 1.0));
controlPoints.Add(new Vector4(-5.0, 0.0, -5.0, 1.0));
controlPoints.Add(new Vector4(5.0, 0.0, -5.0, 1.0));
controlPoints.Add(new Vector4(5.0, 10.0, -5.0, 1.0));
controlPoints.Add(new Vector4(-5.0, 10.0, -5.0, 1.0));
box.CreatePolygon(0, 1, 2, 3);
box.CreatePolygon(1, 5, 6, 2);
box.CreatePolygon(5, 4, 7, 6);
box.CreatePolygon(4, 0, 3, 7);
box.CreatePolygon(0, 4, 5, 1);
box.CreatePolygon(3, 2, 6, 7);
box.VertexElements.Add(PolygonModifier.GenerateNormal(box));
box.VertexElements.Add(PolygonModifier.GenerateUV(box));
return box;
}
}
}
And here is the output:
Aspose.3d Version: Aspose.3D, Version=20.6.0.0, Culture=neutral, PublicKeyToken=f071c641d0b4582b
.Net Core Version: System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
Size of texture in bytes: 152943
Meshes !Text Text Delta ImageCopiesInFile
1 2116 155588 153472 1
2 3936 310824 306888 2
3 5756 466056 460300 3
4 7580 621296 613716 4
We have logged an investigation ticket as THREEDNET-810 in our issue tracking system for the sake of further analysis. We will look into its details and keep you posted with the status of ticket resolution. Please be patient and give us some time.
We are sorry for the inconvenience.
@OBCad
We would like to share with you that the issue has been resolved in Aspose.3D for .NET 21.1.1 hotfix.
Great, thanks so much! I just verified that the hotfix does work. Is there a way to access this hotfix via nuget? If not, when will it be rolled into the next nuget package?
Thanks for your feedback.
The hotfix is not uploaded over NuGet however, this fix will be a part of 21.2v of the API which will be released next month (Feb 2021).