From 158af5fb3be07d8ff18831718560a57faeb9f22c Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Tue, 26 May 2020 19:29:08 +0200 Subject: [PATCH] Add support for cameras --- orx-dnk3/src/demo/kotlin/DemoCamera01.kt | 50 ++++++++++++++++++++++ orx-dnk3/src/main/kotlin/Camera.kt | 32 ++++++++++++++ orx-dnk3/src/main/kotlin/Entity.kt | 4 ++ orx-dnk3/src/main/kotlin/gltf/Gltf.kt | 11 ++++- orx-dnk3/src/main/kotlin/gltf/GltfScene.kt | 27 ++++++++++++ 5 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 orx-dnk3/src/demo/kotlin/DemoCamera01.kt create mode 100644 orx-dnk3/src/main/kotlin/Camera.kt diff --git a/orx-dnk3/src/demo/kotlin/DemoCamera01.kt b/orx-dnk3/src/demo/kotlin/DemoCamera01.kt new file mode 100644 index 00000000..dcba32b7 --- /dev/null +++ b/orx-dnk3/src/demo/kotlin/DemoCamera01.kt @@ -0,0 +1,50 @@ +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.extensions.SingleScreenshot +import org.openrndr.extra.dnk3.* +import org.openrndr.extra.dnk3.gltf.buildSceneNodes +import org.openrndr.extra.dnk3.gltf.loadGltfFromFile +import org.openrndr.extras.camera.Orbital +import org.openrndr.math.* +import org.openrndr.math.transforms.transform +import java.io.File + +fun main() = application { + configure { + width = 1280 + height = 720 + //multisample = WindowMultisample.SampleCount(8) + } + + program { + if (System.getProperty("takeScreenshot") == "true") { + extend(SingleScreenshot()) { + this.outputFile = System.getProperty("screenshotPath") + } + } + + val gltf = loadGltfFromFile(File("demo-data/gltf-models/camera/Scene.glb")) + val scene = Scene(SceneNode()) + + scene.root.entities.add(HemisphereLight().apply { + upColor = ColorRGBa(0.1, 0.1, 0.4) + downColor = ColorRGBa(0.1, 0.0, 0.0) + }) + + val sceneData = gltf.buildSceneNodes() + scene.root.children.addAll(sceneData.scenes.first()) + + // -- create a renderer + val renderer = dryRenderer() + + val cameras = scene.root.findContent { this as? PerspectiveCamera } + + extend { + sceneData.animations[0].applyToTargets(seconds.mod_(sceneData.animations[0].duration)) + drawer.view = cameras[0].content.viewMatrix + drawer.projection = cameras[0].content.projectionMatrix + drawer.clear(ColorRGBa.PINK) + renderer.draw(drawer, scene) + } + } +} \ No newline at end of file diff --git a/orx-dnk3/src/main/kotlin/Camera.kt b/orx-dnk3/src/main/kotlin/Camera.kt new file mode 100644 index 00000000..b2785f4e --- /dev/null +++ b/orx-dnk3/src/main/kotlin/Camera.kt @@ -0,0 +1,32 @@ +package org.openrndr.extra.dnk3 + +import org.openrndr.math.Matrix44 +import org.openrndr.math.transforms.ortho +import org.openrndr.math.transforms.perspective + +class PerspectiveCamera(var node: SceneNode) : Camera() { + override val projectionMatrix: Matrix44 + get() = perspective(fov, aspectRatio, near, far) + + override val viewMatrix: Matrix44 + get() = node.worldTransform.inversed + + var aspectRatio: Double = 16.0 / 9.0 + var fov = 45.0 + var far = 100.0 + var near = 0.1 + +} + +class OrthographicCamera(var node: SceneNode) : Camera() { + override val projectionMatrix: Matrix44 + get() = ortho(xMag, yMag, near, far) + + override val viewMatrix: Matrix44 + get() = node.worldTransform.inversed + + var xMag = 1.0 + var yMag = 1.0 + var near = 0.1 + var far = 100.0 +} \ No newline at end of file diff --git a/orx-dnk3/src/main/kotlin/Entity.kt b/orx-dnk3/src/main/kotlin/Entity.kt index 11cdbecd..a5335b99 100644 --- a/orx-dnk3/src/main/kotlin/Entity.kt +++ b/orx-dnk3/src/main/kotlin/Entity.kt @@ -58,3 +58,7 @@ abstract class Light : Entity() { var color: ColorRGBa = ColorRGBa.WHITE } +abstract class Camera : Entity() { + abstract val projectionMatrix: Matrix44 + abstract val viewMatrix: Matrix44 +} \ No newline at end of file diff --git a/orx-dnk3/src/main/kotlin/gltf/Gltf.kt b/orx-dnk3/src/main/kotlin/gltf/Gltf.kt index ea96873b..3697e04b 100644 --- a/orx-dnk3/src/main/kotlin/gltf/Gltf.kt +++ b/orx-dnk3/src/main/kotlin/gltf/Gltf.kt @@ -28,7 +28,7 @@ class GltfAsset(val generator: String?, val version: String?) class GltfScene(val nodes: IntArray) -class GltfNode(val name:String, +class GltfNode(val name: String, val children: IntArray?, val matrix: DoubleArray?, val scale: DoubleArray?, @@ -36,6 +36,7 @@ class GltfNode(val name:String, val translation: DoubleArray?, val mesh: Int?, val skin: Int?, + val camera: Int?, val extensions: GltfNodeExtensions?) class KHRLightsPunctualIndex(val light: Int) @@ -260,6 +261,11 @@ class KHRLightsPunctual(val lights: List) class GltfExtensions(val KHR_lights_punctual: KHRLightsPunctual?) +class GltfCameraPerspective(val aspectRatio: Double?, val yfov: Double, val zfar: Double?, val znear: Double) +class GltfCameraOrthographic(val xmag: Double, val ymag: Double, val zfar: Double, val znear: Double) + +class GltfCamera(val name: String?, val type: String, val perspective: GltfCameraPerspective?, val orthographic: GltfCameraOrthographic?) + class GltfFile( val asset: GltfAsset?, val scene: Int?, @@ -275,7 +281,8 @@ class GltfFile( val samplers: List?, val animations: List?, val skins: List?, - val extensions: GltfExtensions? + val extensions: GltfExtensions?, + val cameras: List? ) { @Transient lateinit var file: File diff --git a/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt b/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt index c76392fa..aa7a6c4d 100644 --- a/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt +++ b/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt @@ -259,6 +259,28 @@ fun GltfFile.buildSceneNodes(): GltfSceneData { } } + fun GltfCamera.createSceneCamera(sceneNode: SceneNode): Camera { + return when (type) { + "perspective" -> { + PerspectiveCamera(sceneNode).apply { + aspectRatio = perspective?.aspectRatio ?: aspectRatio + far = perspective?.zfar ?: far + near = perspective?.znear ?: near + fov = perspective?.yfov?.let { Math.toDegrees(it) } ?: fov + } + } + "orthographic" -> { + OrthographicCamera(sceneNode).apply { + xMag = orthographic?.xmag ?: xMag + yMag = orthographic?.ymag ?: yMag + near = orthographic?.znear ?: near + far = orthographic?.zfar ?: far + } + } + else -> error("unsupported camera type: $type") + } + } + val scenes = scenes.map { scene -> scene.nodes.map { node -> val gltfNode = nodes[node] @@ -271,6 +293,11 @@ fun GltfFile.buildSceneNodes(): GltfSceneData { val skin = gltfNode.skin?.let { (skins!!)[it] } sceneNode.entities.add(meshes[it].createSceneMesh(skin)) } + + gltfNode.camera?.let { + sceneNode.entities.add(cameras!![it].createSceneCamera(sceneNode)) + } + gltfNode.extensions?.let { exts -> exts.KHR_lights_punctual?.let { lightIndex -> extensions?.KHR_lights_punctual?.lights?.get(lightIndex.light)?.let { light ->