forked from kscience/visionforge
FX backend in progress
This commit is contained in:
parent
c964f80d73
commit
cef1a1ee6d
@ -32,8 +32,7 @@ kotlin {
|
|||||||
jsMain{
|
jsMain{
|
||||||
dependencies {
|
dependencies {
|
||||||
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
|
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
|
||||||
api("kotlin.js.externals:kotlin-js-jquery:3.2.0-0")
|
api(npm("bootstrap","4.4.1"))
|
||||||
api(npm("bootstrap","4.3.1"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package hep.dataforge.vis.common
|
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.Name
|
||||||
import hep.dataforge.names.asName
|
import hep.dataforge.names.asName
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
@ -15,7 +18,7 @@ import kotlinx.serialization.Transient
|
|||||||
* A root type for display hierarchy
|
* A root type for display hierarchy
|
||||||
*/
|
*/
|
||||||
@Type(TYPE)
|
@Type(TYPE)
|
||||||
interface VisualObject : MetaRepr, Configurable {
|
interface VisualObject : Configurable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parent object of this one. If null, this one is a root.
|
* 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?)
|
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<Name>
|
var styles: List<Name>
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ kotlin {
|
|||||||
}
|
}
|
||||||
jvmMain {
|
jvmMain {
|
||||||
dependencies {
|
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 {
|
jsMain {
|
||||||
|
@ -3,7 +3,6 @@ package hep.dataforge.vis.spatial
|
|||||||
|
|
||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.float
|
import hep.dataforge.meta.float
|
||||||
@ -50,8 +49,6 @@ class Box(
|
|||||||
geometryBuilder.face4(node8, node5, node6, node7)
|
geometryBuilder.face4(node8, node5, node6, node7)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta()
|
|
||||||
|
|
||||||
companion object : VisualFactory<Box> {
|
companion object : VisualFactory<Box> {
|
||||||
const val TYPE = "geometry.3d.box"
|
const val TYPE = "geometry.3d.box"
|
||||||
|
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.meta.update
|
import hep.dataforge.meta.update
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@ -34,8 +32,6 @@ class Composite(
|
|||||||
|
|
||||||
@Serializable(ConfigSerializer::class)
|
@Serializable(ConfigSerializer::class)
|
||||||
override var properties: Config? = null
|
override var properties: Config? = null
|
||||||
|
|
||||||
override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun VisualGroup3D.composite(
|
inline fun VisualGroup3D.composite(
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.sin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cylinder or cut cone segment
|
* A cylinder or cut cone segment
|
||||||
@ -20,7 +20,7 @@ class ConeSegment(
|
|||||||
var upperRadius: Float,
|
var upperRadius: Float,
|
||||||
var startAngle: Float = 0f,
|
var startAngle: Float = 0f,
|
||||||
var angle: Float = PI2
|
var angle: Float = PI2
|
||||||
) : AbstractVisualObject(), VisualObject3D {
|
) : AbstractVisualObject(), VisualObject3D, Shape {
|
||||||
|
|
||||||
@Serializable(ConfigSerializer::class)
|
@Serializable(ConfigSerializer::class)
|
||||||
override var properties: Config? = null
|
override var properties: Config? = null
|
||||||
@ -29,7 +29,48 @@ class ConeSegment(
|
|||||||
override var rotation: Point3D? = null
|
override var rotation: Point3D? = null
|
||||||
override var scale: Point3D? = null
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta()
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
|
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<Point3D> {
|
||||||
|
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(
|
inline fun VisualGroup3D.cylinder(
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
@ -20,8 +18,6 @@ class Convex(val points: List<Point3D>) : AbstractVisualObject(), VisualObject3D
|
|||||||
override var rotation: Point3D? = null
|
override var rotation: Point3D? = null
|
||||||
override var scale: Point3D? = null
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta()
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TYPE = "geometry.3d.convex"
|
const val TYPE = "geometry.3d.convex"
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
@ -107,8 +105,6 @@ class Extruded(
|
|||||||
geometryBuilder.cap(layers.last())
|
geometryBuilder.cap(layers.last())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta()
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TYPE = "geometry.3d.extruded"
|
const val TYPE = "geometry.3d.extruded"
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
import hep.dataforge.vis.common.number
|
import hep.dataforge.vis.common.number
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@ -23,7 +21,6 @@ class PolyLine(var points: List<Point3D>) : AbstractVisualObject(), VisualObject
|
|||||||
//var lineType by string()
|
//var lineType by string()
|
||||||
var thickness by number(1.0, key = "material.thickness")
|
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 = {}) =
|
fun VisualGroup3D.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}) =
|
||||||
|
@ -4,7 +4,6 @@ package hep.dataforge.vis.spatial
|
|||||||
|
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.serialization.NameSerializer
|
import hep.dataforge.io.serialization.NameSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.MetaItem
|
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<NameToken, ProxyChild>
|
override val children: Map<NameToken, ProxyChild>
|
||||||
get() = (prototype as? MutableVisualGroup)?.children
|
get() = (prototype as? MutableVisualGroup)?.children
|
||||||
?.filter { !it.key.toString().startsWith("@") }
|
?.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 {
|
companion object {
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
@ -18,7 +16,7 @@ class Sphere(
|
|||||||
var phi: Float = PI2,
|
var phi: Float = PI2,
|
||||||
var thetaStart: Float = 0f,
|
var thetaStart: Float = 0f,
|
||||||
var theta: Float = PI.toFloat()
|
var theta: Float = PI.toFloat()
|
||||||
) : AbstractVisualObject(), VisualObject3D {
|
) : AbstractVisualObject(), VisualObject3D, Shape {
|
||||||
|
|
||||||
@Serializable(ConfigSerializer::class)
|
@Serializable(ConfigSerializer::class)
|
||||||
override var properties: Config? = null
|
override var properties: Config? = null
|
||||||
@ -27,7 +25,9 @@ class Sphere(
|
|||||||
override var rotation: Point3D? = null
|
override var rotation: Point3D? = null
|
||||||
override var scale: Point3D? = null
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta()
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun VisualGroup3D.sphere(
|
inline fun VisualGroup3D.sphere(
|
||||||
|
@ -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) }
|
@ -2,9 +2,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
@ -126,7 +124,6 @@ class Tube(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun VisualGroup3D.tube(
|
inline fun VisualGroup3D.tube(
|
||||||
|
@ -11,7 +11,6 @@ package hep.dataforge.vis.spatial
|
|||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.serialization.MetaSerializer
|
import hep.dataforge.io.serialization.MetaSerializer
|
||||||
import hep.dataforge.io.serialization.NameSerializer
|
import hep.dataforge.io.serialization.NameSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.names.Name
|
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 {
|
companion object {
|
||||||
const val PROTOTYPES_KEY = "templates"
|
const val PROTOTYPES_KEY = "templates"
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package hep.dataforge.vis.spatial
|
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.getIndexed
|
||||||
import hep.dataforge.meta.node
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@ -25,12 +25,11 @@ class ConvexTest {
|
|||||||
|
|
||||||
val convex = group.first() as Convex
|
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
|
val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D()}
|
||||||
|
assertEquals(8, points.count())
|
||||||
assertEquals(8, pointsNode?.items?.count())
|
|
||||||
val points = pointsNode?.getIndexed("points")
|
|
||||||
|
|
||||||
assertEquals(8, convex.points.size)
|
assertEquals(8, convex.points.size)
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,15 @@ import kotlin.test.assertEquals
|
|||||||
class SerializationTest {
|
class SerializationTest {
|
||||||
@ImplicitReflectionSerializer
|
@ImplicitReflectionSerializer
|
||||||
@Test
|
@Test
|
||||||
fun testCubeSerialization(){
|
fun testCubeSerialization() {
|
||||||
val cube = Box(100f,100f,100f).apply{
|
val cube = Box(100f, 100f, 100f).apply {
|
||||||
color(222)
|
color(222)
|
||||||
x = 100
|
x = 100
|
||||||
z = -100
|
z = -100
|
||||||
}
|
}
|
||||||
val string = json.stringify(Box.serializer(),cube)
|
val string = json.stringify(Box.serializer(), cube)
|
||||||
println(string)
|
println(string)
|
||||||
val newCube = json.parse(Box.serializer(),string)
|
val newCube = json.parse(Box.serializer(), string)
|
||||||
assertEquals(cube.toMeta(),newCube.toMeta())
|
assertEquals(cube.config, newCube.config)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package hep.dataforge.vis.spatial.editor
|
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.InputType
|
||||||
import kotlinx.html.dom.append
|
import kotlinx.html.dom.append
|
||||||
import kotlinx.html.js.div
|
import kotlinx.html.js.div
|
||||||
@ -9,7 +9,7 @@ import kotlinx.html.js.label
|
|||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import kotlin.dom.clear
|
import kotlin.dom.clear
|
||||||
|
|
||||||
fun Element.threeOutputConfig(output: ThreeOutput) {
|
fun Element.threeOutputConfig(canvas: ThreeCanvas) {
|
||||||
clear()
|
clear()
|
||||||
append {
|
append {
|
||||||
card("Layers"){
|
card("Layers"){
|
||||||
@ -23,9 +23,9 @@ fun Element.threeOutputConfig(output: ThreeOutput) {
|
|||||||
}
|
}
|
||||||
onchange = {
|
onchange = {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
output.camera.layers.enable(layer)
|
canvas.camera.layers.enable(layer)
|
||||||
} else {
|
} else {
|
||||||
output.camera.layers.disable(layer)
|
canvas.camera.layers.disable(layer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import kotlin.browser.window
|
|||||||
import kotlin.dom.clear
|
import kotlin.dom.clear
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Renderer<VisualObject3D> {
|
class ThreeCanvas(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Renderer<VisualObject3D> {
|
||||||
|
|
||||||
override val context: Context get() = three.context
|
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 = {}) =
|
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) {
|
if (element != null) {
|
||||||
attach(element)
|
attach(element)
|
||||||
}
|
}
|
@ -38,17 +38,17 @@ fun Object3D.updatePosition(obj: VisualObject3D) {
|
|||||||
updateMatrix()
|
updateMatrix()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
///**
|
||||||
* Unsafe invocation of a factory
|
// * Unsafe invocation of a factory
|
||||||
*/
|
// */
|
||||||
operator fun <T : VisualObject3D> ThreeFactory<T>.invoke(obj: Any): Object3D {
|
//operator fun <T : VisualObject3D> ThreeFactory<T>.invoke(obj: Any): Object3D {
|
||||||
if (type.isInstance(obj)) {
|
// if (type.isInstance(obj)) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
// @Suppress("UNCHECKED_CAST")
|
||||||
return invoke(obj as T)
|
// return invoke(obj as T)
|
||||||
} else {
|
// } else {
|
||||||
error("The object of type ${obj::class} could not be rendered by this factory")
|
// error("The object of type ${obj::class} could not be rendered by this factory")
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update non-position non-geometry property
|
* Update non-position non-geometry property
|
||||||
|
@ -16,7 +16,7 @@ import info.laht.threekt.objects.Group as ThreeGroup
|
|||||||
class ThreePlugin : AbstractPlugin() {
|
class ThreePlugin : AbstractPlugin() {
|
||||||
override val tag: PluginTag get() = Companion.tag
|
override val tag: PluginTag get() = Companion.tag
|
||||||
|
|
||||||
private val objectFactories = HashMap<KClass<out VisualObject>, ThreeFactory<*>>()
|
private val objectFactories = HashMap<KClass<out VisualObject3D>, ThreeFactory<*>>()
|
||||||
private val compositeFactory = ThreeCompositeFactory(this)
|
private val compositeFactory = ThreeCompositeFactory(this)
|
||||||
private val proxyFactory = ThreeProxyFactory(this)
|
private val proxyFactory = ThreeProxyFactory(this)
|
||||||
|
|
||||||
@ -29,9 +29,11 @@ class ThreePlugin : AbstractPlugin() {
|
|||||||
objectFactories[PolyLine::class] = ThreeLineFactory
|
objectFactories[PolyLine::class] = ThreeLineFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findObjectFactory(type: KClass<out VisualObject>): ThreeFactory<*>? {
|
@Suppress("UNCHECKED_CAST")
|
||||||
return objectFactories[type]
|
private fun findObjectFactory(type: KClass<out VisualObject>): ThreeFactory<VisualObject3D>? {
|
||||||
?: context.content<ThreeFactory<*>>(ThreeFactory.TYPE).values.find { it.type == type }
|
return (objectFactories[type]
|
||||||
|
?: context.content<ThreeFactory<*>>(ThreeFactory.TYPE).values.find { it.type == type })
|
||||||
|
as ThreeFactory<VisualObject3D>?
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildObject3D(obj: VisualObject3D): Object3D {
|
fun buildObject3D(obj: VisualObject3D): Object3D {
|
||||||
@ -73,7 +75,7 @@ class ThreePlugin : AbstractPlugin() {
|
|||||||
is Composite -> compositeFactory(obj)
|
is Composite -> compositeFactory(obj)
|
||||||
else -> {
|
else -> {
|
||||||
//find specialized factory for this type if it is present
|
//find specialized factory for this type if it is present
|
||||||
val factory = findObjectFactory(obj::class)
|
val factory: ThreeFactory<VisualObject3D>? = findObjectFactory(obj::class)
|
||||||
when {
|
when {
|
||||||
factory != null -> factory(obj)
|
factory != null -> factory(obj)
|
||||||
obj is Shape -> ThreeShapeFactory(obj)
|
obj is Shape -> ThreeShapeFactory(obj)
|
||||||
|
@ -3,13 +3,10 @@
|
|||||||
package hep.dataforge.vis.spatial.three
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
import hep.dataforge.io.serialization.ConfigSerializer
|
import hep.dataforge.io.serialization.ConfigSerializer
|
||||||
import hep.dataforge.io.toMeta
|
|
||||||
import hep.dataforge.meta.Config
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.AbstractVisualObject
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
import hep.dataforge.vis.spatial.Point3D
|
import hep.dataforge.vis.spatial.Point3D
|
||||||
import hep.dataforge.vis.spatial.Point3DSerializer
|
import hep.dataforge.vis.spatial.Point3DSerializer
|
||||||
import hep.dataforge.vis.spatial.Visual3DPlugin
|
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D
|
import hep.dataforge.vis.spatial.VisualObject3D
|
||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@ -32,8 +29,6 @@ class CustomThreeVisualObject(val threeFactory: ThreeFactory<VisualObject3D>) :
|
|||||||
@Serializable(ConfigSerializer::class)
|
@Serializable(ConfigSerializer::class)
|
||||||
override var properties: Config? = null
|
override var properties: Config? = null
|
||||||
|
|
||||||
override fun toMeta(): Meta = Visual3DPlugin.json.toJson(serializer(), this).toMeta()
|
|
||||||
|
|
||||||
override fun toObject3D(): Object3D = threeFactory(this)
|
override fun toObject3D(): Object3D = threeFactory(this)
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,11 @@
|
|||||||
package hep.dataforge.vis.spatial.fx
|
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_FAR_CLIP
|
||||||
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_DISTANCE
|
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_DISTANCE
|
||||||
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_X_ANGLE
|
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 org.fxyz3d.utils.CameraTransformer
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
class Canvas3D : Fragment() {
|
class Canvas3D(val plugin: FX3DPlugin, val meta: Meta = EmptyMeta) : Fragment(), Renderer<VisualObject3D>, ContextAware {
|
||||||
|
|
||||||
|
override val context: Context get() = plugin.context
|
||||||
val world: Group = Group()
|
val world: Group = Group()
|
||||||
|
|
||||||
private val camera = PerspectiveCamera().apply {
|
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 {
|
companion object {
|
||||||
private const val AXIS_LENGTH = 2000.0
|
private const val AXIS_LENGTH = 2000.0
|
||||||
private const val CONTROL_MULTIPLIER = 0.1
|
private const val CONTROL_MULTIPLIER = 0.1
|
||||||
|
@ -10,7 +10,7 @@ import tornadofx.*
|
|||||||
/**
|
/**
|
||||||
* A caching binding collection for [VisualObject] properties
|
* A caching binding collection for [VisualObject] properties
|
||||||
*/
|
*/
|
||||||
class DisplayObjectFXListener(val obj: VisualObject) {
|
class DisplayObjectFXBinding(val obj: VisualObject) {
|
||||||
private val binndings = HashMap<Name, ObjectBinding<MetaItem<*>?>>()
|
private val binndings = HashMap<Name, ObjectBinding<MetaItem<*>?>>()
|
||||||
|
|
||||||
init {
|
init {
|
@ -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<VisualObject> {
|
|
||||||
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) }
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<KClass<out VisualObject3D>, 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<out VisualObject3D>): FX3DFactory<VisualObject3D>? {
|
||||||
|
return (objectFactories[type] ?: context.content<FX3DFactory<*>>(TYPE).values.find { it.type == type })
|
||||||
|
as FX3DFactory<VisualObject3D>?
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildNode(obj: VisualObject3D): Node? {
|
||||||
|
val binding = DisplayObjectFXBinding(obj)
|
||||||
|
return when (obj) {
|
||||||
|
is Proxy -> proxyFactory(obj, binding)
|
||||||
|
is VisualGroup3D -> Group(obj.filterIsInstance<VisualObject3D>().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<VisualObject3D>? = 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<FX3DPlugin> {
|
||||||
|
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<in T : VisualObject3D> {
|
||||||
|
|
||||||
|
val type: KClass<in T>
|
||||||
|
|
||||||
|
operator fun invoke(obj: T, binding: DisplayObjectFXBinding): Node
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TYPE = "fx3DFactory"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<Composite> {
|
||||||
|
override val type: KClass<in Composite>
|
||||||
|
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 })
|
||||||
|
}
|
||||||
|
}
|
@ -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<Convex> {
|
||||||
|
override val type: KClass<in Convex> 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()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<Proxy> {
|
||||||
|
override val type: KClass<in Proxy> 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.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<Shape> {
|
||||||
|
override val type: KClass<in Shape> 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<Mesh> {
|
||||||
|
val vertices = ArrayList<Point3D>()
|
||||||
|
val faces = ArrayList<Face>()
|
||||||
|
private val vertexCache = HashMap<Point3D, Int>()
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -16,9 +16,10 @@ class RendererDemoApp : App(RendererDemoView::class)
|
|||||||
|
|
||||||
|
|
||||||
class RendererDemoView : View() {
|
class RendererDemoView : View() {
|
||||||
val renderer = FX3DOutput(Global)
|
val plugin = Global.plugins.fetch(FX3DPlugin)
|
||||||
|
val renderer = Canvas3D(plugin)
|
||||||
override val root: Parent = borderpane {
|
override val root: Parent = borderpane {
|
||||||
center = renderer.canvas.root
|
center = renderer.root
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var group: VisualGroup3D
|
lateinit var group: VisualGroup3D
|
||||||
@ -44,7 +45,7 @@ class RendererDemoView : View() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.canvas.apply {
|
renderer.apply {
|
||||||
angleY = -30.0
|
angleY = -30.0
|
||||||
angleX = -15.0
|
angleX = -15.0
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,28 @@ actual class Point2D actual constructor(x: Number, y: Number) {
|
|||||||
actual var y = y.toDouble()
|
actual var y = y.toDouble()
|
||||||
}
|
}
|
||||||
|
|
||||||
actual class Point3D actual constructor(x: Number, y: Number, z: Number) {
|
actual class Point3D(val point: org.fxyz3d.geometry.Point3D) {
|
||||||
actual var x = x.toDouble()
|
actual constructor(x: Number, y: Number, z: Number) : this(
|
||||||
actual var y = y.toDouble()
|
org.fxyz3d.geometry.Point3D(
|
||||||
actual var z = z.toDouble()
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
@ -10,12 +10,12 @@ import hep.dataforge.meta.get
|
|||||||
import hep.dataforge.meta.string
|
import hep.dataforge.meta.string
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.output.Output
|
|
||||||
import hep.dataforge.output.OutputManager
|
import hep.dataforge.output.OutputManager
|
||||||
|
import hep.dataforge.output.Renderer
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.spatial.VisualGroup3D
|
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||||
import hep.dataforge.vis.spatial.render
|
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.ThreePlugin
|
||||||
import hep.dataforge.vis.spatial.three.output
|
import hep.dataforge.vis.spatial.three.output
|
||||||
import kotlinx.html.dom.append
|
import kotlinx.html.dom.append
|
||||||
@ -33,7 +33,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager {
|
|||||||
override val tag: PluginTag get() = Companion.tag
|
override val tag: PluginTag get() = Companion.tag
|
||||||
|
|
||||||
private val gridRoot = document.create.div("row")
|
private val gridRoot = document.create.div("row")
|
||||||
private val outputs: MutableMap<Name, ThreeOutput> = HashMap()
|
private val outputs: MutableMap<Name, ThreeCanvas> = HashMap()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(ThreePlugin)
|
require(ThreePlugin)
|
||||||
@ -48,7 +48,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Output<T> {
|
override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Renderer<T> {
|
||||||
val three = context.plugins.get<ThreePlugin>()!!
|
val three = context.plugins.get<ThreePlugin>()!!
|
||||||
|
|
||||||
return outputs.getOrPut(name) {
|
return outputs.getOrPut(name) {
|
||||||
@ -73,7 +73,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
output
|
output
|
||||||
} as Output<T>
|
} as Renderer<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : PluginFactory<ThreeDemoGrid> {
|
companion object : PluginFactory<ThreeDemoGrid> {
|
||||||
|
Loading…
Reference in New Issue
Block a user