[visionOS] Some models appear at the wrong scale when not using auto-fit
https://bugs.webkit.org/show_bug.cgi?id=314227
<rdar://167805672>

Reviewed by Mike Wyrzykowski.

On visionOS, WKRKEntity transforms are applied relative to the world
coordinate system. This can override the model's root entity transform
and loose scaling information about the model (when the unit is not 1
meter like in RealityKit).

Save this original scale so we can apply it on top of the other model
transforms.

* Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.h:
Add the field to store the original scale.
* Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.mm:
(WebKit::ModelProcessModelPlayerProxy::computeTransform):
Apply the original scale to the bounding sphere.
(WebKit::ModelProcessModelPlayerProxy::updateTransform):
Apply the original scale to the current transform.
(WebKit::ModelProcessModelPlayerProxy::didFinishLoading):
Save the original scale and apply it to the original bounding box.
(WebKit::ModelProcessModelPlayerProxy::updateForCurrentStageMode):
Apply the original scale to the current transform.
(WebKit::ModelProcessModelPlayerProxy::updateTransformSRT):
Remove the original scale from the transform value we report back to
JavaScript.

Canonical link: https://commits.webkit.org/312781@main
diff --git a/Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.h b/Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.h
index b6d401e..339c5a7 100644
--- a/Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.h
+++ b/Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.h
@@ -181,6 +181,7 @@
 
     simd_float3 m_originalBoundingBoxCenter { simd_make_float3(0, 0, 0) };
     simd_float3 m_originalBoundingBoxExtents { simd_make_float3(0, 0, 0) };
+    simd_float3 m_originalEntityScale { simd_make_float3(1, 1, 1) };
     float m_pitch { 0 };
     float m_yaw { 0 };
 
diff --git a/Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.mm b/Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.mm
index d79a4f0..573ffa2 100644
--- a/Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.mm
+++ b/Source/WebKit/ModelProcess/cocoa/ModelProcessModelPlayerProxy.mm
@@ -555,7 +555,7 @@
         return;
 
     // FIXME: Use the value of the 'object-fit' property here to compute an appropriate SRT.
-    float boundingRadius = [m_modelRKEntity boundingRadius];
+    float boundingRadius = [m_modelRKEntity boundingRadius] * m_originalEntityScale.x;
     simd_quatf currentModelRotation = setDefaultRotation ? simd_quaternion(0, simd_make_float3(1, 0, 0)) : m_transformSRT.rotation;
 #if ENABLE(MODEL_ELEMENT_IMMERSIVE)
     RESRT newSRT = computeSRT(m_layer.get(), m_originalBoundingBoxExtents, m_originalBoundingBoxCenter, boundingRadius, m_hasPortal, effectivePointsPerMeter(m_layer.get()), m_stageModeOperation, currentModelRotation, m_immersivePresentation);
@@ -580,7 +580,7 @@
     if (!m_modelRKEntity || !m_layer)
         return;
 
-    [m_modelRKEntity setTransform:WKEntityTransform({ m_transformSRT.scale, m_transformSRT.rotation, m_transformSRT.translation })];
+    [m_modelRKEntity setTransform:WKEntityTransform({ m_transformSRT.scale * m_originalEntityScale, m_transformSRT.rotation, m_transformSRT.translation })];
 }
 
 void ModelProcessModelPlayerProxy::updateTransformAfterLayout()
@@ -642,8 +642,13 @@
         m_modelRKEntity = adoptNS([allocWKRKEntityInstance() initWithCoreEntity:model->rootEntity()]);
     [m_modelRKEntity setDelegate:m_objCAdapter.get()];
 
-    m_originalBoundingBoxExtents = [m_modelRKEntity boundingBoxExtents];
-    m_originalBoundingBoxCenter = [m_modelRKEntity boundingBoxCenter];
+    // Capture the root entity's original scale before any transform is applied.
+    WKEntityTransform originalTransform = [m_modelRKEntity transform];
+    m_originalEntityScale = originalTransform.scale;
+
+    // The bounding box is relative to the entity's coordinate space so we still need to apply the scale.
+    m_originalBoundingBoxExtents = [m_modelRKEntity boundingBoxExtents] * m_originalEntityScale;
+    m_originalBoundingBoxCenter = [m_modelRKEntity boundingBoxCenter] * m_originalEntityScale;
 
     m_hostingEntity = adoptRE(REEntityCreate());
     REEntitySetName(m_hostingEntity.get(), "WebKit:EntityWithRootComponent");
@@ -1019,7 +1024,7 @@
 {
     if (m_stageModeOperation != WebCore::StageModeOperation::None) {
         computeTransform(false);
-        [m_modelRKEntity recenterEntityAtTransform:WKEntityTransform({ m_transformSRT.scale, m_transformSRT.rotation, m_transformSRT.translation })];
+        [m_modelRKEntity recenterEntityAtTransform:WKEntityTransform({ m_transformSRT.scale * m_originalEntityScale, m_transformSRT.rotation, m_transformSRT.translation })];
         updateTransformSRT();
     }
 
@@ -1040,7 +1045,7 @@
 {
     WKEntityTransform entityTransform = [m_modelRKEntity transform];
     m_transformSRT = RESRT {
-        .scale = entityTransform.scale,
+        .scale = entityTransform.scale / m_originalEntityScale,
         .rotation = entityTransform.rotation,
         .translation = entityTransform.translation
     };