[orx-camera] Add ChangeEvents interface

This commit is contained in:
Edwin Jakobs
2022-12-21 22:09:47 +01:00
parent d10ddb7dcb
commit 58359b9bab
5 changed files with 97 additions and 13 deletions

View File

@@ -5,6 +5,7 @@ import org.openrndr.MouseEvents
import org.openrndr.Program import org.openrndr.Program
import org.openrndr.draw.Drawer import org.openrndr.draw.Drawer
import org.openrndr.draw.RenderTarget import org.openrndr.draw.RenderTarget
import org.openrndr.events.Event
import org.openrndr.math.Matrix44 import org.openrndr.math.Matrix44
import org.openrndr.math.transforms.buildTransform import org.openrndr.math.transforms.buildTransform
@@ -15,13 +16,27 @@ import org.openrndr.math.transforms.buildTransform
* *
* Usage: `extend(Camera2D())` * Usage: `extend(Camera2D())`
*/ */
class Camera2D : Extension { class Camera2D : Extension, ChangeEvents {
override var enabled = true override var enabled = true
var view = Matrix44.IDENTITY var view = Matrix44.IDENTITY
override val changed = Event<Unit>()
private var dirty = true
set(value) {
if (value && !field) {
changed.trigger(Unit)
}
field = value
}
override val hasChanged: Boolean
get() = dirty
fun setupMouseEvents(mouse: MouseEvents) { fun setupMouseEvents(mouse: MouseEvents) {
mouse.dragged.listen { mouse.dragged.listen {
view = buildTransform { translate(it.dragDisplacement) } * view view = buildTransform { translate(it.dragDisplacement) } * view
dirty = true
} }
mouse.scrolled.listen { mouse.scrolled.listen {
val scaleFactor = 1.0 - it.rotation.y * 0.03 val scaleFactor = 1.0 - it.rotation.y * 0.03
@@ -30,6 +45,7 @@ class Camera2D : Extension {
scale(scaleFactor) scale(scaleFactor)
translate(-it.position) translate(-it.position)
} * view } * view
dirty = true
} }
} }
override fun setup(program: Program) { override fun setup(program: Program) {
@@ -43,6 +59,7 @@ class Camera2D : Extension {
} }
override fun afterDraw(drawer: Drawer, program: Program) { override fun afterDraw(drawer: Drawer, program: Program) {
dirty = false
drawer.popTransforms() drawer.popTransforms()
} }
} }

View File

@@ -0,0 +1,8 @@
package org.openrndr.extra.camera
import org.openrndr.events.Event
interface ChangeEvents {
val changed : Event<Unit>
val hasChanged: Boolean
}

View File

