How to use OrbitalCamera and OrbitalControls in only some parts of your program?

Hi! I have the following in my program:

        val camera = OrbitalCamera(Vector3.UNIT_Z * 1000.0, Vector3.ZERO, 90.0, 0.1, 2000.0)
        val controls = OrbitalControls(camera, keySpeed = 10.0)

        extend(camera)
        extend(controls)

which affects everything I draw with drawer. How can I draw things that are not affected by the camera?

You’d do this by not using the camera as an extension and setting the view and projection matrices manually.

val camera = OrbitalCamera(Vector3.UNIT_Z * 1000.0, Vector3.ZERO, 90.0, 0.1, 2000.0)
val controls = OrbitalControls(camera, keySpeed = 10.0)
extend(controls)
extend {
    camera.update(deltaTime)
    // -- draw in ortho here
    
    drawer.isolated { 
        drawer.perspective(camera.fov, width.toDouble() / height, camera.near, camera.far)
        drawer.view = camera.viewMatrix()
        drawer.drawStyle.depthWrite = true
        drawer.drawStyle.depthTestPass = DepthTestPass.LESS_OR_EQUAL
        // draw in perspective here
    }
   // -- draw in ortho here
}
1 Like

Thanks! That works almost perfectly. With that change I get a side effect: polygons seem to have the wrong z-sorting. Why could that be?
2020-03-16-134434_462x455_scrot

Note: to make it compile I used camera.update(deltaTime)

To get the right behaviour you need to enable depth writing and testing. The conventional settings are:

drawer.drawStyle.depthWrite = true
drawer.drawStyle.depthTestPass = DepthTestPass.LESS_OR_EQUAL

Adviced is to place them inside the isolated block.

1 Like

Since camera.update(deltaTime) would no longer work (deltaTime no longer exists), I’m sharing a newer approach.

A fixed 2D circle in the background, an interactive 3D shape in the middle, and a fixed 2D ring on front of everything.

sketches.Orbital_01-2024-02-08-19.42.15

imports
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.DrawPrimitive
import org.openrndr.draw.shadeStyle
import org.openrndr.extra.camera.OrbitalCamera
import org.openrndr.extra.camera.OrbitalControls
import org.openrndr.extra.camera.isolated
import org.openrndr.extra.meshgenerators.boxMesh
import org.openrndr.math.Vector3
fun main() = application {
    program {
        val box = boxMesh(50.0, 20.0, 5.0)

        val camera = OrbitalCamera(Vector3.ONE * 20.0, Vector3.ZERO, 90.0, 0.1, 5000.0)
        val controls = OrbitalControls(camera)

        val gradientShading = shadeStyle {
            fragmentTransform = """
                vec3 c = sin(v_worldPosition * 0.1) * 0.5 + 0.5;
                c = c * (dot(va_normal, vec3(0.1, 0.2, 0.8)) * 0.5 + 0.5);
                x_fill = vec4(c, 1.0);
            """.trimIndent()
        }

        var secondsLast = seconds

        //extend(camera)
        extend(controls)
        extend {
            camera.update(seconds - secondsLast)
            secondsLast = seconds

            // Draw in 2D on the back
            drawer.circle(drawer.bounds.center, 200.0)

            // Draw in 3D
            camera.isolated(drawer) {
                drawer.shadeStyle = gradientShading
                drawer.vertexBuffer(box, DrawPrimitive.TRIANGLES)
            }

            // Draw in 2D on the front
            drawer.strokeWeight = 4.0
            drawer.shadeStyle = null
            drawer.fill = null
            drawer.stroke = ColorRGBa.WHITE
            drawer.circle(drawer.bounds.center, 220.0)
        }
    }
}

Note: if you don’t need to revert back to 2D (ortho) mode, you can use

camera.applyTo(drawer)

instead of

camera.isolated(drawer) { ... }

which is a tiny bit faster.