From 8700f1b32f812104200e2c9041f35f501e0b67fa Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Fri, 18 Sep 2026 12:46:58 +0530 Subject: Faces stuff + simple camera rotation --- src/main/kotlin/faces/FacesProgram.kt | 50 ++++++++++++++++++++ src/main/kotlin/phenax/extensions/CameraManager.kt | 54 +++++++++++++++++----- 2 files changed, 92 insertions(+), 12 deletions(-) create mode 100644 src/main/kotlin/faces/FacesProgram.kt (limited to 'src/main/kotlin') diff --git a/src/main/kotlin/faces/FacesProgram.kt b/src/main/kotlin/faces/FacesProgram.kt new file mode 100644 index 0000000..b76f607 --- /dev/null +++ b/src/main/kotlin/faces/FacesProgram.kt @@ -0,0 +1,50 @@ +package faces + +import org.openrndr.application +import org.openrndr.color.* +import org.openrndr.draw.* +import org.openrndr.extra.noise.filters.SimplexNoise3D +import org.openrndr.math.IntVector2 +import org.openrndr.math.Vector3 +import phenax.extensions.CameraManager +import phenax.utils.* + +fun main() = application { + recordDuration(5.seconds()) + + configure { + width = 640 + height = 480 + windowResizable = false + position = IntVector2(0, 0) + } + + oliveProgram { + val cs by liveComputeShader("faces") + + val outputBuffer = colorBuffer(width, height, type = ColorType.UINT8) + + val size = Math.max(width, height) * 2 + val noiseBuffer = colorBuffer(size, size, type = ColorType.UINT8) + val noiseFilter = SimplexNoise3D() + noiseFilter.scale = Vector3.ONE * 2.4 + noiseFilter.octaves = 8 + noiseFilter.premultipliedAlpha = true + + val cameraManager = CameraManager(Vector3(1.0, 1.0, -1.0), Vector3(30.0, 0.0, 0.0)) + cameraManager.lightPosition = Vector3(6.0, 8.0, -8.0) + extend(cameraManager) + + extend { + noiseFilter.seed = Vector3(0.01, 0.01, 0.001) + noiseFilter.apply(emptyArray(), noiseBuffer) + cs.image("noise_texture", 1, noiseBuffer.imageBinding(0, ImageAccess.READ)) + + cs.uniform("seconds", seconds) + cs.image("output_image", 0, outputBuffer.imageBinding(0, ImageAccess.WRITE)) + cameraManager.setUniforms(cs) + cs.execute(outputBuffer.width, outputBuffer.height, 1) + drawer.image(outputBuffer) + } + } +} diff --git a/src/main/kotlin/phenax/extensions/CameraManager.kt b/src/main/kotlin/phenax/extensions/CameraManager.kt index ab2403c..0303a54 100644 --- a/src/main/kotlin/phenax/extensions/CameraManager.kt +++ b/src/main/kotlin/phenax/extensions/CameraManager.kt @@ -1,55 +1,79 @@ package phenax.extensions +import kotlin.math.absoluteValue import org.openrndr.* import org.openrndr.color.* import org.openrndr.draw.* +import org.openrndr.math.Quaternion +import org.openrndr.math.Vector2 import org.openrndr.math.Vector3 import phenax.utils.recordingEnabled enum class ActionType { PAN, - LIGHT_MOVE + ROTATE } -class CameraManager : Extension { +class CameraManager(public var cameraPosition: Vector3, public var cameraRotation: Vector3) : + Extension { override var enabled: Boolean = true - public var cameraPosition: Vector3 = Vector3(0.0, 1.0, 0.0) + public var cameraQuaternion: Quaternion = Quaternion.IDENTITY public var lightPosition: Vector3 = Vector3(1.0, 2.0, 1.0) var font: FontImageMap? = null var actionType: ActionType? = null var lastPos: Vector3? = null + constructor() : this(Vector3(0.0, 1.0, 0.0), Vector3.ZERO) {} + override fun setup(program: Program) { if (recordingEnabled) return + cameraQuaternion = Quaternion.fromAngles(cameraRotation.x, cameraRotation.y, cameraRotation.z) + font = program.loadFont("data/fonts/default.otf", 16.0) - program.keyboard.keyDown.listen { if (it.key == KEY_ESCAPE) program.application.exit() } + program.keyboard.keyDown.listen { + when (it.name) { + "escape" -> program.application.exit() + "x" -> cameraQuaternion = Quaternion.IDENTITY + "y" -> cameraQuaternion = Quaternion.fromAngles(0.0, -90.0, 0.0) + "z" -> cameraQuaternion = Quaternion.fromAngles(90.0, 0.0, 0.0) + } + } program.mouse.moved.listen { val dimens = Vector3(program.width.toDouble(), program.height.toDouble(), 1.0) - val pos = (Vector3(it.position.x, -it.position.y, 0.0) - dimens / 2.0).div(dimens) + var pos = (Vector3(it.position.x, -it.position.y, 0.0) - dimens / 2.0).div(dimens) + pos = cameraQuaternion.inversed.matrix * pos + val increment = lastPos?.let { pos - it } if (actionType == ActionType.PAN) { - lastPos?.let { lastPos -> cameraPosition -= (pos - lastPos) } - } else if (actionType == ActionType.LIGHT_MOVE) { - lastPos?.let { lastPos -> lightPosition += (pos - lastPos) } + increment?.let { cameraPosition -= it } + } else if (actionType == ActionType.ROTATE) { + increment?.let { + val mag = 10.0 + val rot = + if (it.x.absoluteValue >= it.y.absoluteValue) Vector2(it.x * mag, 0.0) + else Vector2(0.0, it.y * mag) + cameraQuaternion *= Quaternion.fromAngles(rot.x, rot.y, 0.0) + } + // lastPos?.let { lastPos -> lightPosition += (pos - lastPos) } } actionType?.let { lastPos = pos } } program.mouse.buttonDown.listen { val isCtrl = KeyModifier.CTRL in it.modifiers - actionType = if (isCtrl) ActionType.LIGHT_MOVE else ActionType.PAN + actionType = if (isCtrl) ActionType.ROTATE else ActionType.PAN } program.mouse.scrolled.listen { val isCtrl = KeyModifier.CTRL in it.modifiers if (isCtrl) { - lightPosition += Vector3(0.0, 0.0, it.rotation.y * 0.1) + cameraQuaternion *= Quaternion.fromAngles(it.rotation.y, 0.0, 0.0) } else { - cameraPosition += Vector3(0.0, 0.0, it.rotation.y * 0.1) + cameraPosition += cameraQuaternion.inversed.matrix * Vector3(0.0, 0.0, it.rotation.y * 0.1) } } @@ -61,7 +85,8 @@ class CameraManager : Extension { fun setUniforms(cs: ComputeShader) { cs.uniform("camera_position", cameraPosition) - cs.uniform("primary_light_position", lightPosition) + cs.uniform("camera_transformation", cameraQuaternion.matrix) + cs.uniform("key_light_position", lightPosition) } override fun beforeDraw(drawer: Drawer, program: Program) {} @@ -81,5 +106,10 @@ class CameraManager : Extension { 8.0, 32.0 ) + drawer.text( + "L: %.2f %.2f %.2f".format(lightPosition.x, lightPosition.y, lightPosition.z), + 8.0, + 32.0 + ) } } -- cgit v1.3.1