Hi @jad maqdah
Calculation of viewportSz is, unfortunately, too complex to be reduced to mathematical equations. There are two basic steps that are run after a 3D Model is first inserted into Office: calculating the frame bounds, and then calculating the full frame size. We also run variations on these steps after any Office commands that change the camera settings.
Let’s refer to the bounds stored in the p:xfrm (transform) element of the p:graphicFrame element as the “3D Model Frame Rect”. Each app (PowerPoint, Excel, Word) have their own default Frame Rect dimensions for newly inserted 3D Models. PowerPoint chooses a default starting frameRect such that the width = slideWidth*2/3, the height = slideWidth*4/9, and the anchor is centered in the slide. I didn’t research the Excel or Word starting frame rect logic; they are probably similar.
- Update the 3D Model Frame Rect to match the aspect ratio of the 3D model
a. Start with originalFrameRect, the original 3D Model Frame Rect as described above (some fixed size relative to the doc slide/page).
b. Calculate originalFrameSize as the min of originalFrameRect's width or height.
c. Measure visibleBoundsRatios – A 2D ratio vector where visibleBoundsRatios.dx is the ratio of the how much of the (square) 3D camera viewport is filled on the x-axis, and visibleBoundsRatios.dy reflects the y-axis. We actually render the 3D model to a small texture and scan the image to measure this. For example, a value of (1.0,0.5) means the 3D scene fully fills the camera on the x-axis, but only fills 50% of the y-axis.
i. Note: We init our cameras to leave buffer around the 3D scene, and the scene is probably bigger on one axis than the other, so both values in the ratio vector are almost always smaller than 0.9 on each axis.
ii. Note: For an example seahorse model, which is tall and skinny, we measure this visible bounds ratio as (0.125, 0.858).
d. Calculate adjustedFrameRect = originalFrameSize * visibleBoundsRatios. This effectively shrinks originalFrameRect to have the aspect ratio of the camera output, but inscribed within and slightly smaller than the original/default frame rect. - Calculate “fullFrameSize”, which will then be stored in attribute viewportSz inside element am3d:objViewport:
a. Measure visibleBoundsRatios (same as described in part 1, and it should be the same exact value until the camera is changed or scene is rotated)
b. Inflate visibleBoundsRatios on whichever axis (x or y) allows its aspect ratio (visibleBoundsRatios.x / visibleBoundsRatios.y) to equal (adjustedFrameRect.width / adjustedFrameRect.height).
c. Calculate fullFrameSize = adjustedFrameRect.height / visibleBoundsRatios.dy
This is a complex algorithm, and could be challenging to emulate exactly like Office does it. The hardest part to emulate is probably 1.c and 2.a, which involve rasterization and image scanning. Perhaps you could approximate these steps instead, given some knowledge of how your camera and 3D scene were programmatically assembled.
Let me know if this helped
Hung-Chun Yu