@@ -3,14 +3,22 @@ package org.openrndr.extra.camera
import org.openrndr.Extension import org.openrndr.Extension
import org.openrndr.Program import org.openrndr.Program
import org.openrndr.draw.Drawer import org.openrndr.draw.Drawer
import org.openrndr.events.Event
import org.openrndr.math.Vector3 import org.openrndr.math.Vector3
/** /**
* Extension that provides orbital camera view and controls. * Extension that provides orbital camera view and controls.
*/ */
class Orbital : Extension { class Orbital : Extension, ChangeEvents {
override var enabled: Boolean = true override var enabled: Boolean = true
override val changed = Event<Unit>()
override val hasChanged: Boolean
get() {
return camera.hasChanged
}
var eye = Vector3.UNIT_Z * 10.0 var eye = Vector3.UNIT_Z * 10.0
var lookAt = Vector3.ZERO var lookAt = Vector3.ZERO
var near = 0.1 var near = 0.1
@@ -28,6 +36,7 @@ class Orbital : Extension {
val camera by lazy { val camera by lazy {
OrbitalCamera(eye, lookAt, fov, near, far, projectionType).apply { OrbitalCamera(eye, lookAt, fov, near, far, projectionType).apply {
dampingFactor = this@Orbital.dampingFactor dampingFactor = this@Orbital.dampingFactor
this.changed.listen(this@Orbital.changed)
} }
} }
val controls by lazy { OrbitalControls(camera, userInteraction, keySpeed) } val controls by lazy { OrbitalControls(camera, userInteraction, keySpeed) }

View File

@@ -4,6 +4,7 @@ import org.openrndr.Extension
import org.openrndr.Program import org.openrndr.Program
import org.openrndr.draw.DepthTestPass import org.openrndr.draw.DepthTestPass
import org.openrndr.draw.Drawer import org.openrndr.draw.Drawer
import org.openrndr.events.Event
import org.openrndr.math.Matrix44 import org.openrndr.math.Matrix44
import org.openrndr.math.Spherical import org.openrndr.math.Spherical
import org.openrndr.math.Vector3 import org.openrndr.math.Vector3
@@ -17,7 +18,21 @@ enum class ProjectionType {
} }
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 { 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, ChangeEvents {
override val changed = Event<Unit>()
override val hasChanged: Boolean
get() = dirty
// current position in spherical coordinates // current position in spherical coordinates
var spherical = Spherical.fromVector(eye) var spherical = Spherical.fromVector(eye)
private set private set
@@ -32,6 +47,12 @@ class OrbitalCamera(eye: Vector3 = Vector3.ZERO, lookAt: Vector3 = Vector3.UNIT_
private var sphericalEnd = Spherical.fromVector(eye) private var sphericalEnd = Spherical.fromVector(eye)
private var lookAtEnd = lookAt private var lookAtEnd = lookAt
private var dirty: Boolean = true private var dirty: Boolean = true
set(value) {
if (value && !field) {
changed.trigger(Unit)
}
field = value
}
private var lastSeconds: Double = -1.0 private var lastSeconds: Double = -1.0
var fovEnd = fov var fovEnd = fov
@@ -127,7 +148,9 @@ class OrbitalCamera(eye: Vector3 = Vector3.ZERO, lookAt: Vector3 = Vector3.UNIT_
if (!dirty) return if (!dirty) return
dirty = false dirty = false
val dampingFactor = if (dampingFactor > 0.0) { dampingFactor * timeDelta / 0.0060 } else 1.0 val dampingFactor = if (dampingFactor > 0.0) {
dampingFactor * timeDelta / 0.0060
} else 1.0
val sphericalDelta = sphericalEnd - spherical val sphericalDelta = sphericalEnd - spherical
val lookAtDelta = lookAtEnd - lookAt val lookAtDelta = lookAtEnd - lookAt
val fovDelta = fovEnd - fov val fovDelta = fovEnd - fov

View File

@@ -3,6 +3,7 @@ package org.openrndr.extra.camera
import org.openrndr.Extension import org.openrndr.Extension
import org.openrndr.Program import org.openrndr.Program
import org.openrndr.draw.Drawer import org.openrndr.draw.Drawer
import org.openrndr.events.Event
import org.openrndr.extra.parameters.Description import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.extra.parameters.Vector3Parameter import org.openrndr.extra.parameters.Vector3Parameter
@@ -13,12 +14,25 @@ import org.openrndr.math.Vector3
* Extension that provides orbital camera through annotated parameters * Extension that provides orbital camera through annotated parameters
*/ */
@Description("Orbital camera") @Description("Orbital camera")
class ParametricOrbital : Extension { class ParametricOrbital : Extension, ChangeEvents {
override var enabled: Boolean = true override var enabled: Boolean = true
override val changed = Event<Unit>()
override val hasChanged: Boolean
get() = dirty
private var dirty = true
set(value) {
if (value && !field) {
changed.trigger(Unit)
}
field = value
}
@DoubleParameter("fov", 1.0, 90.0, order = 0) @DoubleParameter("fov", 1.0, 90.0, order = 0)
var fov = 45.0 var fov = 45.0
set(value) { set(value) {
if (field != value) {
dirty = true
}
field = value field = value
camera.zoomTo(fov) camera.zoomTo(fov)
} }
@@ -32,6 +46,9 @@ class ParametricOrbital : Extension {
@DoubleParameter("phi", 0.0, 180.0, order = 2) @DoubleParameter("phi", 0.0, 180.0, order = 2)
var phi = 0.0 var phi = 0.0
set(value) { set(value) {
if (field != value) {
dirty = true
}
field = value field = value
camera.rotateTo(theta, phi.coerceAtLeast(1E-3)) camera.rotateTo(theta, phi.coerceAtLeast(1E-3))
} }
@@ -39,6 +56,9 @@ class ParametricOrbital : Extension {
@DoubleParameter("theta", -180.0, 180.0, order = 1) @DoubleParameter("theta", -180.0, 180.0, order = 1)
var theta = 0.0 var theta = 0.0
set(value) { set(value) {
if (field != value) {
dirty = true
}
field = value field = value
camera.rotateTo(theta, phi.coerceAtLeast(1E-3)) camera.rotateTo(theta, phi.coerceAtLeast(1E-3))
} }
@@ -47,6 +67,9 @@ class ParametricOrbital : Extension {
@DoubleParameter("orbit radius", 0.1, 100.0, order = 3) @DoubleParameter("orbit radius", 0.1, 100.0, order = 3)
var radius = 10.0 var radius = 10.0
set(value) { set(value) {
if (field != value) {
dirty = true
}
field = value field = value
camera.dollyTo(radius) camera.dollyTo(radius)
} }
@@ -55,6 +78,9 @@ class ParametricOrbital : Extension {
@Vector3Parameter("center", order = 4) @Vector3Parameter("center", order = 4)
var center = Vector3.ZERO var center = Vector3.ZERO
set(value) { set(value) {
if (field != value) {
dirty = true
}
field = value field = value
camera.panTo(value) camera.panTo(value)
} }
@@ -72,6 +98,7 @@ class ParametricOrbital : Extension {
} }
override fun afterDraw(drawer: Drawer, program: Program) { override fun afterDraw(drawer: Drawer, program: Program) {
dirty = false
camera.afterDraw(drawer, program) camera.afterDraw(drawer, program)
} }
} }