From b35aede77fb7896de8dd9929e79a1af2231d384c Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Wed, 22 Jul 2020 15:29:25 +0200 Subject: [PATCH] [orx-camera] Add orthogonal projection --- orx-camera/src/main/kotlin/Orbital.kt | 3 +- orx-camera/src/main/kotlin/OrbitalCamera.kt | 43 +++++++++++++++---- orx-camera/src/main/kotlin/OrbitalControls.kt | 16 +++++-- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/orx-camera/src/main/kotlin/Orbital.kt b/orx-camera/src/main/kotlin/Orbital.kt index 4faf0a48..41eb273d 100644 --- a/orx-camera/src/main/kotlin/Orbital.kt +++ b/orx-camera/src/main/kotlin/Orbital.kt @@ -18,8 +18,9 @@ class Orbital : Extension { var fov = 90.0 var userInteraction = true var keySpeed = 1.0 + var projectionType = ProjectionType.PERSPECTIVE - val camera by lazy { OrbitalCamera(eye, lookAt, fov, near, far) } + val camera by lazy { println("creating camera $projectionType"); OrbitalCamera(eye, lookAt, fov, near, far, projectionType) } val controls by lazy { OrbitalControls(camera, userInteraction, keySpeed) } override fun setup(program: Program) { diff --git a/orx-camera/src/main/kotlin/OrbitalCamera.kt b/orx-camera/src/main/kotlin/OrbitalCamera.kt index 93556db5..2eaea1f3 100644 --- a/orx-camera/src/main/kotlin/OrbitalCamera.kt +++ b/orx-camera/src/main/kotlin/OrbitalCamera.kt @@ -10,7 +10,13 @@ import org.openrndr.math.Vector3 import kotlin.math.abs import org.openrndr.math.transforms.lookAt as lookAt_ -class OrbitalCamera(eye: Vector3 = Vector3.ZERO, lookAt: Vector3 = Vector3.UNIT_Z, var fov: Double = 90.0, var near: Double = 0.1, var far: Double = 1000.0) : Extension { +enum class ProjectionType { + PERSPECTIVE, + ORTHOGONAL +} + + +class OrbitalCamera(eye: Vector3 = Vector3.ZERO, lookAt: Vector3 = Vector3.UNIT_Z, var fov: Double = 90.0, var near: Double = 0.1, var far: Double = 1000.0, var projectionType: ProjectionType = ProjectionType.PERSPECTIVE) : Extension { // current position in spherical coordinates var spherical = Spherical.fromVector(eye) private set @@ -19,6 +25,9 @@ class OrbitalCamera(eye: Vector3 = Vector3.ZERO, lookAt: Vector3 = Vector3.UNIT_ var depthTest = true + var magnitude = 100.0 + var magnitudeEnd = magnitude + private var sphericalEnd = Spherical.fromVector(eye) private var lookAtEnd = lookAt private var dirty: Boolean = true @@ -90,6 +99,11 @@ class OrbitalCamera(eye: Vector3 = Vector3.ZERO, lookAt: Vector3 = Vector3.UNIT_ dirty = true } + fun scale(s: Double) { + magnitudeEnd += s + dirty = true + } + fun zoom(degrees: Double) { fovEnd += degrees dirty = true @@ -108,25 +122,27 @@ class OrbitalCamera(eye: Vector3 = Vector3.ZERO, lookAt: Vector3 = Vector3.UNIT_ val sphericalDelta = sphericalEnd - spherical val lookAtDelta = lookAtEnd - lookAt val fovDelta = fovEnd - fov + val magnitudeDelta = magnitudeEnd - magnitude if ( - abs(sphericalEnd.radius) > EPSILON || - abs(sphericalEnd.theta) > EPSILON || - abs(sphericalEnd.phi) > EPSILON || + abs(sphericalDelta.radius) > EPSILON || + abs(sphericalDelta.theta) > EPSILON || + abs(sphericalDelta.phi) > EPSILON || abs(lookAtDelta.x) > EPSILON || abs(lookAtDelta.y) > EPSILON || abs(lookAtDelta.z) > EPSILON || abs(fovDelta) > EPSILON ) { - fov += (fovDelta * dampingFactor) spherical += (sphericalDelta * dampingFactor) spherical = spherical.makeSafe() lookAt += (lookAtDelta * dampingFactor) + magnitude += (magnitudeDelta * dampingFactor) dirty = true - } else { + magnitude = magnitudeEnd spherical = sphericalEnd.copy() lookAt = lookAtEnd.copy() + fov = fovEnd } spherical = spherical.makeSafe() } @@ -150,7 +166,12 @@ class OrbitalCamera(eye: Vector3 = Vector3.ZERO, lookAt: Vector3 = Vector3.UNIT_ update(delta) - drawer.perspective(fov, program.window.size.x / program.window.size.y, near, far) + if (projectionType == ProjectionType.PERSPECTIVE) { + drawer.perspective(fov, drawer.width.toDouble() / drawer.height, near, far) + } else { + val ar = drawer.width * 1.0 / drawer.height + drawer.ortho(-ar * magnitude, ar * magnitude, -1.0 * magnitude, 1.0 * magnitude, -1000.0, 1000.0) + } drawer.view = viewMatrix() if (depthTest) { @@ -188,7 +209,13 @@ fun OrbitalCamera.isolated(drawer: Drawer, function: Drawer.() -> Unit) { * if you don't need to revert back to the orthographic projection. */ fun OrbitalCamera.applyTo(drawer: Drawer) { - drawer.perspective(fov, drawer.width.toDouble() / drawer.height, near, far) + + if (projectionType == ProjectionType.PERSPECTIVE) { + drawer.perspective(fov, drawer.width.toDouble() / drawer.height, near, far) + } else { + val ar = drawer.width * 1.0 / drawer.height + drawer.ortho(-ar, ar, 1.0, -1.0, near, far) + } drawer.view = viewMatrix() drawer.drawStyle.depthWrite = true drawer.drawStyle.depthTestPass = DepthTestPass.LESS_OR_EQUAL diff --git a/orx-camera/src/main/kotlin/OrbitalControls.kt b/orx-camera/src/main/kotlin/OrbitalControls.kt index 981a3111..6f3b387d 100644 --- a/orx-camera/src/main/kotlin/OrbitalControls.kt +++ b/orx-camera/src/main/kotlin/OrbitalControls.kt @@ -22,11 +22,19 @@ class OrbitalControls(val orbitalCamera: OrbitalCamera, val userInteraction: Boo private fun mouseScrolled(event: MouseEvent) { if (!event.propagationCancelled) { - if (abs(event.rotation.x) > 0.1) return - when { - event.rotation.y > 0 -> orbitalCamera.dollyIn() - event.rotation.y < 0 -> orbitalCamera.dollyOut() + if (orbitalCamera.projectionType == ProjectionType.PERSPECTIVE) { + if (abs(event.rotation.x) > 0.1) return + when { + event.rotation.y > 0 -> orbitalCamera.dollyIn() + event.rotation.y < 0 -> orbitalCamera.dollyOut() + } + } else { + if (abs(event.rotation.x) > 0.1) return + when { + event.rotation.y > 0 -> orbitalCamera.scale(1.0) + event.rotation.y < 0 -> orbitalCamera.scale(-1.0) + } } } }