From cef1a1ee6d56f12a83485ac5feb3d6ff464c9a02 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 14 Dec 2019 21:45:41 +0300 Subject: [PATCH] FX backend in progress --- dataforge-vis-common/build.gradle.kts | 3 +- .../hep/dataforge/vis/common/VisualObject.kt | 9 +- dataforge-vis-spatial/build.gradle.kts | 3 +- .../kotlin/hep/dataforge/vis/spatial/Box.kt | 3 - .../hep/dataforge/vis/spatial/Composite.kt | 4 - .../hep/dataforge/vis/spatial/ConeSegment.kt | 49 +++++++- .../hep/dataforge/vis/spatial/Convex.kt | 4 - .../hep/dataforge/vis/spatial/Extruded.kt | 4 - .../hep/dataforge/vis/spatial/PolyLine.kt | 3 - .../kotlin/hep/dataforge/vis/spatial/Proxy.kt | 5 - .../hep/dataforge/vis/spatial/Sphere.kt | 8 +- .../hep/dataforge/vis/spatial/Text3D.kt | 23 ++++ .../kotlin/hep/dataforge/vis/spatial/Tube.kt | 3 - .../dataforge/vis/spatial/VisualGroup3D.kt | 3 - .../hep/dataforge/vis/spatial/ConvexTest.kt | 13 +- .../vis/spatial/SerializationTest.kt | 10 +- .../vis/spatial/editor/outputConfig.kt | 8 +- .../three/{ThreeOutput.kt => ThreeCanvas.kt} | 4 +- .../vis/spatial/three/ThreeFactory.kt | 22 ++-- .../vis/spatial/three/ThreePlugin.kt | 12 +- .../vis/spatial/three/ThreeVisualObject.kt | 5 - .../hep/dataforge/vis/spatial/fx/Canvas3D.kt | 14 ++- ...XListener.kt => DisplayObjectFXBinding.kt} | 2 +- .../dataforge/vis/spatial/fx/FX3DOutput.kt | 50 -------- .../dataforge/vis/spatial/fx/FX3DPlugin.kt | 113 ++++++++++++++++++ .../vis/spatial/fx/FXCompositeFactory.kt | 38 ++++++ .../vis/spatial/fx/FXConvexFactory.kt | 19 +++ .../vis/spatial/fx/FXProxyFactory.kt | 15 +++ .../vis/spatial/fx/FXShapeFactory.kt | 58 +++++++++ .../vis/spatial/fx/RendererDemoApp.kt | 7 +- .../hep/dataforge/vis/spatial/geometryJVM.kt | 28 ++++- .../vis/spatial/demo/ThreeDemoGrid.kt | 10 +- 32 files changed, 406 insertions(+), 146 deletions(-) create mode 100644 dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Text3D.kt rename dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/{ThreeOutput.kt => ThreeCanvas.kt} (95%) rename dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/{DisplayObjectFXListener.kt => DisplayObjectFXBinding.kt} (96%) delete mode 100644 dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DOutput.kt create mode 100644 dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt create mode 100644 dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCompositeFactory.kt create mode 100644 dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXConvexFactory.kt create mode 100644 dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXProxyFactory.kt create mode 100644 dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXShapeFactory.kt diff --git a/dataforge-vis-common/build.gradle.kts b/dataforge-vis-common/build.gradle.kts index aff8d7a0..e6fb3815 100644 --- a/dataforge-vis-common/build.gradle.kts +++ b/dataforge-vis-common/build.gradle.kts @@ -32,8 +32,7 @@ kotlin { jsMain{ dependencies { api("hep.dataforge:dataforge-output-html:$dataforgeVersion") - api("kotlin.js.externals:kotlin-js-jquery:3.2.0-0") - api(npm("bootstrap","4.3.1")) + api(npm("bootstrap","4.4.1")) } } } diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt index 5d54a98a..23d46683 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt @@ -1,6 +1,9 @@ package hep.dataforge.vis.common -import hep.dataforge.meta.* +import hep.dataforge.meta.Config +import hep.dataforge.meta.Configurable +import hep.dataforge.meta.Laminate +import hep.dataforge.meta.MetaItem import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.toName @@ -15,7 +18,7 @@ import kotlinx.serialization.Transient * A root type for display hierarchy */ @Type(TYPE) -interface VisualObject : MetaRepr, Configurable { +interface VisualObject : Configurable { /** * The parent object of this one. If null, this one is a root. @@ -54,7 +57,7 @@ interface VisualObject : MetaRepr, Configurable { fun removeChangeListener(owner: Any?) /** - * List of names of styles applied to this object + * List of names of styles applied to this object. Order matters. */ var styles: List diff --git a/dataforge-vis-spatial/build.gradle.kts b/dataforge-vis-spatial/build.gradle.kts index 1d562140..67352978 100644 --- a/dataforge-vis-spatial/build.gradle.kts +++ b/dataforge-vis-spatial/build.gradle.kts @@ -21,7 +21,8 @@ kotlin { } jvmMain { dependencies { - implementation("org.fxyz3d:fxyz3d:0.5.2") + api("org.fxyz3d:fxyz3d:0.5.2") + implementation("eu.mihosoft.vrl.jcsg:jcsg:0.5.7") } } jsMain { diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt index 571a1ff8..550430f3 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt @@ -3,7 +3,6 @@ package hep.dataforge.vis.spatial import hep.dataforge.context.Context import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config import hep.dataforge.meta.Meta import hep.dataforge.meta.float @@ -50,8 +49,6 @@ class Box( geometryBuilder.face4(node8, node5, node6, node7) } - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() - companion object : VisualFactory { const val TYPE = "geometry.3d.box" diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt index 4e920800..e0ac521b 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt @@ -2,9 +2,7 @@ package hep.dataforge.vis.spatial import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config -import hep.dataforge.meta.Meta import hep.dataforge.meta.update import hep.dataforge.vis.common.AbstractVisualObject import kotlinx.serialization.Serializable @@ -34,8 +32,6 @@ class Composite( @Serializable(ConfigSerializer::class) override var properties: Config? = null - - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() } inline fun VisualGroup3D.composite( diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt index b1533a83..9aa090ef 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt @@ -3,12 +3,12 @@ package hep.dataforge.vis.spatial import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config -import hep.dataforge.meta.Meta import hep.dataforge.vis.common.AbstractVisualObject import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers +import kotlin.math.cos +import kotlin.math.sin /** * A cylinder or cut cone segment @@ -20,7 +20,7 @@ class ConeSegment( var upperRadius: Float, var startAngle: Float = 0f, var angle: Float = PI2 -) : AbstractVisualObject(), VisualObject3D { +) : AbstractVisualObject(), VisualObject3D, Shape { @Serializable(ConfigSerializer::class) override var properties: Config? = null @@ -29,7 +29,48 @@ class ConeSegment( override var rotation: Point3D? = null override var scale: Point3D? = null - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() + override fun toGeometry(geometryBuilder: GeometryBuilder) { + val segments = detail ?: 8 + require(segments >= 4) { "The number of segments in cone segment is too small" } + val angleStep = angle / (segments - 1) + + fun shape(r: Float, z: Float): List { + return (0 until segments).map { i -> + Point3D(r * cos(startAngle + angleStep * i), r * sin(startAngle + angleStep * i), z) + } + } + + geometryBuilder.apply { + + //creating shape in x-y plane with z = 0 + val bottomOuterPoints = shape(upperRadius, -height / 2) + val upperOuterPoints = shape(radius, height / 2) + //outer face + (1 until segments).forEach { + face4(bottomOuterPoints[it - 1], bottomOuterPoints[it], upperOuterPoints[it], upperOuterPoints[it - 1]) + } + + if (angle == PI2) { + face4(bottomOuterPoints.last(), bottomOuterPoints[0], upperOuterPoints[0], upperOuterPoints.last()) + } + + val zeroBottom = Point3D(0f, 0f, 0f) + val zeroTop = Point3D(0f, 0f, height) + (1 until segments).forEach { + face(bottomOuterPoints[it - 1], zeroBottom, bottomOuterPoints[it]) + face(upperOuterPoints[it - 1], upperOuterPoints[it], zeroTop) + } + if (angle == PI2) { + face(bottomOuterPoints.last(), zeroBottom, bottomOuterPoints[0]) + face(upperOuterPoints.last(), upperOuterPoints[0], zeroTop) + } else { + face4(zeroTop, zeroBottom, bottomOuterPoints[0], upperOuterPoints[0]) + face4(zeroTop, zeroBottom, bottomOuterPoints.last(), upperOuterPoints.last()) + } + + } + } + } inline fun VisualGroup3D.cylinder( diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt index 3d9f03d5..1ca46886 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt @@ -3,9 +3,7 @@ package hep.dataforge.vis.spatial import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config -import hep.dataforge.meta.Meta import hep.dataforge.vis.common.AbstractVisualObject import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -20,8 +18,6 @@ class Convex(val points: List) : AbstractVisualObject(), VisualObject3D override var rotation: Point3D? = null override var scale: Point3D? = null - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() - companion object { const val TYPE = "geometry.3d.convex" } diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt index c0bb0fb1..7255b7ef 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt @@ -2,9 +2,7 @@ package hep.dataforge.vis.spatial import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config -import hep.dataforge.meta.Meta import hep.dataforge.vis.common.AbstractVisualObject import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -107,8 +105,6 @@ class Extruded( geometryBuilder.cap(layers.last()) } - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() - companion object { const val TYPE = "geometry.3d.extruded" } diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/PolyLine.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/PolyLine.kt index 001c1e40..75d00ab4 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/PolyLine.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/PolyLine.kt @@ -3,9 +3,7 @@ package hep.dataforge.vis.spatial import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config -import hep.dataforge.meta.Meta import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.common.number import kotlinx.serialization.Serializable @@ -23,7 +21,6 @@ class PolyLine(var points: List) : AbstractVisualObject(), VisualObject //var lineType by string() var thickness by number(1.0, key = "material.thickness") - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() } fun VisualGroup3D.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}) = diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Proxy.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Proxy.kt index e5ea3be6..e71186c7 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Proxy.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Proxy.kt @@ -4,7 +4,6 @@ package hep.dataforge.vis.spatial import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.io.serialization.NameSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaItem @@ -64,8 +63,6 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua } } - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() - override val children: Map get() = (prototype as? MutableVisualGroup)?.children ?.filter { !it.key.toString().startsWith("@") } @@ -144,8 +141,6 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua } } - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() - } companion object { diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt index 1b210c75..f762a48a 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt @@ -3,9 +3,7 @@ package hep.dataforge.vis.spatial import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config -import hep.dataforge.meta.Meta import hep.dataforge.vis.common.AbstractVisualObject import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -18,7 +16,7 @@ class Sphere( var phi: Float = PI2, var thetaStart: Float = 0f, var theta: Float = PI.toFloat() -) : AbstractVisualObject(), VisualObject3D { +) : AbstractVisualObject(), VisualObject3D, Shape { @Serializable(ConfigSerializer::class) override var properties: Config? = null @@ -27,7 +25,9 @@ class Sphere( override var rotation: Point3D? = null override var scale: Point3D? = null - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() + override fun toGeometry(geometryBuilder: GeometryBuilder) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } } inline fun VisualGroup3D.sphere( diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Text3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Text3D.kt new file mode 100644 index 00000000..2fbecf1d --- /dev/null +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Text3D.kt @@ -0,0 +1,23 @@ +@file:UseSerializers(Point3DSerializer::class) + +package hep.dataforge.vis.spatial + +import hep.dataforge.io.serialization.ConfigSerializer +import hep.dataforge.meta.Config +import hep.dataforge.vis.common.AbstractVisualObject +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers + +@Serializable +class Text3D(var text: String, var fontSize: Int) : AbstractVisualObject(), VisualObject3D { + @Serializable(ConfigSerializer::class) + override var properties: Config? = null + + override var position: Point3D? = null + override var rotation: Point3D? = null + override var scale: Point3D? = null + +} + +fun VisualGroup3D.text(text: String, fontSize: Int, name: String = "", action: Text3D.() -> Unit = {}) = + Text3D(text, fontSize).apply(action).also { set(name, it) } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Tube.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Tube.kt index ccf6a62f..248fbfce 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Tube.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Tube.kt @@ -2,9 +2,7 @@ package hep.dataforge.vis.spatial import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config -import hep.dataforge.meta.Meta import hep.dataforge.vis.common.AbstractVisualObject import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -126,7 +124,6 @@ class Tube( } } - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() } inline fun VisualGroup3D.tube( diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt index 071623b7..9c959e73 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt @@ -11,7 +11,6 @@ package hep.dataforge.vis.spatial import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.io.serialization.MetaSerializer import hep.dataforge.io.serialization.NameSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config import hep.dataforge.meta.Meta import hep.dataforge.names.Name @@ -97,8 +96,6 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D { } } - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() - companion object { const val PROTOTYPES_KEY = "templates" } diff --git a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt index 40cb4404..3358fe84 100644 --- a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt +++ b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt @@ -1,8 +1,8 @@ package hep.dataforge.vis.spatial -import hep.dataforge.meta.get +import hep.dataforge.io.toMeta +import hep.dataforge.meta.MetaItem import hep.dataforge.meta.getIndexed -import hep.dataforge.meta.node import kotlin.test.Test import kotlin.test.assertEquals @@ -25,12 +25,11 @@ class ConvexTest { val convex = group.first() as Convex - val meta = convex.toMeta() + val json = Visual3DPlugin.json.toJson(Convex.serializer(), convex) + val meta = json.toMeta() - val pointsNode = convex.toMeta()["points"].node - - assertEquals(8, pointsNode?.items?.count()) - val points = pointsNode?.getIndexed("points") + val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D()} + assertEquals(8, points.count()) assertEquals(8, convex.points.size) } diff --git a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/SerializationTest.kt b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/SerializationTest.kt index 958f98c3..128b507b 100644 --- a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/SerializationTest.kt +++ b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/SerializationTest.kt @@ -8,15 +8,15 @@ import kotlin.test.assertEquals class SerializationTest { @ImplicitReflectionSerializer @Test - fun testCubeSerialization(){ - val cube = Box(100f,100f,100f).apply{ + fun testCubeSerialization() { + val cube = Box(100f, 100f, 100f).apply { color(222) x = 100 z = -100 } - val string = json.stringify(Box.serializer(),cube) + val string = json.stringify(Box.serializer(), cube) println(string) - val newCube = json.parse(Box.serializer(),string) - assertEquals(cube.toMeta(),newCube.toMeta()) + val newCube = json.parse(Box.serializer(), string) + assertEquals(cube.config, newCube.config) } } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/editor/outputConfig.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/editor/outputConfig.kt index f667fc99..308a61bd 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/editor/outputConfig.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/editor/outputConfig.kt @@ -1,6 +1,6 @@ package hep.dataforge.vis.spatial.editor -import hep.dataforge.vis.spatial.three.ThreeOutput +import hep.dataforge.vis.spatial.three.ThreeCanvas import kotlinx.html.InputType import kotlinx.html.dom.append import kotlinx.html.js.div @@ -9,7 +9,7 @@ import kotlinx.html.js.label import org.w3c.dom.Element import kotlin.dom.clear -fun Element.threeOutputConfig(output: ThreeOutput) { +fun Element.threeOutputConfig(canvas: ThreeCanvas) { clear() append { card("Layers"){ @@ -23,9 +23,9 @@ fun Element.threeOutputConfig(output: ThreeOutput) { } onchange = { if (checked) { - output.camera.layers.enable(layer) + canvas.camera.layers.enable(layer) } else { - output.camera.layers.disable(layer) + canvas.camera.layers.disable(layer) } } } diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeOutput.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvas.kt similarity index 95% rename from dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeOutput.kt rename to dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvas.kt index 0ea8989f..a6f1d9be 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeOutput.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvas.kt @@ -19,7 +19,7 @@ import kotlin.browser.window import kotlin.dom.clear import kotlin.math.max -class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Renderer { +class ThreeCanvas(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Renderer { override val context: Context get() = three.context @@ -95,7 +95,7 @@ class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Renderer } fun ThreePlugin.output(element: HTMLElement? = null, meta: Meta = EmptyMeta, override: MetaBuilder.() -> Unit = {}) = - ThreeOutput(this, buildMeta(meta, override)).apply { + ThreeCanvas(this, buildMeta(meta, override)).apply { if (element != null) { attach(element) } diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt index bfd273c7..b3e76a20 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt @@ -38,17 +38,17 @@ fun Object3D.updatePosition(obj: VisualObject3D) { updateMatrix() } -/** - * Unsafe invocation of a factory - */ -operator fun ThreeFactory.invoke(obj: Any): Object3D { - if (type.isInstance(obj)) { - @Suppress("UNCHECKED_CAST") - return invoke(obj as T) - } else { - error("The object of type ${obj::class} could not be rendered by this factory") - } -} +///** +// * Unsafe invocation of a factory +// */ +//operator fun ThreeFactory.invoke(obj: Any): Object3D { +// if (type.isInstance(obj)) { +// @Suppress("UNCHECKED_CAST") +// return invoke(obj as T) +// } else { +// error("The object of type ${obj::class} could not be rendered by this factory") +// } +//} /** * Update non-position non-geometry property diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt index b3d6db64..ddcff805 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt @@ -16,7 +16,7 @@ import info.laht.threekt.objects.Group as ThreeGroup class ThreePlugin : AbstractPlugin() { override val tag: PluginTag get() = Companion.tag - private val objectFactories = HashMap, ThreeFactory<*>>() + private val objectFactories = HashMap, ThreeFactory<*>>() private val compositeFactory = ThreeCompositeFactory(this) private val proxyFactory = ThreeProxyFactory(this) @@ -29,9 +29,11 @@ class ThreePlugin : AbstractPlugin() { objectFactories[PolyLine::class] = ThreeLineFactory } - private fun findObjectFactory(type: KClass): ThreeFactory<*>? { - return objectFactories[type] - ?: context.content>(ThreeFactory.TYPE).values.find { it.type == type } + @Suppress("UNCHECKED_CAST") + private fun findObjectFactory(type: KClass): ThreeFactory? { + return (objectFactories[type] + ?: context.content>(ThreeFactory.TYPE).values.find { it.type == type }) + as ThreeFactory? } fun buildObject3D(obj: VisualObject3D): Object3D { @@ -73,7 +75,7 @@ class ThreePlugin : AbstractPlugin() { is Composite -> compositeFactory(obj) else -> { //find specialized factory for this type if it is present - val factory = findObjectFactory(obj::class) + val factory: ThreeFactory? = findObjectFactory(obj::class) when { factory != null -> factory(obj) obj is Shape -> ThreeShapeFactory(obj) diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeVisualObject.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeVisualObject.kt index 36095377..5970a76d 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeVisualObject.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeVisualObject.kt @@ -3,13 +3,10 @@ package hep.dataforge.vis.spatial.three import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.toMeta import hep.dataforge.meta.Config -import hep.dataforge.meta.Meta import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.spatial.Point3D import hep.dataforge.vis.spatial.Point3DSerializer -import hep.dataforge.vis.spatial.Visual3DPlugin import hep.dataforge.vis.spatial.VisualObject3D import info.laht.threekt.core.Object3D import kotlinx.serialization.Serializable @@ -32,8 +29,6 @@ class CustomThreeVisualObject(val threeFactory: ThreeFactory) : @Serializable(ConfigSerializer::class) override var properties: Config? = null - override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta() - override fun toObject3D(): Object3D = threeFactory(this) } \ 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 211c0d41..bf95d931 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 @@ -1,5 +1,11 @@ package hep.dataforge.vis.spatial.fx +import hep.dataforge.context.Context +import hep.dataforge.context.ContextAware +import hep.dataforge.meta.EmptyMeta +import hep.dataforge.meta.Meta +import hep.dataforge.output.Renderer +import hep.dataforge.vis.spatial.VisualObject3D import hep.dataforge.vis.spatial.World.CAMERA_FAR_CLIP import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_DISTANCE import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_X_ANGLE @@ -16,7 +22,9 @@ import javafx.scene.paint.Color import org.fxyz3d.utils.CameraTransformer import tornadofx.* -class Canvas3D : Fragment() { +class Canvas3D(val plugin: FX3DPlugin, val meta: Meta = EmptyMeta) : Fragment(), Renderer, ContextAware { + + override val context: Context get() = plugin.context val world: Group = Group() private val camera = PerspectiveCamera().apply { @@ -153,6 +161,10 @@ class Canvas3D : Fragment() { } } + override fun render(obj: VisualObject3D, meta: Meta) { + plugin.buildNode(obj)?.let { world.children.add(it) } + } + companion object { private const val AXIS_LENGTH = 2000.0 private const val CONTROL_MULTIPLIER = 0.1 diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/DisplayObjectFXListener.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/DisplayObjectFXBinding.kt similarity index 96% rename from dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/DisplayObjectFXListener.kt rename to dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/DisplayObjectFXBinding.kt index b0d3089e..b0d66ed8 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/DisplayObjectFXListener.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/DisplayObjectFXBinding.kt @@ -10,7 +10,7 @@ import tornadofx.* /** * A caching binding collection for [VisualObject] properties */ -class DisplayObjectFXListener(val obj: VisualObject) { +class DisplayObjectFXBinding(val obj: VisualObject) { private val binndings = HashMap?>>() init { diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DOutput.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DOutput.kt deleted file mode 100644 index 7497ead5..00000000 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DOutput.kt +++ /dev/null @@ -1,50 +0,0 @@ -package hep.dataforge.vis.spatial.fx - -import hep.dataforge.context.Context -import hep.dataforge.meta.Meta -import hep.dataforge.output.Renderer -import hep.dataforge.vis.common.VisualObject -import hep.dataforge.vis.spatial.Box -import hep.dataforge.vis.spatial.VisualGroup3D -import javafx.scene.Group -import javafx.scene.Node -import org.fxyz3d.shapes.primitives.CuboidMesh -import tornadofx.* - -/** - * https://github.com/miho/JCSG for operations - * - */ -class FX3DOutput(override val context: Context) : Renderer { - val canvas by lazy { Canvas3D() } - - - private fun buildNode(obj: VisualObject): Node? { - val listener = DisplayObjectFXListener(obj) - val x = listener["pos.x"].float() - val y = listener["pos.y"].float() - val z = listener["pos.z"].float() - val center = objectBinding(x, y, z) { - org.fxyz3d.geometry.Point3D(x.value ?: 0f, y.value ?: 0f, z.value ?: 0f) - } - return when (obj) { - is VisualGroup3D -> Group(obj.map { buildNode(it) }).apply { - this.translateXProperty().bind(x) - this.translateYProperty().bind(y) - this.translateZProperty().bind(z) - } - is Box -> CuboidMesh(obj.xSize.toDouble(), obj.ySize.toDouble(), obj.zSize.toDouble()).apply { - this.centerProperty().bind(center) - this.materialProperty().bind(listener["color"].transform { it.material() }) - } - else -> { - logger.error { "No renderer defined for ${obj::class}" } - null - } - } - } - - override fun render(obj: VisualObject, meta: Meta) { - buildNode(obj)?.let { canvas.world.children.add(it) } - } -} \ No newline at end of file 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 new file mode 100644 index 00000000..4e28730a --- /dev/null +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FX3DPlugin.kt @@ -0,0 +1,113 @@ +package hep.dataforge.vis.spatial.fx + +import hep.dataforge.context.* +import hep.dataforge.meta.Meta +import hep.dataforge.meta.get +import hep.dataforge.provider.Type +import hep.dataforge.vis.spatial.* +import hep.dataforge.vis.spatial.fx.FX3DFactory.Companion.TYPE +import javafx.scene.Group +import javafx.scene.Node +import javafx.scene.shape.Shape3D +import javafx.scene.transform.Rotate +import org.fxyz3d.shapes.composites.PolyLine3D +import org.fxyz3d.shapes.primitives.CuboidMesh +import kotlin.reflect.KClass + +class FX3DPlugin : AbstractPlugin() { + override val tag: PluginTag get() = Companion.tag + + private val objectFactories = HashMap, FX3DFactory<*>>() + private val compositeFactory = FXCompositeFactory(this) + private val proxyFactory = FXProxyFactory(this) + + init { + //Add specialized factories here + objectFactories[Convex::class] = FXConvexFactory + } + + + @Suppress("UNCHECKED_CAST") + private fun findObjectFactory(type: KClass): FX3DFactory? { + return (objectFactories[type] ?: context.content>(TYPE).values.find { it.type == type }) + as FX3DFactory? + } + + fun buildNode(obj: VisualObject3D): Node? { + val binding = DisplayObjectFXBinding(obj) + return when (obj) { + is Proxy -> proxyFactory(obj, binding) + is VisualGroup3D -> Group(obj.filterIsInstance().map { buildNode(it) }) + is Composite -> compositeFactory(obj, binding) + is Box -> CuboidMesh(obj.xSize.toDouble(), obj.ySize.toDouble(), obj.zSize.toDouble()) + is PolyLine -> PolyLine3D( + obj.points.map { it.point }, + obj.thickness.toFloat(), + obj.material?.get("color")?.color() + ) + else -> { + //find specialized factory for this type if it is present + val factory: FX3DFactory? = findObjectFactory(obj::class) + when { + factory != null -> factory(obj, binding) + obj is Shape -> FXShapeFactory(obj, binding) + else -> error("Renderer for ${obj::class} not found") + } + } + }.apply { + translateXProperty().bind(binding[VisualObject3D.xPos].float()) + translateYProperty().bind(binding[VisualObject3D.yPos].float()) + translateZProperty().bind(binding[VisualObject3D.zPos].float()) + scaleXProperty().bind(binding[VisualObject3D.xScale].float()) + scaleYProperty().bind(binding[VisualObject3D.yScale].float()) + scaleZProperty().bind(binding[VisualObject3D.zScale].float()) + + val rotateX = Rotate(0.0, Rotate.X_AXIS).apply { + angleProperty().bind(binding[VisualObject3D.xRotation].float()) + } + + val rotateY = Rotate(0.0, Rotate.Y_AXIS).apply { + angleProperty().bind(binding[VisualObject3D.yRotation].float()) + } + + val rotateZ = Rotate(0.0, Rotate.Z_AXIS).apply { + angleProperty().bind(binding[VisualObject3D.zRotation].float()) + } + + when (obj.rotationOrder) { + RotationOrder.ZYX -> transforms.addAll(rotateZ, rotateY, rotateX) + RotationOrder.XZY -> transforms.addAll(rotateY, rotateZ, rotateX) + RotationOrder.YXZ -> transforms.addAll(rotateZ, rotateX, rotateY) + RotationOrder.YZX -> transforms.addAll(rotateX, rotateZ, rotateY) + RotationOrder.ZXY -> transforms.addAll(rotateY, rotateX, rotateZ) + RotationOrder.XYZ -> transforms.addAll(rotateZ, rotateY, rotateX) + } + + if (this is Shape3D) { + materialProperty().bind(binding["color"].transform { it.material() }) + } + } + } + + companion object : PluginFactory { + override val tag = PluginTag("visual.fx3D", PluginTag.DATAFORGE_GROUP) + override val type = FX3DPlugin::class + override fun invoke(meta: Meta, context: Context) = FX3DPlugin() + } +} + +/** + * Builder and updater for three.js object + */ +@Type(TYPE) +interface FX3DFactory { + + val type: KClass + + operator fun invoke(obj: T, binding: DisplayObjectFXBinding): Node + + companion object { + const val TYPE = "fx3DFactory" + } +} + diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCompositeFactory.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCompositeFactory.kt new file mode 100644 index 00000000..e5efbf78 --- /dev/null +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCompositeFactory.kt @@ -0,0 +1,38 @@ +package hep.dataforge.vis.spatial.fx + +import eu.mihosoft.jcsg.CSG +import hep.dataforge.vis.spatial.Composite +import hep.dataforge.vis.spatial.CompositeType +import javafx.scene.Group +import javafx.scene.Node +import javafx.scene.shape.MeshView +import org.fxyz3d.utils.MeshUtils +import kotlin.reflect.KClass + +class FXCompositeFactory(val plugin: FX3DPlugin) : + FX3DFactory { + override val type: KClass + get() = Composite::class + + override fun invoke(obj: Composite, binding: DisplayObjectFXBinding): Node { + val first = plugin.buildNode(obj.first) as? MeshView ?: error("Can't build node") + val second = plugin.buildNode(obj.second) as? MeshView ?: error("Can't build node") + val firstCSG = MeshUtils.mesh2CSG(first) + val secondCSG = MeshUtils.mesh2CSG(second) + val resultCSG = when(obj.compositeType){ + CompositeType.UNION -> firstCSG.union(secondCSG) + CompositeType.INTERSECT -> firstCSG.intersect(secondCSG) + CompositeType.SUBTRACT -> firstCSG.difference(secondCSG) + } + return resultCSG.toNode() + } +} + +internal fun CSG.toNode(): Node{ + val meshes = toJavaFXMesh().asMeshViews + return if(meshes.size == 1){ + meshes.first() + } else { + Group(meshes.map { it }) + } +} \ No newline at end of file diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXConvexFactory.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXConvexFactory.kt new file mode 100644 index 00000000..386cdf31 --- /dev/null +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXConvexFactory.kt @@ -0,0 +1,19 @@ +package hep.dataforge.vis.spatial.fx + +import eu.mihosoft.jcsg.PropertyStorage +import eu.mihosoft.jcsg.ext.quickhull3d.HullUtil +import eu.mihosoft.vvecmath.Vector3d +import hep.dataforge.vis.spatial.Convex +import javafx.scene.Node +import kotlin.reflect.KClass + + +object FXConvexFactory : FX3DFactory { + override val type: KClass get() = Convex::class + + override fun invoke(obj: Convex, binding: DisplayObjectFXBinding): Node { + val hull = HullUtil.hull(obj.points.map { Vector3d.xyz(it.x, it.y, it.z) }, PropertyStorage()) + return hull.toNode() + } + +} \ No newline at end of file diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXProxyFactory.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXProxyFactory.kt new file mode 100644 index 00000000..d42362b2 --- /dev/null +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXProxyFactory.kt @@ -0,0 +1,15 @@ +package hep.dataforge.vis.spatial.fx + +import hep.dataforge.vis.spatial.Proxy +import javafx.scene.Node +import kotlin.reflect.KClass + +class FXProxyFactory(val plugin: FX3DPlugin) : + FX3DFactory { + override val type: KClass get() = Proxy::class + + override fun invoke(obj: Proxy, binding: DisplayObjectFXBinding): Node { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + +} \ No newline at end of file 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 new file mode 100644 index 00000000..eb3f6925 --- /dev/null +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXShapeFactory.kt @@ -0,0 +1,58 @@ +package hep.dataforge.vis.spatial.fx + +import hep.dataforge.meta.Meta +import hep.dataforge.vis.spatial.GeometryBuilder +import hep.dataforge.vis.spatial.Point3D +import hep.dataforge.vis.spatial.Shape +import javafx.scene.shape.Mesh +import javafx.scene.shape.MeshView +import javafx.scene.shape.TriangleMesh +import kotlin.reflect.KClass + +object FXShapeFactory : FX3DFactory { + override val type: KClass get() = Shape::class + + override fun invoke(obj: Shape, binding: DisplayObjectFXBinding): MeshView { + val mesh = FXGeometryBuilder().apply { obj.toGeometry(this) }.build() + return MeshView(mesh) + } +} + +private typealias Face = IntArray + +private class FXGeometryBuilder : GeometryBuilder { + val vertices = ArrayList() + val faces = ArrayList() + private val vertexCache = HashMap() + + private fun append(vertex: Point3D): Int { + val index = vertexCache[vertex] ?: -1//vertices.indexOf(vertex) + return if (index > 0) { + index + } else { + vertices.add(vertex) + vertexCache[vertex] = vertices.size - 1 + vertices.size - 1 + } + } + + 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)) + faces.add(face) + } + + override fun build(): Mesh { + val mesh = TriangleMesh() + vertices.forEach { + //TODO optimize copy + mesh.points.addAll(it.x.toFloat(), it.y.toFloat(), it.z.toFloat()) + } + faces.forEach { + mesh.faces.addAll(it[0], it[1], it[2]) + } + return mesh + } + +} + 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/fx/RendererDemoApp.kt index cd4bc32c..1349280c 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/fx/RendererDemoApp.kt @@ -16,9 +16,10 @@ class RendererDemoApp : App(RendererDemoView::class) class RendererDemoView : View() { - val renderer = FX3DOutput(Global) + val plugin = Global.plugins.fetch(FX3DPlugin) + val renderer = Canvas3D(plugin) override val root: Parent = borderpane { - center = renderer.canvas.root + center = renderer.root } lateinit var group: VisualGroup3D @@ -44,7 +45,7 @@ class RendererDemoView : View() { } } - renderer.canvas.apply { + renderer.apply { angleY = -30.0 angleX = -15.0 } diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/geometryJVM.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/geometryJVM.kt index 3e56de87..affc7f8c 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/geometryJVM.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/geometryJVM.kt @@ -5,8 +5,28 @@ actual class Point2D actual constructor(x: Number, y: Number) { actual var y = y.toDouble() } -actual class Point3D actual constructor(x: Number, y: Number, z: Number) { - actual var x = x.toDouble() - actual var y = y.toDouble() - actual var z = z.toDouble() +actual class Point3D(val point: org.fxyz3d.geometry.Point3D) { + actual constructor(x: Number, y: Number, z: Number) : this( + org.fxyz3d.geometry.Point3D( + x.toFloat(), + y.toFloat(), + z.toFloat() + ) + ) + + actual var x: Double + inline get() = point.x.toDouble() + inline set(value) { + point.x = value.toFloat() + } + actual var y: Double + inline get() = point.y.toDouble() + inline set(value) { + point.y = value.toFloat() + } + actual var z: Double + inline get() = point.z.toDouble() + inline set(value) { + point.z = value.toFloat() + } } \ No newline at end of file diff --git a/spatial-js-demo/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt b/spatial-js-demo/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt index ff8a2f88..94e9b709 100644 --- a/spatial-js-demo/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt +++ b/spatial-js-demo/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt @@ -10,12 +10,12 @@ import hep.dataforge.meta.get import hep.dataforge.meta.string import hep.dataforge.names.Name import hep.dataforge.names.toName -import hep.dataforge.output.Output import hep.dataforge.output.OutputManager +import hep.dataforge.output.Renderer import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.render -import hep.dataforge.vis.spatial.three.ThreeOutput +import hep.dataforge.vis.spatial.three.ThreeCanvas import hep.dataforge.vis.spatial.three.ThreePlugin import hep.dataforge.vis.spatial.three.output import kotlinx.html.dom.append @@ -33,7 +33,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager { override val tag: PluginTag get() = Companion.tag private val gridRoot = document.create.div("row") - private val outputs: MutableMap = HashMap() + private val outputs: MutableMap = HashMap() init { require(ThreePlugin) @@ -48,7 +48,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager { } @Suppress("UNCHECKED_CAST") - override fun get(type: KClass, name: Name, stage: Name, meta: Meta): Output { + override fun get(type: KClass, name: Name, stage: Name, meta: Meta): Renderer { val three = context.plugins.get()!! return outputs.getOrPut(name) { @@ -73,7 +73,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager { } output - } as Output + } as Renderer } companion object : PluginFactory {