Page 1 of 1

Fusion: how to get this geometrical distortion in 3D?

PostPosted: Wed May 14, 2025 7:25 pm
by BartReynaard
I need to replicate this exact distortion. I already created the cubes in Fusion, and the 3D camera is setup for orthogonal view.
But then I need to gradually distort the picture as it is shown here in this video
but I have not clue what to do to get it done.

Here the video

Re: Fusion: how to get this geometrical distortion in 3D?

PostPosted: Wed May 14, 2025 9:28 pm
by KrunoSmithy
Try lens distortion.

Re: Fusion: how to get this geometrical distortion in 3D?

PostPosted: Wed May 14, 2025 9:49 pm
by Sander de Regt
Since this is the result of the lens going to a wider angle, you have to turn off orthogonal and then adjust the angle width while either scaling up the cube or moving in towards it to compensate for the wider angle i.e. make a sort of reverse dolly zoom.

Re: Fusion: how to get this geometrical distortion in 3D?

PostPosted: Wed May 14, 2025 10:26 pm
by Bryan Ray
Aye, it's a zolly. At one point I worked out the math for how far to move the camera while changing the focal length...

I haven't tested it, but the formula at the bottom of the wikipedia page looks right: https://en.wikipedia.org/wiki/Dolly_zoom

Re: Fusion: how to get this geometrical distortion in 3D?

PostPosted: Wed May 14, 2025 10:50 pm
by philipbowser
I was just working on something where I needed to do this and came up with a handy expression that handles the 'zoom' in the dolly zoom.

