From fd43ea484303bd50d10b5e3c24e1796b18294373 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 15 Dec 2019 10:56:44 +0300 Subject: [PATCH] FX backend in progress --- .../SpatialDemoApp.kt} | 23 +++++++------- .../hep/dataforge/vis/spatial/fx/Canvas3D.kt | 31 ++++++++++++------- .../dataforge/vis/spatial/fx/FX3DPlugin.kt | 2 +- .../fx/{Materials.kt => FXMaterials.kt} | 15 +++++---- .../vis/spatial/fx/FXShapeFactory.kt | 9 +++--- 5 files changed, 46 insertions(+), 34 deletions(-) rename dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/{fx/RendererDemoApp.kt => demo/SpatialDemoApp.kt} (67%) rename dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/{Materials.kt => FXMaterials.kt} (82%) diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/RendererDemoApp.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/demo/SpatialDemoApp.kt similarity index 67% rename from dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/RendererDemoApp.kt rename to dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/demo/SpatialDemoApp.kt index 1349280c..0a9fc4b7 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/RendererDemoApp.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/demo/SpatialDemoApp.kt @@ -1,8 +1,10 @@ -package hep.dataforge.vis.spatial.fx +package hep.dataforge.vis.spatial.demo import hep.dataforge.context.Global import hep.dataforge.meta.number import hep.dataforge.vis.spatial.* +import hep.dataforge.vis.spatial.fx.Canvas3D +import hep.dataforge.vis.spatial.fx.FX3DPlugin import javafx.scene.Parent import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay @@ -11,22 +13,21 @@ import kotlinx.coroutines.launch import tornadofx.* import kotlin.random.Random +class SpatialDemoApp: App(SpatialDemoView::class) -class RendererDemoApp : App(RendererDemoView::class) +class SpatialDemoView: View(){ + private val plugin = Global.plugins.fetch(FX3DPlugin) + private val canvas = Canvas3D(plugin) - -class RendererDemoView : View() { - val plugin = Global.plugins.fetch(FX3DPlugin) - val renderer = Canvas3D(plugin) override val root: Parent = borderpane { - center = renderer.root + center = canvas.root } lateinit var group: VisualGroup3D init { - - renderer.render { + canvas.render { + box(100,100,100) group = group { box(100,100,100) box(100,100,100) { @@ -45,7 +46,7 @@ class RendererDemoView : View() { } } - renderer.apply { + canvas.apply { angleY = -30.0 angleX = -15.0 } @@ -54,5 +55,5 @@ class RendererDemoView : View() { fun main() { - launch() + launch() } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/Canvas3D.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/Canvas3D.kt index bf95d931..fd6cbc40 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/Canvas3D.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/Canvas3D.kt @@ -19,13 +19,21 @@ import javafx.scene.input.KeyEvent import javafx.scene.input.MouseEvent import javafx.scene.input.ScrollEvent import javafx.scene.paint.Color +import org.fxyz3d.scene.Axes +import org.fxyz3d.scene.CubeWorld import org.fxyz3d.utils.CameraTransformer import tornadofx.* -class Canvas3D(val plugin: FX3DPlugin, val meta: Meta = EmptyMeta) : Fragment(), Renderer, ContextAware { +class Canvas3D(val plugin: FX3DPlugin, meta: Meta = EmptyMeta) : + Fragment(), Renderer, ContextAware { override val context: Context get() = plugin.context - val world: Group = Group() + val world = CubeWorld(true) + val axes = Axes().also { + it.setHeight(AXIS_LENGTH) + it.setRadius(LINE_WIDTH) + world.add(it) + } private val camera = PerspectiveCamera().apply { nearClip = CAMERA_NEAR_CLIP @@ -69,12 +77,12 @@ class Canvas3D(val plugin: FX3DPlugin, val meta: Meta = EmptyMeta) : Fragment(), 768.0, true, SceneAntialiasing.BALANCED - ).apply { - fill = Color.GREY - this.camera = this@Canvas3D.camera + ).also {scene-> + scene.fill = Color.GREY + scene.camera = camera id = "canvas" - handleKeyboard(this) - handleMouse(this) + handleKeyboard(scene) + handleMouse(scene) } } @@ -90,7 +98,7 @@ class Canvas3D(val plugin: FX3DPlugin, val meta: Meta = EmptyMeta) : Fragment(), cameraRotation.ry.angle = CAMERA_INITIAL_Y_ANGLE cameraRotation.rx.angle = CAMERA_INITIAL_X_ANGLE } -// KeyCode.X -> axisGroup.isVisible = !axisGroup.isVisible + KeyCode.X -> axes.isVisible = !axes.isVisible // KeyCode.S -> snapshot() // KeyCode.DIGIT1 -> pixelMap.filterKeys { it.getLayerNumber() == 1 }.values.forEach { // toggleTransparency( @@ -145,8 +153,8 @@ class Canvas3D(val plugin: FX3DPlugin, val meta: Meta = EmptyMeta) : Fragment(), } if (me.isPrimaryButtonDown) { - cameraRotation.rz.angle = - cameraRotation.rz.angle + mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED + cameraRotation.ry.angle = + cameraRotation.ry.angle + mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED cameraRotation.rx.angle = cameraRotation.rx.angle + mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED } else if (me.isSecondaryButtonDown) { @@ -162,7 +170,8 @@ class Canvas3D(val plugin: FX3DPlugin, val meta: Meta = EmptyMeta) : Fragment(), } override fun render(obj: VisualObject3D, meta: Meta) { - plugin.buildNode(obj)?.let { world.children.add(it) } + val node = plugin.buildNode(obj) ?: kotlin.error("Can't render FX node for object $obj") + world.add(node) } companion object { diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt index 4e28730a..1a1aa430 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt @@ -84,7 +84,7 @@ class FX3DPlugin : AbstractPlugin() { } if (this is Shape3D) { - materialProperty().bind(binding["color"].transform { it.material() }) + materialProperty().bind(binding[Material3D.MATERIAL_KEY].transform { it.material() }) } } } diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/Materials.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXMaterials.kt similarity index 82% rename from dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/Materials.kt rename to dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXMaterials.kt index 626a3594..174c3559 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/Materials.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXMaterials.kt @@ -9,7 +9,7 @@ import javafx.scene.paint.Color import javafx.scene.paint.Material import javafx.scene.paint.PhongMaterial -object Materials { +object FXMaterials { val RED = PhongMaterial().apply { diffuseColor = Color.DARKRED specularColor = Color.RED @@ -30,8 +30,9 @@ object Materials { /** * Infer color based on meta item + * @param opacity default opacity */ -fun MetaItem<*>.color(): Color { +fun MetaItem<*>.color(opacity: Double = 1.0): Color { return when (this) { is MetaItem.ValueItem -> if (this.value.type == ValueType.STRING) { Color.web(this.value.string) @@ -47,7 +48,7 @@ fun MetaItem<*>.color(): Color { node["red"]?.int ?: 0, node["green"]?.int ?: 0, node["blue"]?.int ?: 0, - node["opacity"]?.double ?: 1.0 + node["opacity"]?.double ?: opacity ) } } @@ -58,11 +59,13 @@ fun MetaItem<*>.color(): Color { */ fun MetaItem<*>?.material(): Material { return when (this) { - null -> Materials.GREY + null -> FXMaterials.GREY is MetaItem.ValueItem -> PhongMaterial(color()) is MetaItem.NodeItem -> PhongMaterial().apply { - (node["color"]?: this@material).let { diffuseColor = it.color() } - node["specularColor"]?.let { specularColor = it.color() } + val opacity = node["opacity"].double ?: 1.0 + (node["color"] ?: this@material).let { diffuseColor = it.color(opacity) } + node["specularColor"]?.let { specularColor = it.color(opacity) } + } } } diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXShapeFactory.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXShapeFactory.kt index eb3f6925..93868b54 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXShapeFactory.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXShapeFactory.kt @@ -7,6 +7,7 @@ import hep.dataforge.vis.spatial.Shape import javafx.scene.shape.Mesh import javafx.scene.shape.MeshView import javafx.scene.shape.TriangleMesh +import org.fxyz3d.geometry.Face3 import kotlin.reflect.KClass object FXShapeFactory : FX3DFactory { @@ -18,11 +19,9 @@ object FXShapeFactory : FX3DFactory { } } -private typealias Face = IntArray - private class FXGeometryBuilder : GeometryBuilder { val vertices = ArrayList() - val faces = ArrayList() + val faces = ArrayList() private val vertexCache = HashMap() private fun append(vertex: Point3D): Int { @@ -38,7 +37,7 @@ private class FXGeometryBuilder : GeometryBuilder { override fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D?, meta: Meta) { //adding vertices - val face: Face = intArrayOf(append(vertex1), append(vertex2), append(vertex3)) + val face = Face3(append(vertex1), append(vertex2), append(vertex3)) faces.add(face) } @@ -49,7 +48,7 @@ private class FXGeometryBuilder : GeometryBuilder { mesh.points.addAll(it.x.toFloat(), it.y.toFloat(), it.z.toFloat()) } faces.forEach { - mesh.faces.addAll(it[0], it[1], it[2]) + mesh.faces.addAll(it.p0, it.p1, it.p2) } return mesh }