[orx-camera] Add orthogonal projection

This commit is contained in:
Edwin Jakobs
2020-07-22 15:29:25 +02:00
parent 3409230147
commit b35aede77f
3 changed files with 49 additions and 13 deletions

View File

@@ -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) {

View File

@@ -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

View File

@@ -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)
}
}
}
}