Here's a sample comp that uses it. The camera will automatically adjust its angle of view based on the distance between its transform property and its target property. The camera's target is currently set in the center of the cube but you can put it wherever you want. On the controls page of the camera there's also an Initial AoV slider that you can adjust to taste. Move the camera wherever you want and the expression will handle the zoom.
Code: Select all
{
   Tools = ordered() {
      Cube3D1 = Cube3D {
         Inputs = {
            ["Transform3DOp.Translate.Y"] = Input { Value = 0.035, },
            ["Transform3DOp.Rotate.RotOrder"] = Input { Value = FuID { "YXZ" }, },
            ["Transform3DOp.Rotate.X"] = Input { Value = 35.3, },
            ["Transform3DOp.Rotate.Y"] = Input { Value = -45, },
            ["SurfaceCubeInputs.ObjectID.ObjectID"] = Input { Value = 4, },
            ["Front.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0.5, },
            ["Front.MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0, },
            ["Front.MtlStdInputs.MaterialID"] = Input { Value = 3, },
            ["Right.MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0.200000002980232, },
            ["Right.MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0, },
            ["Right.MtlStdInputs.MaterialID"] = Input { Value = 4, },
            ["Left.MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0.699999988079071, },
            ["Left.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0.400000005960464, },
            ["Left.MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0.699999988079071, },
            ["Left.MtlStdInputs.MaterialID"] = Input { Value = 5, },
            ["Bottom.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0, },
            ["Bottom.MtlStdInputs.MaterialID"] = Input { Value = 6, },
            ["Top.MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0, },
            ["Top.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0, },
            ["Top.MtlStdInputs.MaterialID"] = Input { Value = 7, },
            ["Back.MtlStdInputs.MaterialID"] = Input { Value = 8, }
         },
         ViewInfo = OperatorInfo { Pos = { 220, 181.5 } },
      },
      Merge3D3 = Merge3D {
         Inputs = {
            SceneInput1 = Input {
               SourceOp = "Cube3D1",
               Source = "Output",
            },
            SceneInput2 = Input {
               SourceOp = "Camera3D1",
               Source = "Output",
            }
         },
         ViewInfo = OperatorInfo { Pos = { 220, 214.5 } },
      },
      Camera3D1 = Camera3D {
         CtrlWZoom = false,
         Inputs = {
            ["Transform3DOp.Translate.Z"] = Input {
               SourceOp = "Camera3D1ZOffset",
               Source = "Value",
            },
            ["Transform3DOp.PivotNest"] = Input { Value = 1, },
            ["Transform3DOp.UseTarget"] = Input { Value = 1, },
            PerspNearClip = Input { Value = 0.1, },
            PerspFarClip = Input { Value = 10000, },
            AovType = Input { Value = 1, },
            AoV = Input {
               Value = 10.9378759788595,
               Expression = "2 * deg(atan(tan(rad(InitialAoV / 2)) * (4 / abs(sqrt(((Transform3DOp.Target.X-Transform3DOp.Translate.X)^2)+((Transform3DOp.Target.Y-Transform3DOp.Translate.Y)^2)+((Transform3DOp.Target.Z-Transform3DOp.Translate.Z)^2))))))",
            },
            FLength = Input { Value = 110.296518511085, },
            ["Stereo.Mode"] = Input { Value = FuID { "OffAxis" }, },
            FilmGate = Input { Value = FuID { "BMD_URSA_4K_16x9" }, },
            ApertureW = Input { Value = 0.831496062992126, },
            ApertureH = Input { Value = 0.467716535433071, },
            ["SurfacePlaneInputs.ObjectID.ObjectID"] = Input { Value = 3, },
            ["MtlStdInputs.MaterialID"] = Input { Value = 2, }
         },
         ViewInfo = OperatorInfo { Pos = { 330, 214.5 } },
         UserControls = ordered() {
            InitialAoV = {
               LINKS_Name = "Initial AoV",
               LINKID_DataType = "Number",
               INPID_InputControl = "SliderControl",
               INP_Default = 45,
               INP_Integer = false,
               INP_MinScale = 1,
               INP_MaxScale = 175,
               INP_MinAllowed = 1,
               INP_MaxAllowed = 175,
               ICS_ControlPage = "Controls"
            }
         }
      },
      Camera3D1ZOffset = BezierSpline {
         SplineColor = { Red = 254, Green = 56, Blue = 46 },
         CtrlWZoom = false,
         NameSet = true,
         KeyFrames = {
            [0] = { 17.3054219128132, RH = { 1.8, 11.9 }, Flags = { Linear = true } },
            [10] = { 1.54991230334487, LH = { 6.66666666666667, 1.54991230334487 } }
         }
      },
      Renderer3D1 = Renderer3D {
         CustomData = {
            ToolVersion = 2,
         },
         Inputs = {
            GlobalOut = Input { Value = 48, },
            Width = Input { Value = 1920, },
            Height = Input { Value = 1080, },
            ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
            SceneInput = Input {
               SourceOp = "Merge3D3",
               Source = "Output",
            }
         },
         ViewInfo = OperatorInfo { Pos = { 220, 280.5 } },
      }
   }
}



Alternatively, you can also achieve identical visual results by just scaling the cube on the axis that points at the camera, but this may not be ideal in all scenarios. Here's an example comp of that.
Code: Select all
{
   Tools = ordered() {
      Cube3D1_1 = Cube3D {
         Inputs = {
            ["Transform3DOp.Translate.Y"] = Input { Value = 0.035, },
            ["Transform3DOp.Rotate.RotOrder"] = Input { Value = FuID { "YXZ" }, },
            ["Transform3DOp.Rotate.X"] = Input { Value = 35.3, },
            ["Transform3DOp.Rotate.Y"] = Input { Value = -45, },
            ["SurfaceCubeInputs.ObjectID.ObjectID"] = Input { Value = 4, },
            ["Front.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0.5, },
            ["Front.MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0, },
            ["Front.MtlStdInputs.MaterialID"] = Input { Value = 3, },
            ["Right.MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0.200000002980232, },
            ["Right.MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0, },
            ["Right.MtlStdInputs.MaterialID"] = Input { Value = 4, },
            ["Left.MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0.699999988079071, },
            ["Left.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0.400000005960464, },
            ["Left.MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0.699999988079071, },
            ["Left.MtlStdInputs.MaterialID"] = Input { Value = 5, },
            ["Bottom.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0, },
            ["Bottom.MtlStdInputs.MaterialID"] = Input { Value = 6, },
            ["Top.MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0, },
            ["Top.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0, },
            ["Top.MtlStdInputs.MaterialID"] = Input { Value = 7, },
            ["Back.MtlStdInputs.MaterialID"] = Input { Value = 8, }
         },
         ViewInfo = OperatorInfo { Pos = { 550, 181.5 } },
      },
      Transform3D1 = Transform3D {
         CtrlWZoom = false,
         Inputs = {
            SceneInput = Input {
               SourceOp = "Cube3D1_1",
               Source = "Output",
            },
            ["Transform3DOp.ScaleLock"] = Input { Value = 0, },
            ["Transform3DOp.Scale.Z"] = Input {
               SourceOp = "Transform3D1ZScale",
               Source = "Value",
            }
         },
         ViewInfo = OperatorInfo { Pos = { 550, 214.5 } },
      },
      Transform3D1ZScale = BezierSpline {
         SplineColor = { Red = 254, Green = 20, Blue = 111 },
         CtrlWZoom = false,
         NameSet = true,
         KeyFrames = {
            [0] = { 1, RH = { 3.33333333333333, 1 }, Flags = { Linear = true } },
            [10] = { 5, LH = { 6.66666666666667, 5 } }
         }
      },
      Merge3D3_1 = Merge3D {
         Inputs = {
            SceneInput1 = Input {
               SourceOp = "Transform3D1",
               Source = "Output",
            },
            SceneInput2 = Input {
               SourceOp = "Camera3D2",
               Source = "Output",
            }
         },
         ViewInfo = OperatorInfo { Pos = { 550, 247.5 } },
      },
      Camera3D2 = Camera3D {
         Inputs = {
            ["Transform3DOp.Translate.Z"] = Input { Value = 5.39364869571355, },
            AoV = Input { Value = 19.2642683071402, },
            ["Stereo.Mode"] = Input { Value = FuID { "OffAxis" }, },
            FilmGate = Input { Value = FuID { "BMD_URSA_4K_16x9" }, },
            ApertureW = Input { Value = 0.831496062992126, },
            ApertureH = Input { Value = 0.467716535433071, },
            ["SurfacePlaneInputs.ObjectID.ObjectID"] = Input { Value = 1, },
            ["MtlStdInputs.MaterialID"] = Input { Value = 1, }
         },
         ViewInfo = OperatorInfo { Pos = { 660, 247.5 } },
      },
      Renderer3D1_1 = Renderer3D {
         CustomData = {
            ToolVersion = 2,
         },
         Inputs = {
            GlobalOut = Input { Value = 48, },
            Width = Input { Value = 1920, },
            Height = Input { Value = 1080, },
            ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
            SceneInput = Input {
               SourceOp = "Merge3D3_1",
               Source = "Output",
            }
         },
         ViewInfo = OperatorInfo { Pos = { 550, 313.5 } },
      }
   }
}

Re: Fusion: how to get this geometrical distortion in 3D?

PostPosted: Thu May 15, 2025 12:09 am
by philipbowser
Now that I'm revisiting this, I've tried a different method using the Expression modifier that seems to handle rendering a bit better. For some reason I was getting render cache issues with the previous expression.

With this setup, you can freely change the Focal Length or Angle of View sliders to taste and they will automatically compensate based on the distance between the position of the camera and its target.

Code: Select all
{
   Tools = ordered() {
      Cube3D1 = Cube3D {
         Inputs = {
            ["Transform3DOp.Translate.Y"] = Input { Value = 0.035, },
            ["Transform3DOp.Rotate.RotOrder"] = Input { Value = FuID { "YXZ" }, },
            ["Transform3DOp.Rotate.X"] = Input { Value = 35.3, },
            ["Transform3DOp.Rotate.Y"] = Input { Value = -45, },
            ["SurfaceCubeInputs.ObjectID.ObjectID"] = Input { Value = 4, },
            ["Front.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0.5, },
            ["Front.MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0, },
            ["Front.MtlStdInputs.MaterialID"] = Input { Value = 3, },
            ["Right.MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0.200000002980232, },
            ["Right.MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0, },
            ["Right.MtlStdInputs.MaterialID"] = Input { Value = 4, },
            ["Left.MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0.699999988079071, },
            ["Left.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0.400000005960464, },
            ["Left.MtlStdInputs.Diffuse.Color.Blue"] = Input { Value = 0.699999988079071, },
            ["Left.MtlStdInputs.MaterialID"] = Input { Value = 5, },
            ["Bottom.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0, },
            ["Bottom.MtlStdInputs.MaterialID"] = Input { Value = 6, },
            ["Top.MtlStdInputs.Diffuse.Color.Red"] = Input { Value = 0, },
            ["Top.MtlStdInputs.Diffuse.Color.Green"] = Input { Value = 0, },
            ["Top.MtlStdInputs.MaterialID"] = Input { Value = 7, },
            ["Back.MtlStdInputs.MaterialID"] = Input { Value = 8, }
         },
         ViewInfo = OperatorInfo { Pos = { 169.333, 169.788 } },
      },
      Merge3D3 = Merge3D {
         Inputs = {
            SceneInput1 = Input {
               SourceOp = "Cube3D1",
               Source = "Output",
            },
            SceneInput2 = Input {
               SourceOp = "Camera3D1",
               Source = "Output",
            }
         },
         ViewInfo = OperatorInfo { Pos = { 169.333, 202.788 } },
      },
      Camera3D1 = Camera3D {
         Inputs = {
            ["Transform3DOp.Translate.Z"] = Input {
               SourceOp = "Camera3D1ZOffset",
               Source = "Value",
            },
            ["Transform3DOp.PivotNest"] = Input { Value = 1, },
            ["Transform3DOp.UseTarget"] = Input { Value = 1, },
            PerspFarClip = Input { Value = 10000, },
            AovType = Input { Value = 1, },
            AoV = Input { Value = 109.312057231196, },
            FLength = Input {
               SourceOp = "Calculation1",
               Source = "Result",
            },
            ["Stereo.Mode"] = Input { Value = FuID { "OffAxis" }, },
            FilmGate = Input { Value = FuID { "BMD_URSA_4K_16x9" }, },
            ApertureW = Input { Value = 0.831496062992126, },
            ApertureH = Input { Value = 0.467716535433071, },
            ["SurfacePlaneInputs.ObjectID.ObjectID"] = Input { Value = 3, },
            ["MtlStdInputs.MaterialID"] = Input { Value = 2, }
         },
         ViewInfo = OperatorInfo { Pos = { 279.333, 202.788 } },
         UserControls = ordered() {
            InitialAoV = {
               INP_MaxAllowed = 175,
               INP_Integer = false,
               INPID_InputControl = "SliderControl",
               INP_MaxScale = 175,
               INP_Default = 45,
               INP_MinScale = 1,
               INP_MinAllowed = 1,
               LINKID_DataType = "Number",
               ICS_ControlPage = "Controls",
               LINKS_Name = "Initial AoV"
            }
         }
      },
      Camera3D1ZOffset = BezierSpline {
         SplineColor = { Red = 254, Green = 56, Blue = 46 },
         NameSet = true,
         KeyFrames = {
            [0] = { 13.34, RH = { 3.66666666666667, 9.28333333333333 }, Flags = { Linear = true } },
            [11] = { 1.17, LH = { 7.33333333333333, 1.17 } }
         }
      },
      Calculation1 = Calculation {
         Inputs = {
            FirstOperand = Input { Value = 6.40091489106122, },
            Operator = Input { Value = 2, },
            SecondOperand = Input {
               SourceOp = "Expression1",
               Source = "NumberResult",
            }
         },
      },
      Expression1 = Expression {
         CtrlWZoom = false,
         Inputs = {
            n1 = Input { Expression = "Camera3D1.Transform3DOp.Translate.X", },
            n2 = Input { Expression = "Camera3D1.Transform3DOp.Translate.Y", },
            n3 = Input {
               Value = 1.17,
               Expression = "Camera3D1.Transform3DOp.Translate.Z",
            },
            n4 = Input { Expression = "Camera3D1.Transform3DOp.Target.X", },
            n5 = Input { Expression = "Camera3D1.Transform3DOp.Target.Y", },
            n6 = Input { Expression = "Camera3D1.Transform3DOp.Target.Z", },
            NumberExpression = Input { Value = "dist3d(n1,n2,n3,n4,n5,n6)", },
            NumberControls = Input { Value = 1, },
            ShowNumber7 = Input { Value = 0, },
            ShowNumber8 = Input { Value = 0, },
            ShowNumber9 = Input { Value = 0, },
            PointControls = Input { Value = 1, },
            ShowPoint1 = Input { Value = 0, },
            ShowPoint2 = Input { Value = 0, },
            ShowPoint3 = Input { Value = 0, },
            ShowPoint4 = Input { Value = 0, },
            ShowPoint5 = Input { Value = 0, },
            ShowPoint6 = Input { Value = 0, },
            ShowPoint7 = Input { Value = 0, },
            ShowPoint8 = Input { Value = 0, },
            ShowPoint9 = Input { Value = 0, }
         },
      },
      Renderer3D1 = Renderer3D {
         CtrlWZoom = false,
         CustomData = {
            ToolVersion = 2,
         },
         Inputs = {
            Width = Input { Value = 1920, },
            Height = Input { Value = 1080, },
            ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
            SceneInput = Input {
               SourceOp = "Merge3D3",
               Source = "Output",
            },
            CameraSelector = Input { Value = FuID { "Camera3D1" }, },
            ["RendererOpenGL.AntiAliasing.Channels.RGBA.HighQuality.Enable"] = Input { Value = 1, },
            ["RendererOpenGL.AntiAliasing.Presets.Color.Supersampling.HighQuality.Rate"] = Input { Value = 3, },
            ["RendererOpenGL.AntiAliasing.Presets.Color.Multisampling.LowQuality.SampleCount"] = Input { Value = 2, },
            ["RendererOpenGL.AntiAliasing.Presets.Color.Multisampling.HighQuality.SampleCount"] = Input { Value = 3, },
            ["RendererOpenGL.AntiAliasing.Presets.Aux.Supersampling.HighQuality.Rate"] = Input { Value = 3, },
            ["RendererOpenGL.AntiAliasing.Presets.Aux.Multisampling.LowQuality.SampleCount"] = Input { Value = 2, },
            ["RendererOpenGL.AntiAliasing.Presets.Aux.Multisampling.HighQuality.SampleCount"] = Input { Value = 3, },
            ["RendererOpenGL.AccumQuality"] = Input { Value = 32, }
         },
         ViewInfo = OperatorInfo { Pos = { 169.333, 268.788 } },
         SubInputsData = {
            RendererOpenGL = {
               Version = 1
            }
         }
      }
   }
}