FBX Format - Scene.Save - 18.9.0 UnitScaleFactor Regression

Hi

I’ve noticed scene.AssetInfo.UnitScaleFactor no longer works in 18.9.0. When saving to FBX Ascii the FBX Property value is always 1. For an fbx file this results in 1 unit being 1 centimeter.

In 18.8.0 the behaviour was working as expected and by default the fbx property had a value of 100 saved in the file (100 = 100cm = 1 meter). This value was correctly changing when you adjusted scene.AssetInfo.UnitScaleFactor.

For example, if I want to work in millimeters within the Aspose.3D API, I would do this:

scene.AssetInfo.UnitScaleFactor = 0.001;

In 18.8.0 the FBX "UnitScaleFactor " property results in 0.1, which is correct.
In 18.9.0 the property is always 1.

Documentation:

Public property UnitName Gets or sets the unit of length used in this asset. e.g. cm/m/km/inch/feet
Public property UnitScaleFactor Gets or sets the scale factor to real-world meter.

Unit Tests:

    [ TestFixture ]
    public class SceneFileScaleTests
    {
        [ Test ]
        public void Aspose_Scene_MetersFileScale()
        {
            Scene scene = CreateSampleScene();

            scene.AssetInfo.UnitName = "m";
            scene.AssetInfo.UnitScaleFactor = 1;

            double fileScale = GetSavedFileScale( scene );

            // 1 meter should return 100 file scale 
            Assert.AreEqual(100, fileScale);
        }

        [ Test ]
        public void Aspose_Scene_MillimetersFileScale()
        {
            Scene scene = CreateSampleScene();

            scene.AssetInfo.UnitName = "mm";
            scene.AssetInfo.UnitScaleFactor = 0.001;

            double fileScale = GetSavedFileScale( scene );

            Assert.AreEqual(0.1, fileScale);
        }


        [Test]
        public void Aspose_Scene_InchesFileScale()
        {
            Scene scene = CreateSampleScene();

            scene.AssetInfo.UnitName = "inch";
            scene.AssetInfo.UnitScaleFactor = 0.0254;

            double fileScale = GetSavedFileScale(scene);

            Assert.AreEqual(2.54, fileScale);
        }

        /// <summary>
        /// Creates a sample scene with a 1x1x1 cube.
        /// </summary>
        private static Scene CreateSampleScene()
        {
            Scene scene = new Scene();

            var cubeNode = scene.RootNode.CreateChildNode( "Cube" );
            cubeNode.AddEntity( new Box( 1, 1, 1 ).ToMesh() );

            return scene;
        }

        /// <summary>
        /// Saves the and return the line that contains the "UnitScaleFactor" property when saved
        /// as an ASCII FBX.
        /// </summary>
        /// <param name="scene">The scene.</param>
        /// <exception cref="Exception">Failed to locate UnitScaleFactor</exception>
        private static string SaveAndReturnFileScaleLine( Scene scene )
        {
            byte[] bytes;

            using ( var saveStream = new MemoryStream() )
            {
                scene.Save( saveStream, FileFormat.FBX7500ASCII );
                bytes = saveStream.GetBuffer();
            }

            string unitScaleFactorLine = string.Empty;

            // Read saved bytes as text
            using ( var ms = new MemoryStream( bytes ) )
            using ( var sr = new StreamReader( ms ) )
            {
                while ( !sr.EndOfStream )
                {
                    string line = sr.ReadLine();

                    if ( line == null )
                        break;

                    if ( line.Contains( "\"UnitScaleFactor\"" ) )
                    {
                        unitScaleFactorLine = line;
                        break;
                    }
                }
            }

            if ( string.IsNullOrEmpty( unitScaleFactorLine ) )
                throw new Exception( "Failed to locate UnitScaleFactor" );

            return unitScaleFactorLine;
        }

        private static double GetSavedFileScale( Scene scene )
        {
            var line = SaveAndReturnFileScaleLine( scene );

            // Example line:
            // 		P: "UnitScaleFactor", "double", "Number", "",100
            // Index of 4
            string fileScaleValue = line.Split( ',' )[4];

            Debug.WriteLine($"Scene UnitScaleFactor: {scene.AssetInfo.UnitScaleFactor}");
            Debug.WriteLine("FBX Property Line: " + SaveAndReturnFileScaleLine(scene) );

            return double.Parse( fileScaleValue );
        }
    }

