Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    CAMERA_ZOOM and Pparallel

    Cinema 4D SDK
    c++
    2
    4
    359
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • WickedPW
      WickedP
      last edited by

      Hi Folks,

      How does the camera zoom work with Pparallel? It feels really unituitive without knowing what the number means. How can I set the 'zoom' so that it covers a particular unit area of the viewport?

      As an example, if I have an object - say a plane that's width and height are the same in units as HD resolution (so width 1920 and height 1080), how can I set the 'zoom' so that the parallel camera covers the precise width (or height) of the plane (assume everything lines up)?

      This viewport capture might help to visualise:

      7046624e-e3be-47d5-bff7-6c7313b5bb04-image.png

      I want to know what 'zoom' means in terms of viewport unit size, so that I can set the 'zoom' to a size that reflects an object unit size in the scene.

      WP.

      wickedp.com

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @WickedP
        last edited by ferdinand

        Hey @WickedP,

        Thank you for reaching out to us. I sense there is some frustration, but I am not sure how you would expect this to work to be more intuitive. Cinema 4D has to norm its orthographic camera somehow, since an orthographic projection preserves length.

        You could just use one of the built-in framing commands or API functions, but here is how to do it manually. Cinema 4D normalizes its orthographic projection to 1024 units on the larger camera axis. I.e., for a standard 16:9 resolution such as 1080p, this means a plane with the dimensions 1024x576 will fill exactly the viewport. The rest is then just some math, see my example below.

        Cheers,
        Ferdinand

        Result

        ead1ec9c-3ed8-44fd-8c5b-e11d65fd8758-image.png

        Code

        """Demonstrates how to fit an object into the view frustum of an orthographic camera.
        
        Will create a plane of random size, a random render resolution, an orthographic camera, and then fit
        the camera to the plane so that it fits in the viewport. You can run this script rapidly multiple 
        times to see it fit different planes into different aspect ratios of a viewport.
        
        WARNING: 
            
            This script will empty the whole document each time it is run (i.e., it will delete all objects, 
            materials, lights, etc.), so make sure to save your work before running it.
        """
        
        import c4d
        import mxutils
        
        doc: c4d.documents.BaseDocument  # The currently active document.
        op: c4d.BaseObject | None  # The primary selected object in `doc`. Can be `None`.
        
        def main() -> None:
            """Called by Cinema 4D when the script is being executed.
            """
            # Empty the whole document.
            doc.Flush()
        
            # Set the width, height and aspect ratio of the current render settings.
            rData: c4d.documents.RenderData = doc.GetActiveRenderData()
            renderSize: c4d.Vector = mxutils.g_random.RandomVector(
                lower=c4d.Vector(64), upper=c4d.Vector(2048))
            rData[c4d.RDATA_XRES] = int(renderSize.x)
            rData[c4d.RDATA_YRES] = int(renderSize.y)
            rData[c4d.RDATA_FILMASPECT] = renderSize.x / renderSize.y
        
            # The inverse aspect ratio is used to calculate the camera zoom.
            iAspect: float = renderSize.y / renderSize.x
        
            # Create a plane object of random size.
            plane: c4d.BaseObject = mxutils.CheckType(c4d.BaseObject(c4d.Oplane))
            planeSize: c4d.Vector = mxutils.g_random.RandomVector(
                lower=c4d.Vector(256), upper=c4d.Vector(4096))
            plane[c4d.PRIM_PLANE_WIDTH] = planeSize.x
            plane[c4d.PRIM_PLANE_HEIGHT] = planeSize.y
            plane[c4d.PRIM_AXIS] = c4d.PRIM_AXIS_ZP
        
            # Create an orthographic camera.
            camera: c4d.BaseObject = mxutils.CheckType(c4d.BaseObject(c4d.Ocamera))
            camera[c4d.CAMERA_PROJECTION] = c4d.Pparallel
            camera.SetMg(c4d.Matrix(off=c4d.Vector(0, 0, -1)))
        
            # Cinema 4D norms its orthographic camera zoom to fit 1024 units on the widest axis at 100%.
            # I.e., for the standard 16:9 viewport, it will fit a 1024x576 rectangle in the viewport, no
            # matter the actual viewport size (what counts is the aspect ratio).
        
            # We calculate the zoom factor so that the plane fits in the viewport by calculating the zoom
            # both for the x and y axes, and then taking the minimum of the two.
            cameraZoom: float = min(1024.0 / planeSize.x, 1024.0 / planeSize.y * iAspect)
            camera[c4d.CAMERA_ZOOM] = cameraZoom
        
            # Insert things into the document.
            doc.InsertObject(plane)
            doc.InsertObject(camera)
            viewport: c4d.BaseDraw = doc.GetActiveBaseDraw()
            viewport.SetSceneCamera(camera)
        
            print(f"Created plane of size ({planeSize.x}, {planeSize.y}) and camera with a zoom of "
                  f"'{cameraZoom:.2f}', fitting it into a viewport of size ({renderSize.x}, {renderSize.y}).")
        
            c4d.EventAdd()
        
        
        if __name__ == '__main__':
            main()
        

        MAXON SDK Specialist
        developers.maxon.net

        WickedPW 1 Reply Last reply Reply Quote 0
        • WickedPW
          WickedP @ferdinand
          last edited by

          Thanks @ferdinand, this seems to have solved my problem.

          Apologies if it came across a bit abrupt, I was trying to get to the crux of it. Just seemed strange that there wasn't a way to rationally relate the zoom to any meaningful size for an orthographic camera. In other software I recall being able to set the camera as a width and height, not some factor of zoom. Made much more sense, kind of like setting it as a size. Also curious to know why they choose 1024 to underpin the zoom and not a rounded number, like 1000 (or something that can work off C4D's base unit).

          But all good here - it's working now. Solved.

          WP.

          wickedp.com

          1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand
            last edited by ferdinand

            Hey @WickedP,

            It did not come across as abrupt or rude, but it was clear that you were a bit frustrated, and I was just trying to make clear that they had to choose some magic number, as that is the nature of rendering an orthographic projection. As to why we chose this number, I have no idea, as this happened 20 years or an even longer time back, long before I was at Maxon. It could either be because programmers simply love powers of two, or something more concrete such as that a power of two leads to less floating precision losses when multiplying other numbers with them, or simply that they did chose 1024x576 as the norm render size then.

            And you can set the camera width and height, but you just do this in the render settings with the render resolution, which was pretty standard for 3D software I would say. The new Redshift camera then uses a more complex model with an actual sensor and fitting the sensor to the render resolution (which I ignored here since you showed us using a Standard camera).

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

            1 Reply Last reply Reply Quote 0
            • First post
              Last post