The above code passes in 18.8.0 but fails in 18.9.0.

From my understanding UnitName doesn’t matter which is fine, however UnitScaleFactor in 18.9.0 now makes it impossible to correct the units, and we are stuck in centimeters.

https://help.autodesk.com/view/FBX/2019/ENU/?guid=FBX_Developer_Help_cpp_ref_class_fbx_system_unit_html

18.9.0 Output

Scene UnitScaleFactor: 0.0254
FBX Property Line: 		P: "UnitScaleFactor", "double", "Number", "",1
Exception thrown: 'NUnit.Framework.AssertionException' in nunit.framework.dll
An exception of type 'NUnit.Framework.AssertionException' occurred in nunit.framework.dll but was not handled in user code
  Expected: 2.54d
  But was:  1.0d

'JetBrains.ReSharper.TaskRunner.CLR45.x64.exe' (CLR v4.0.30319: domain-): Loaded 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\Remote Debugger\x64\Runtime\Microsoft.VisualStudio.Debugger.Runtime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Scene UnitScaleFactor: 1
FBX Property Line: 		P: "UnitScaleFactor", "double", "Number", "",1
Exception thrown: 'NUnit.Framework.AssertionException' in nunit.framework.dll
An exception of type 'NUnit.Framework.AssertionException' occurred in nunit.framework.dll but was not handled in user code
  Expected: 100
  But was:  1.0d

Scene UnitScaleFactor: 0.001
FBX Property Line: 		P: "UnitScaleFactor", "double", "Number", "",1
Exception thrown: 'NUnit.Framework.AssertionException' in nunit.framework.dll
An exception of type 'NUnit.Framework.AssertionException' occurred in nunit.framework.dll but was not handled in user code
  Expected: 0.10000000000000001d
  But was:  1.0d

18.8.0 Output

Scene UnitScaleFactor: 0.0254
FBX Property Line: 		P: "UnitScaleFactor", "double", "Number", "",2.54
Scene UnitScaleFactor: 1
FBX Property Line: 		P: "UnitScaleFactor", "double", "Number", "",100
Scene UnitScaleFactor: 0.001
FBX Property Line: 		P: "UnitScaleFactor", "double", "Number", "",0.1

I have created a project with unit tests that pass in 18.8.0 and fail in 18.9.0

The issue also exists when opening a file - the “UnitScaleFactor” never changes from 1.

I believe the tests clearly show that 18.9.0 is not working as expected and that 18.8.0 has “UnitScaleFactor” working as intended
AsposeThreeDTests.zip (18.4 KB)

@bortos

Thank you for contacting support.

We have logged a ticket with ID THREEDNET-429 in our issue management system for further investigation and resolution. The ticket ID has been linked with this thread so that you will receive notification as soon as the ticket is resolved.

We are sorry for the inconvenience.

@bortos

Thank you for being patient.

We would like to share with you that the properties of GlobalSettings are mapped to Scene.RootNode.AssetInfo, so the code snippet to read the UnitScaleFactor after Aspose.3D for .NET 18.9 should be:

        Scene scene = new Scene(fileName); 
        Console.WriteLine(scene.RootNode.AssetInfo.UnitName); 
        Console.WriteLine(scene.RootNode.AssetInfo.UnitScaleFactor); 

However, this may appear unclear, because the design of AssetInfo contains both information like Title/Author/Revisions and Coordinate system/Unit/Camera, they should be separated, but we have put them together to make it compatible with most 3D files and share the same interfaces.

Hi Farhan

I’ve updated to 18.10 and there are still some issues.

I have changed my code to use the following property for FBX file scale:

scene.RootNode.AssetInfo.UnitScaleFactor

Issue: Incorrect UnitScaleFactor when opening an existing FBX File

When opening an existing FBX file the UnitScaleFactor has not been correctly adjusted to meters. Instead, the returned value is equal to the FBX’s “OriginalUnitScaleFactor” raw value which is in centimeters.

For example, if you were to create and save fbx file that has 1 meter units, the FBX property “OriginalUnitScaleFactor” would be “100”. This is expected as 100 centimeters is 1 meter.
When opening that file with Aspose the scene.RootNode.AssetInfo.UnitScaleFactor is returning 100. It should be returning 1, as it is 1 unit = 1 meter.

The AssetInfo documentation states this should be in meters:

/// <summary>Gets or sets the scale factor to real-world meter.</summary>

Working as expected: Creating a new scene and setting scene.RootNode.AssetInfo.UnitScaleFactor

Creating a new scene and setting the file scale is working as expected. For example:

        var scene = new Scene();    
        if ( scene.RootNode.AssetInfo == null )
            scene.RootNode.AssetInfo = new AssetInfo();

        scene.RootNode.AssetInfo.UnitScaleFactor = 0.0254;

Saving the above scene to FBX Ascii shows the FBX property to be correct ( should be 2.54 )

Also, when creating a new scene the scene.RootNode.AssetInfo is null, not sure if that is intended. Maybe it is OK.

Interestingly opening an existing fbx file that has 1 unit = 1 inch ( OriginalUnitScaleFactor = 2.54 ), and then saving it immediately does not affect the value when comparing the before fbx to the saved fbx ( saving to ASCII for quick readability. )

@bortos

We have recorded your feedback under the same ticket and will update you with our findings soon. However, please upgrade to Aspose.3D for .NET 18.10 in your environment.

The issues you had found earlier (filed as THREEDNET-429) have been fixed in this update.

Farhan, my previous post was with the update to 18.10.

The UnitScaleFactor is not functioning correctly in 18.10. Not sure if this is just an issue with FBX files.

@bortos

The notification was posted because logged issue was marked as resolved in this release. We have recorded your concerns and will get back to you with our findings soon.

@bortos

We had found some issues with UnitScaleFactor in Aspose.3D for .NET 18.10 so we have resolved them and now sharing a Hotfix Aspose.3D for .NET 18.10.1 for your kind reference.

Aspose.3D-18.10.1.zip

This property is only used by FBX so far, so it’s null by default.

Yes, it is useless in other file formats.

Moreover, all the properties defined in FBX’s GlobalSettings that are not exposed by the interface of AssetInfo can be accessed by GetProperty as in the code snippet below:

Scene s = new Scene("test.fbx"); 
Console.WriteLine(s.RootNode.AssetInfo.UnitScaleFactor); 
Console.WriteLine(s.RootNode.AssetInfo.GetProperty("UnitScaleFactor")); 
Console.WriteLine(s.RootNode.AssetInfo.GetProperty("OriginalUnitScaleFactor")); 

The output of this code snippet may be:

0.0254 
0.0254 
2.54 

Where the definition in FBX file looks like:

P: "UnitScaleFactor", "double", "Number", "",2.54 
P: "OriginalUnitScaleFactor", "double", "Number", "",2.54 

The following statements returns the same 0.0254 (which scaled by * 0.01) because the unit is scaled by Aspose.3D

Console.WriteLine(s.RootNode.AssetInfo.UnitScaleFactor); 
Console.WriteLine(s.RootNode.AssetInfo.GetProperty("UnitScaleFactor")); 

But the OriginalUnitScaleFactor is not scaled because it an unsupported property, so you can always get its raw value.