forked from kscience/visionforge
Almost working OrbitControls for FX
This commit is contained in:
parent
26948a88d7
commit
459d256ebd
@ -1,6 +1,6 @@
|
|||||||
import scientifik.useSerialization
|
import scientifik.useSerialization
|
||||||
|
|
||||||
val dataforgeVersion by extra("0.1.5-dev-5")
|
val dataforgeVersion by extra("0.1.5-dev-6")
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
val kotlinVersion = "1.3.61"
|
val kotlinVersion = "1.3.61"
|
||||||
|
@ -35,6 +35,7 @@ kotlin {
|
|||||||
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
|
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
|
||||||
api(npm("bootstrap","4.4.1"))
|
api(npm("bootstrap","4.4.1"))
|
||||||
implementation(npm("jsoneditor"))
|
implementation(npm("jsoneditor"))
|
||||||
|
implementation(npm("file-saver"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
package hep.dataforge.js
|
package hep.dataforge.vis.js.editor
|
||||||
|
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.common.isEmpty
|
import hep.dataforge.vis.common.isEmpty
|
||||||
import hep.dataforge.vis.js.editor.card
|
|
||||||
import kotlinx.html.TagConsumer
|
import kotlinx.html.TagConsumer
|
||||||
import kotlinx.html.dom.append
|
import kotlinx.html.dom.append
|
||||||
import kotlinx.html.js.*
|
import kotlinx.html.js.*
|
||||||
|
@ -5,13 +5,9 @@ import hep.dataforge.meta.MetaBuilder
|
|||||||
import hep.dataforge.meta.buildMeta
|
import hep.dataforge.meta.buildMeta
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.vis.common.VisualObject
|
|
||||||
import hep.dataforge.vis.common.useStyle
|
import hep.dataforge.vis.common.useStyle
|
||||||
|
import hep.dataforge.vis.spatial.*
|
||||||
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
|
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
|
||||||
import hep.dataforge.vis.spatial.RotationOrder
|
|
||||||
import hep.dataforge.vis.spatial.VisualGroup3D
|
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D
|
|
||||||
import hep.dataforge.vis.spatial.rotationOrder
|
|
||||||
import scientifik.gdml.*
|
import scientifik.gdml.*
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@ -37,7 +33,14 @@ class GDMLTransformer(val root: GDML) {
|
|||||||
var volumeAction: (GDMLGroup) -> Action = { Action.CACHE }
|
var volumeAction: (GDMLGroup) -> Action = { Action.CACHE }
|
||||||
|
|
||||||
|
|
||||||
var solidConfiguration: VisualObject3D.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { _, _ -> }
|
var solidConfiguration: VisualObject3D.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { parent, solid ->
|
||||||
|
lUnit = LUnit.CM
|
||||||
|
if (parent.physVolumes.isNotEmpty()) {
|
||||||
|
useStyle("opaque") {
|
||||||
|
Material3D.MATERIAL_OPACITY_KEY put 0.3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun VisualObject3D.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
|
fun VisualObject3D.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
|
||||||
styleCache.getOrPut(name.toName()) {
|
styleCache.getOrPut(name.toName()) {
|
||||||
|
@ -6,8 +6,8 @@ import hep.dataforge.names.asName
|
|||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.plus
|
||||||
import hep.dataforge.vis.common.get
|
import hep.dataforge.vis.common.get
|
||||||
import hep.dataforge.vis.spatial.*
|
import hep.dataforge.vis.spatial.*
|
||||||
import hep.dataforge.vis.spatial.GeometryConstants.one
|
import hep.dataforge.vis.spatial.World.ONE
|
||||||
import hep.dataforge.vis.spatial.GeometryConstants.zero
|
import hep.dataforge.vis.spatial.World.ZERO
|
||||||
import scientifik.gdml.*
|
import scientifik.gdml.*
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
@ -21,20 +21,20 @@ private fun VisualObject3D.withPosition(
|
|||||||
): VisualObject3D = apply {
|
): VisualObject3D = apply {
|
||||||
newPos?.let {
|
newPos?.let {
|
||||||
val point = Point3D(it.x(lUnit), it.y(lUnit), it.z(lUnit))
|
val point = Point3D(it.x(lUnit), it.y(lUnit), it.z(lUnit))
|
||||||
if (position != null || point != zero) {
|
if (position != null || point != ZERO) {
|
||||||
position = point
|
position = point
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newRotation?.let {
|
newRotation?.let {
|
||||||
val point = Point3D(it.x(), it.y(), it.z())
|
val point = Point3D(it.x(), it.y(), it.z())
|
||||||
if (rotation != null || point != zero) {
|
if (rotation != null || point != ZERO) {
|
||||||
rotation = point
|
rotation = point
|
||||||
}
|
}
|
||||||
//this@withPosition.rotationOrder = RotationOrder.ZXY
|
//this@withPosition.rotationOrder = RotationOrder.ZXY
|
||||||
}
|
}
|
||||||
newScale?.let {
|
newScale?.let {
|
||||||
val point = Point3D(it.x, it.y, it.z)
|
val point = Point3D(it.x, it.y, it.z)
|
||||||
if (scale != null || point != one) {
|
if (scale != null || point != ONE) {
|
||||||
scale = point
|
scale = point
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
contextual(Point2DSerializer)
|
contextual(Point2DSerializer)
|
||||||
contextual(NameSerializer)
|
contextual(NameSerializer)
|
||||||
contextual(NameTokenSerializer)
|
contextual(NameTokenSerializer)
|
||||||
contextual(Meta::class, MetaSerializer)
|
contextual(MetaSerializer)
|
||||||
contextual(ConfigSerializer)
|
contextual(ConfigSerializer)
|
||||||
|
|
||||||
polymorphic(VisualObject::class, VisualObject3D::class) {
|
polymorphic(VisualObject::class, VisualObject3D::class) {
|
||||||
@ -48,7 +48,8 @@ class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
Tube::class with Tube.serializer()
|
Tube::class with Tube.serializer()
|
||||||
Box::class with Box.serializer()
|
Box::class with Box.serializer()
|
||||||
Convex::class with Convex.serializer()
|
Convex::class with Convex.serializer()
|
||||||
addSubclass(Extruded.serializer())
|
Extruded::class with Extruded.serializer()
|
||||||
|
addSubclass(Label3D.serializer())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,12 +3,8 @@ package hep.dataforge.vis.spatial
|
|||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
|
||||||
object World {
|
object World {
|
||||||
const val CAMERA_INITIAL_DISTANCE = -500.0
|
val ZERO = Point3D(0.0, 0.0, 0.0)
|
||||||
const val CAMERA_INITIAL_X_ANGLE = -50.0
|
val ONE = Point3D(1.0, 1.0, 1.0)
|
||||||
const val CAMERA_INITIAL_Y_ANGLE = 0.0
|
|
||||||
const val CAMERA_INITIAL_Z_ANGLE = -210.0
|
|
||||||
const val CAMERA_NEAR_CLIP = 0.1
|
|
||||||
const val CAMERA_FAR_CLIP = 10000.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const val PI2: Float = 2 * PI.toFloat()
|
const val PI2: Float = 2 * PI.toFloat()
|
@ -39,8 +39,3 @@ fun Point3D.toMeta() = buildMeta {
|
|||||||
VisualObject3D.y put y
|
VisualObject3D.y put y
|
||||||
VisualObject3D.z put z
|
VisualObject3D.z put z
|
||||||
}
|
}
|
||||||
|
|
||||||
object GeometryConstants {
|
|
||||||
val zero = Point3D(0.0, 0.0, 0.0)
|
|
||||||
val one = Point3D(1.0, 1.0, 1.0)
|
|
||||||
}
|
|
@ -0,0 +1,17 @@
|
|||||||
|
package hep.dataforge.vis.spatial.specifications
|
||||||
|
|
||||||
|
import hep.dataforge.meta.*
|
||||||
|
|
||||||
|
class AxesSpec(override val config: Config) : Specific {
|
||||||
|
var visible by boolean(!config.isEmpty())
|
||||||
|
var size by double(AXIS_SIZE)
|
||||||
|
var width by double(AXIS_WIDTH)
|
||||||
|
|
||||||
|
companion object : Specification<AxesSpec> {
|
||||||
|
override fun wrap(config: Config): AxesSpec = AxesSpec(config)
|
||||||
|
|
||||||
|
const val AXIS_SIZE = 1000.0
|
||||||
|
const val AXIS_WIDTH = 3.0
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package hep.dataforge.vis.spatial.specifications
|
||||||
|
|
||||||
|
import hep.dataforge.meta.*
|
||||||
|
import kotlin.math.PI
|
||||||
|
|
||||||
|
class CameraSpec(override val config: Config) : Specific {
|
||||||
|
var fov by int(FIELD_OF_VIEW)
|
||||||
|
//var aspect by double(1.0)
|
||||||
|
var nearClip by double(NEAR_CLIP)
|
||||||
|
var farClip by double(FAR_CLIP)
|
||||||
|
|
||||||
|
var distance by double(INITIAL_DISTANCE)
|
||||||
|
var azimuth by double(INITIAL_AZIMUTH)
|
||||||
|
var latitude by double(INITIAL_LATITUDE)
|
||||||
|
val zenith: Double get() = PI / 2 - latitude
|
||||||
|
|
||||||
|
companion object : Specification<CameraSpec> {
|
||||||
|
override fun wrap(config: Config): CameraSpec = CameraSpec(config)
|
||||||
|
const val INITIAL_DISTANCE = 300.0
|
||||||
|
const val INITIAL_AZIMUTH = 0.0
|
||||||
|
const val INITIAL_LATITUDE = PI/6
|
||||||
|
const val NEAR_CLIP = 0.1
|
||||||
|
const val FAR_CLIP = 10000.0
|
||||||
|
const val FIELD_OF_VIEW = 75
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package hep.dataforge.vis.spatial.specifications
|
||||||
|
|
||||||
|
import hep.dataforge.meta.*
|
||||||
|
|
||||||
|
class CanvasSpec(override val config: Config) : Specific {
|
||||||
|
var axes by spec(AxesSpec)
|
||||||
|
var camera by spec(CameraSpec)
|
||||||
|
var controls by spec(ControlsSpec)
|
||||||
|
var minSize by int(300)
|
||||||
|
|
||||||
|
companion object: Specification<CanvasSpec>{
|
||||||
|
override fun wrap(config: Config): CanvasSpec = CanvasSpec(config)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package hep.dataforge.vis.spatial.specifications
|
||||||
|
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
|
import hep.dataforge.meta.Specific
|
||||||
|
import hep.dataforge.meta.Specification
|
||||||
|
|
||||||
|
class ControlsSpec(override val config: Config) : Specific {
|
||||||
|
companion object : Specification<ControlsSpec> {
|
||||||
|
override fun wrap(config: Config): ControlsSpec = ControlsSpec(config)
|
||||||
|
}
|
||||||
|
}
|
@ -15,8 +15,8 @@ internal fun mergeChild(parent: VisualGroup, child: VisualObject): VisualObject
|
|||||||
//parent.properties?.let { config.update(it) }
|
//parent.properties?.let { config.update(it) }
|
||||||
|
|
||||||
if (this is VisualObject3D && parent is VisualObject3D) {
|
if (this is VisualObject3D && parent is VisualObject3D) {
|
||||||
position = (position ?: GeometryConstants.zero) + (parent.position ?: GeometryConstants.zero)
|
position = (position ?: World.ZERO) + (parent.position ?: World.ZERO)
|
||||||
rotation = (parent.rotation ?: GeometryConstants.zero) + (parent.rotation ?: GeometryConstants.zero)
|
rotation = (parent.rotation ?: World.ZERO) + (parent.rotation ?: World.ZERO)
|
||||||
scale = when {
|
scale = when {
|
||||||
scale == null && parent.scale == null -> null
|
scale == null && parent.scale == null -> null
|
||||||
scale == null -> parent.scale
|
scale == null -> parent.scale
|
||||||
|
@ -1,59 +1,61 @@
|
|||||||
package hep.dataforge.vis.spatial.three
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.get
|
||||||
|
import hep.dataforge.meta.string
|
||||||
import hep.dataforge.output.Renderer
|
import hep.dataforge.output.Renderer
|
||||||
import hep.dataforge.vis.common.Colors
|
import hep.dataforge.vis.common.Colors
|
||||||
|
import hep.dataforge.vis.spatial.Point3D
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D
|
import hep.dataforge.vis.spatial.VisualObject3D
|
||||||
import hep.dataforge.vis.spatial.World
|
import hep.dataforge.vis.spatial.specifications.AxesSpec
|
||||||
|
import hep.dataforge.vis.spatial.specifications.CameraSpec
|
||||||
|
import hep.dataforge.vis.spatial.specifications.CanvasSpec
|
||||||
|
import hep.dataforge.vis.spatial.specifications.ControlsSpec
|
||||||
import info.laht.threekt.WebGLRenderer
|
import info.laht.threekt.WebGLRenderer
|
||||||
import info.laht.threekt.cameras.PerspectiveCamera
|
import info.laht.threekt.cameras.PerspectiveCamera
|
||||||
import info.laht.threekt.external.controls.OrbitControls
|
import info.laht.threekt.external.controls.OrbitControls
|
||||||
import info.laht.threekt.external.controls.TrackballControls
|
import info.laht.threekt.external.controls.TrackballControls
|
||||||
import info.laht.threekt.helpers.AxesHelper
|
import info.laht.threekt.helpers.AxesHelper
|
||||||
import info.laht.threekt.lights.AmbientLight
|
|
||||||
import info.laht.threekt.scenes.Scene
|
import info.laht.threekt.scenes.Scene
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
import kotlin.browser.window
|
import kotlin.browser.window
|
||||||
import kotlin.dom.clear
|
import kotlin.dom.clear
|
||||||
|
import kotlin.math.cos
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
import kotlin.math.sin
|
||||||
|
|
||||||
class ThreeCanvas(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Renderer<VisualObject3D> {
|
class ThreeCanvas(val three: ThreePlugin, val spec: CanvasSpec) : Renderer<VisualObject3D> {
|
||||||
|
|
||||||
override val context: Context get() = three.context
|
override val context: Context get() = three.context
|
||||||
|
|
||||||
var data: VisualObject3D? = null
|
var content: VisualObject3D? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
val axes = AxesHelper(meta["axes.size"].int ?: 50).apply { visible = false }
|
val axes = AxesHelper(spec.axes.size.toInt()).apply {
|
||||||
|
visible = spec.axes.visible
|
||||||
|
}
|
||||||
|
|
||||||
val scene: Scene = Scene().apply {
|
val scene: Scene = Scene().apply {
|
||||||
add(AmbientLight())
|
|
||||||
if (meta["axes.visible"].boolean == true) {
|
|
||||||
axes.visible = true
|
|
||||||
}
|
|
||||||
add(axes)
|
add(axes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildCamera(meta: Meta) = PerspectiveCamera(
|
val camera = buildCamera(spec.camera)
|
||||||
meta["fov"].int ?: 75,
|
|
||||||
meta["aspect"].double ?: 1.0,
|
private fun buildCamera(spec: CameraSpec) = PerspectiveCamera(
|
||||||
meta["nearClip"].double ?: World.CAMERA_NEAR_CLIP,
|
spec.fov,
|
||||||
meta["farClip"].double ?: World.CAMERA_FAR_CLIP
|
1.0,
|
||||||
|
spec.nearClip,
|
||||||
|
spec.farClip
|
||||||
).apply {
|
).apply {
|
||||||
position.setZ(World.CAMERA_INITIAL_DISTANCE)
|
translateX(spec.distance* sin(spec.zenith) * sin(spec.azimuth))
|
||||||
rotation.set(
|
translateY(spec.distance* cos(spec.zenith))
|
||||||
World.CAMERA_INITIAL_X_ANGLE,
|
translateZ(spec.distance * sin(spec.zenith) * cos(spec.azimuth))
|
||||||
World.CAMERA_INITIAL_Y_ANGLE,
|
|
||||||
World.CAMERA_INITIAL_Z_ANGLE
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val camera = buildCamera(meta["camera"].node ?: EmptyMeta)
|
private fun addControls(element: Node, controlsSpec: ControlsSpec) {
|
||||||
|
when (controlsSpec["type"].string) {
|
||||||
private fun addControls(element: Node, meta: Meta) {
|
|
||||||
when (meta["type"].string) {
|
|
||||||
"trackball" -> TrackballControls(camera, element)
|
"trackball" -> TrackballControls(camera, element)
|
||||||
else -> OrbitControls(camera, element)
|
else -> OrbitControls(camera, element)
|
||||||
}
|
}
|
||||||
@ -69,7 +71,7 @@ class ThreeCanvas(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Renderer
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addControls(renderer.domElement, meta["controls"].node ?: EmptyMeta)
|
addControls(renderer.domElement, spec.controls ?: ControlsSpec.empty())
|
||||||
|
|
||||||
fun animate() {
|
fun animate() {
|
||||||
window.requestAnimationFrame {
|
window.requestAnimationFrame {
|
||||||
@ -80,9 +82,7 @@ class ThreeCanvas(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Renderer
|
|||||||
|
|
||||||
element.appendChild(renderer.domElement)
|
element.appendChild(renderer.domElement)
|
||||||
|
|
||||||
val minSize by meta.number(0).int
|
renderer.setSize(max(spec.minSize, element.offsetWidth), max(spec.minSize, element.offsetWidth))
|
||||||
|
|
||||||
renderer.setSize(max(minSize, element.offsetWidth), max(minSize, element.offsetWidth))
|
|
||||||
|
|
||||||
element.onresize = {
|
element.onresize = {
|
||||||
renderer.setSize(element.offsetWidth, element.offsetWidth)
|
renderer.setSize(element.offsetWidth, element.offsetWidth)
|
||||||
@ -93,13 +93,13 @@ class ThreeCanvas(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Renderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(obj: VisualObject3D, meta: Meta) {
|
override fun render(obj: VisualObject3D, meta: Meta) {
|
||||||
data = obj
|
content = obj
|
||||||
scene.add(three.buildObject3D(obj))
|
scene.add(three.buildObject3D(obj))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ThreePlugin.output(element: HTMLElement? = null, meta: Meta = EmptyMeta, override: MetaBuilder.() -> Unit = {}) =
|
fun ThreePlugin.output(element: HTMLElement? = null, spec: CanvasSpec = CanvasSpec.empty()): ThreeCanvas =
|
||||||
ThreeCanvas(this, buildMeta(meta, override)).apply {
|
ThreeCanvas(this, spec).apply {
|
||||||
if (element != null) {
|
if (element != null) {
|
||||||
attach(element)
|
attach(element)
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,35 @@
|
|||||||
package hep.dataforge.vis.spatial.three
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
import hep.dataforge.vis.spatial.Label3D
|
import hep.dataforge.vis.spatial.Label3D
|
||||||
|
import hep.dataforge.vis.spatial.color
|
||||||
import info.laht.threekt.DoubleSide
|
import info.laht.threekt.DoubleSide
|
||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import info.laht.threekt.geometries.PlaneGeometry
|
import info.laht.threekt.geometries.PlaneBufferGeometry
|
||||||
import info.laht.threekt.materials.MeshBasicMaterial
|
import info.laht.threekt.materials.MeshBasicMaterial
|
||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
import info.laht.threekt.textures.Texture
|
import info.laht.threekt.textures.Texture
|
||||||
import org.w3c.dom.CanvasRenderingContext2D
|
import org.w3c.dom.*
|
||||||
import org.w3c.dom.HTMLCanvasElement
|
|
||||||
import kotlin.browser.document
|
import kotlin.browser.document
|
||||||
|
import kotlin.math.PI
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using example from http://stemkoski.github.io/Three.js/Texture-From-Canvas.html
|
* Using example from http://stemkoski.github.io/Three.js/Texture-From-Canvas.html
|
||||||
*/
|
*/
|
||||||
object ThreeTextFactory : ThreeFactory<Label3D> {
|
object ThreeLabelFactory : ThreeFactory<Label3D> {
|
||||||
override val type: KClass<in Label3D> get() = Label3D::class
|
override val type: KClass<in Label3D> get() = Label3D::class
|
||||||
|
|
||||||
override fun invoke(obj: Label3D): Object3D {
|
override fun invoke(obj: Label3D): Object3D {
|
||||||
val canvas = document.createElement("canvas") as HTMLCanvasElement
|
val canvas = document.createElement("canvas") as HTMLCanvasElement
|
||||||
val context = canvas.getContext("2d") as CanvasRenderingContext2D
|
val context = canvas.getContext("2d") as CanvasRenderingContext2D
|
||||||
context.font = "${obj.fontSize}pt ${obj.fontFamily}"
|
context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}"
|
||||||
context.fillStyle = "rgba(255,0,0,0.95)"//obj.material?.color ?: "black"
|
context.fillStyle = obj.color ?: "black"
|
||||||
context.fillText(obj.text, 0.0, 0.0)
|
context.textAlign = CanvasTextAlign.CENTER
|
||||||
|
//context.textBaseline = CanvasTextBaseline.MIDDLE
|
||||||
|
val metrics = context.measureText(obj.text)
|
||||||
|
|
||||||
|
context.fillText(obj.text, 0.5*metrics.width, 0.5*metrics.width)
|
||||||
|
|
||||||
|
|
||||||
// canvas contents will be used for a texture
|
// canvas contents will be used for a texture
|
||||||
val texture = Texture(canvas)
|
val texture = Texture(canvas)
|
||||||
@ -32,14 +38,16 @@ object ThreeTextFactory : ThreeFactory<Label3D> {
|
|||||||
val material = MeshBasicMaterial().apply {
|
val material = MeshBasicMaterial().apply {
|
||||||
map = texture
|
map = texture
|
||||||
side = DoubleSide
|
side = DoubleSide
|
||||||
|
transparent = true
|
||||||
}
|
}
|
||||||
material.transparent = true;
|
|
||||||
|
|
||||||
val mesh = Mesh(
|
val mesh = Mesh(
|
||||||
PlaneGeometry(canvas.clientWidth, canvas.clientHeight),
|
PlaneBufferGeometry(canvas.width, canvas.height),
|
||||||
material
|
material
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//mesh.rotateX(PI)
|
||||||
|
|
||||||
mesh.updatePosition(obj)
|
mesh.updatePosition(obj)
|
||||||
|
|
||||||
return mesh
|
return mesh
|
@ -27,7 +27,7 @@ class ThreePlugin : AbstractPlugin() {
|
|||||||
objectFactories[Sphere::class] = ThreeSphereFactory
|
objectFactories[Sphere::class] = ThreeSphereFactory
|
||||||
objectFactories[ConeSegment::class] = ThreeCylinderFactory
|
objectFactories[ConeSegment::class] = ThreeCylinderFactory
|
||||||
objectFactories[PolyLine::class] = ThreeLineFactory
|
objectFactories[PolyLine::class] = ThreeLineFactory
|
||||||
objectFactories[Label3D::class] = ThreeTextFactory
|
objectFactories[Label3D::class] = ThreeLabelFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
@ -1,51 +1,67 @@
|
|||||||
package hep.dataforge.vis.spatial.three
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
|
import hep.dataforge.js.requireJS
|
||||||
import hep.dataforge.vis.js.editor.card
|
import hep.dataforge.vis.js.editor.card
|
||||||
|
import hep.dataforge.vis.spatial.Visual3DPlugin
|
||||||
|
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||||
import kotlinx.html.InputType
|
import kotlinx.html.InputType
|
||||||
|
import kotlinx.html.TagConsumer
|
||||||
import kotlinx.html.button
|
import kotlinx.html.button
|
||||||
import kotlinx.html.dom.append
|
import kotlinx.html.dom.append
|
||||||
import kotlinx.html.js.*
|
import kotlinx.html.js.*
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
|
import org.w3c.dom.HTMLElement
|
||||||
|
import org.w3c.dom.events.Event
|
||||||
|
import org.w3c.files.Blob
|
||||||
|
import org.w3c.files.BlobPropertyBag
|
||||||
import kotlin.dom.clear
|
import kotlin.dom.clear
|
||||||
|
|
||||||
//private fun download(filename: String, text: String) {
|
private fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) {
|
||||||
// var element = document.createElement("a");
|
event.stopPropagation();
|
||||||
// element.setAttribute("href", "data:text/json;charset=utf-8," + encodeURIComponent(text));
|
event.preventDefault();
|
||||||
// element.setAttribute("download", filename);
|
|
||||||
//
|
|
||||||
// element.style.display = 'none';
|
|
||||||
// document.body.appendChild(element);
|
|
||||||
//
|
|
||||||
// element.click();
|
|
||||||
//
|
|
||||||
// document.body.removeChild(element);
|
|
||||||
//}
|
|
||||||
|
|
||||||
fun Element.threeOutputConfig(canvas: ThreeCanvas) {
|
val fileSaver = requireJS("file-saver")
|
||||||
|
val blob = Blob(arrayOf(dataBuilder()), BlobPropertyBag("$mimeType;charset=utf-8"))
|
||||||
|
fileSaver.saveAs(blob, fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Element.threeSettings(canvas: ThreeCanvas, block: TagConsumer<HTMLElement>.() -> Unit = {}) {
|
||||||
clear()
|
clear()
|
||||||
append {
|
append {
|
||||||
card("Settings"){
|
card("Settings") {
|
||||||
div("row"){
|
div("row") {
|
||||||
div("col-1") {
|
div("col-2") {
|
||||||
label { +"Axes" }
|
label("checkbox-inline") {
|
||||||
input(type = InputType.checkBox).apply {
|
input(type = InputType.checkBox).apply {
|
||||||
checked = canvas.axes.visible
|
checked = canvas.axes.visible
|
||||||
onChangeFunction = {
|
onChangeFunction = {
|
||||||
canvas.axes.visible = checked
|
canvas.axes.visible = checked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
+"Axes"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
div("col-1") {
|
div("col-1") {
|
||||||
button {
|
button {
|
||||||
+"Export"
|
+"Export"
|
||||||
onClickFunction = {
|
onClickFunction = {
|
||||||
|
val json = (canvas.content as? VisualGroup3D)?.let { group ->
|
||||||
|
Visual3DPlugin.json.stringify(
|
||||||
|
VisualGroup3D.serializer(),
|
||||||
|
group
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (json != null) {
|
||||||
|
saveData(it, "object.json", "text/json"){
|
||||||
|
json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
card("Layers"){
|
}
|
||||||
|
}
|
||||||
|
card("Layers") {
|
||||||
div("row") {
|
div("row") {
|
||||||
(0..11).forEach { layer ->
|
(0..11).forEach { layer ->
|
||||||
div("col-1") {
|
div("col-1") {
|
||||||
@ -66,5 +82,6 @@ fun Element.threeOutputConfig(canvas: ThreeCanvas) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
block()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,6 @@ import hep.dataforge.meta.float
|
|||||||
import hep.dataforge.meta.get
|
import hep.dataforge.meta.get
|
||||||
import hep.dataforge.meta.node
|
import hep.dataforge.meta.node
|
||||||
import hep.dataforge.vis.spatial.*
|
import hep.dataforge.vis.spatial.*
|
||||||
import hep.dataforge.vis.spatial.GeometryConstants.zero
|
|
||||||
import info.laht.threekt.core.*
|
import info.laht.threekt.core.*
|
||||||
import info.laht.threekt.external.controls.OrbitControls
|
import info.laht.threekt.external.controls.OrbitControls
|
||||||
import info.laht.threekt.materials.Material
|
import info.laht.threekt.materials.Material
|
||||||
@ -13,6 +12,7 @@ import info.laht.threekt.math.Euler
|
|||||||
import info.laht.threekt.math.Vector3
|
import info.laht.threekt.math.Vector3
|
||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
import info.laht.threekt.textures.Texture
|
import info.laht.threekt.textures.Texture
|
||||||
|
import kotlin.math.PI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for three.kt.
|
* Utility methods for three.kt.
|
||||||
@ -30,6 +30,8 @@ val MetaItem<*>.vector get() = Vector3(node["x"].float ?: 0f, node["y"].float ?:
|
|||||||
|
|
||||||
fun Geometry.toBufferGeometry(): BufferGeometry = BufferGeometry().apply { fromGeometry(this@toBufferGeometry) }
|
fun Geometry.toBufferGeometry(): BufferGeometry = BufferGeometry().apply { fromGeometry(this@toBufferGeometry) }
|
||||||
|
|
||||||
|
internal fun Double.toRadians() = this * PI / 180
|
||||||
|
|
||||||
fun CSG.toGeometry(): Geometry {
|
fun CSG.toGeometry(): Geometry {
|
||||||
val geom = Geometry()
|
val geom = Geometry()
|
||||||
|
|
||||||
@ -45,7 +47,7 @@ fun CSG.toGeometry(): Geometry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (j in 3..polygon.vertices.size) {
|
for (j in 3..polygon.vertices.size) {
|
||||||
val fc = Face3(v0, v0 + j - 2, v0 + j - 1, zero)
|
val fc = Face3(v0, v0 + j - 2, v0 + j - 1, World.ZERO)
|
||||||
fc.vertexNormals = arrayOf(
|
fc.vertexNormals = arrayOf(
|
||||||
Vector3().copy(pvs[0].normal),
|
Vector3().copy(pvs[0].normal),
|
||||||
Vector3().copy(pvs[j - 2].normal),
|
Vector3().copy(pvs[j - 2].normal),
|
||||||
|
@ -2,29 +2,20 @@ package hep.dataforge.vis.spatial.fx
|
|||||||
|
|
||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.context.ContextAware
|
import hep.dataforge.context.ContextAware
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.output.Renderer
|
import hep.dataforge.output.Renderer
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D
|
import hep.dataforge.vis.spatial.VisualObject3D
|
||||||
import hep.dataforge.vis.spatial.World.CAMERA_FAR_CLIP
|
import hep.dataforge.vis.spatial.specifications.CanvasSpec
|
||||||
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_Y_ANGLE
|
|
||||||
import hep.dataforge.vis.spatial.World.CAMERA_NEAR_CLIP
|
|
||||||
import javafx.application.Platform
|
import javafx.application.Platform
|
||||||
import javafx.beans.property.ObjectProperty
|
import javafx.beans.property.ObjectProperty
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
import javafx.event.EventHandler
|
|
||||||
import javafx.scene.*
|
import javafx.scene.*
|
||||||
import javafx.scene.input.KeyCode
|
import javafx.scene.layout.BorderPane
|
||||||
import javafx.scene.input.KeyEvent
|
|
||||||
import javafx.scene.input.MouseEvent
|
|
||||||
import javafx.scene.input.ScrollEvent
|
|
||||||
import javafx.scene.paint.Color
|
import javafx.scene.paint.Color
|
||||||
import org.fxyz3d.scene.Axes
|
import org.fxyz3d.scene.Axes
|
||||||
import org.fxyz3d.utils.CameraTransformer
|
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
class FXCanvas3D(val plugin: FX3DPlugin, meta: Meta = EmptyMeta) :
|
class FXCanvas3D(val plugin: FX3DPlugin, val spec: CanvasSpec) :
|
||||||
Fragment(), Renderer<VisualObject3D>, ContextAware {
|
Fragment(), Renderer<VisualObject3D>, ContextAware {
|
||||||
|
|
||||||
override val context: Context get() = plugin.context
|
override val context: Context get() = plugin.context
|
||||||
@ -32,41 +23,23 @@ class FXCanvas3D(val plugin: FX3DPlugin, meta: Meta = EmptyMeta) :
|
|||||||
val world = Group()
|
val world = Group()
|
||||||
|
|
||||||
val axes = Axes().also {
|
val axes = Axes().also {
|
||||||
it.setHeight(meta["axis.size"].double ?: AXIS_LENGTH)
|
it.setHeight(spec.axes.size)
|
||||||
it.setRadius(meta["axis.width"].double ?: LINE_WIDTH)
|
it.setRadius(spec.axes.width)
|
||||||
it.isVisible = meta["axis.visible"].boolean ?: (meta["axis"] != null)
|
it.isVisible = spec.axes.visible
|
||||||
world.add(it)
|
world.add(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
val light = AmbientLight()
|
val light = AmbientLight()
|
||||||
|
|
||||||
private val camera = PerspectiveCamera().apply {
|
private val camera = PerspectiveCamera().apply {
|
||||||
nearClip = CAMERA_NEAR_CLIP
|
nearClip = spec.camera.nearClip
|
||||||
farClip = CAMERA_FAR_CLIP
|
farClip = spec.camera.farClip
|
||||||
translateZ = CAMERA_INITIAL_DISTANCE
|
fieldOfView = spec.camera.fov.toDouble()
|
||||||
this.add(light)
|
this.add(light)
|
||||||
}
|
}
|
||||||
|
|
||||||
val cameraTransform = CameraTransformer().also {
|
|
||||||
it.add(camera)
|
|
||||||
}
|
|
||||||
|
|
||||||
val translationXProperty get() = cameraTransform.t.xProperty()
|
|
||||||
var translateX by translationXProperty
|
|
||||||
val translationYProperty get() = cameraTransform.t.yProperty()
|
|
||||||
var translateY by translationYProperty
|
|
||||||
val translationZProperty get() = cameraTransform.t.zProperty()
|
|
||||||
var translateZ by translationZProperty
|
|
||||||
|
|
||||||
val rotationXProperty get() = cameraTransform.rx.angleProperty()
|
|
||||||
var angleX by rotationXProperty
|
|
||||||
val rotationYProperty get() = cameraTransform.ry.angleProperty()
|
|
||||||
var angleY by rotationYProperty
|
|
||||||
val rotationZProperty get() = cameraTransform.rz.angleProperty()
|
|
||||||
var angleZ by rotationZProperty
|
|
||||||
|
|
||||||
private val canvas = SubScene(
|
private val canvas = SubScene(
|
||||||
Group(world, cameraTransform).apply { DepthTest.ENABLE },
|
Group(world, camera).apply { DepthTest.ENABLE },
|
||||||
400.0,
|
400.0,
|
||||||
400.0,
|
400.0,
|
||||||
true,
|
true,
|
||||||
@ -74,15 +47,16 @@ class FXCanvas3D(val plugin: FX3DPlugin, meta: Meta = EmptyMeta) :
|
|||||||
).also { scene ->
|
).also { scene ->
|
||||||
scene.fill = Color.GREY
|
scene.fill = Color.GREY
|
||||||
scene.camera = camera
|
scene.camera = camera
|
||||||
//id = "canvas"
|
|
||||||
handleKeyboard(scene)
|
|
||||||
handleMouse(scene)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val root = borderpane {
|
override val root = borderpane {
|
||||||
center = canvas
|
center = canvas
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val controls = camera.orbitControls(canvas, spec.camera).also {
|
||||||
|
world.add(it.centerMarker)
|
||||||
|
}
|
||||||
|
|
||||||
val rootObjectProperty: ObjectProperty<VisualObject3D> = SimpleObjectProperty()
|
val rootObjectProperty: ObjectProperty<VisualObject3D> = SimpleObjectProperty()
|
||||||
var rootObject: VisualObject3D? by rootObjectProperty
|
var rootObject: VisualObject3D? by rootObjectProperty
|
||||||
|
|
||||||
@ -105,99 +79,7 @@ class FXCanvas3D(val plugin: FX3DPlugin, meta: Meta = EmptyMeta) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun handleKeyboard(scene: SubScene) {
|
|
||||||
scene.onKeyPressed = EventHandler<KeyEvent> { event ->
|
|
||||||
if (event.isControlDown) {
|
|
||||||
when (event.code) {
|
|
||||||
KeyCode.Z -> {
|
|
||||||
translateX = 0.0
|
|
||||||
translateY = 0.0
|
|
||||||
camera.translateZ = CAMERA_INITIAL_DISTANCE
|
|
||||||
angleY = CAMERA_INITIAL_Y_ANGLE
|
|
||||||
angleX = CAMERA_INITIAL_X_ANGLE
|
|
||||||
}
|
|
||||||
KeyCode.X -> axes.isVisible = !axes.isVisible
|
|
||||||
// KeyCode.S -> snapshot()
|
|
||||||
// KeyCode.DIGIT1 -> pixelMap.filterKeys { it.getLayerNumber() == 1 }.values.forEach {
|
|
||||||
// toggleTransparency(
|
|
||||||
// it
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// KeyCode.DIGIT2 -> pixelMap.filterKeys { it.getLayerNumber() == 2 }.values.forEach {
|
|
||||||
// toggleTransparency(
|
|
||||||
// it
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// KeyCode.DIGIT3 -> pixelMap.filterKeys { it.getLayerNumber() == 3 }.values.forEach {
|
|
||||||
// toggleTransparency(
|
|
||||||
// it
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
else -> {
|
|
||||||
}//do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleMouse(scene: SubScene) {
|
|
||||||
|
|
||||||
var mousePosX: Double = 0.0
|
|
||||||
var mousePosY: Double = 0.0
|
|
||||||
var mouseOldX: Double = 0.0
|
|
||||||
var mouseOldY: Double = 0.0
|
|
||||||
var mouseDeltaX: Double = 0.0
|
|
||||||
var mouseDeltaY: Double = 0.0
|
|
||||||
|
|
||||||
scene.onMousePressed = EventHandler<MouseEvent> { me ->
|
|
||||||
mousePosX = me.sceneX
|
|
||||||
mousePosY = me.sceneY
|
|
||||||
mouseOldX = me.sceneX
|
|
||||||
mouseOldY = me.sceneY
|
|
||||||
}
|
|
||||||
|
|
||||||
scene.onMouseDragged = EventHandler<MouseEvent> { me ->
|
|
||||||
mouseOldX = mousePosX
|
|
||||||
mouseOldY = mousePosY
|
|
||||||
mousePosX = me.sceneX
|
|
||||||
mousePosY = me.sceneY
|
|
||||||
mouseDeltaX = mousePosX - mouseOldX
|
|
||||||
mouseDeltaY = mousePosY - mouseOldY
|
|
||||||
|
|
||||||
val modifier = when {
|
|
||||||
me.isControlDown -> CONTROL_MULTIPLIER
|
|
||||||
me.isShiftDown -> SHIFT_MULTIPLIER
|
|
||||||
else -> 1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me.isPrimaryButtonDown) {
|
|
||||||
angleY += mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED
|
|
||||||
angleX += mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED
|
|
||||||
} else if (me.isSecondaryButtonDown) {
|
|
||||||
translateX -= mouseDeltaX * MOUSE_SPEED * modifier * TRACK_SPEED
|
|
||||||
translateY -= mouseDeltaY * MOUSE_SPEED * modifier * TRACK_SPEED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scene.onScroll = EventHandler<ScrollEvent> { event ->
|
|
||||||
val z = camera.translateZ
|
|
||||||
val newZ = z + MOUSE_SPEED * event.deltaY * RESIZE_SPEED
|
|
||||||
camera.translateZ = newZ
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun render(obj: VisualObject3D, meta: Meta) {
|
override fun render(obj: VisualObject3D, meta: Meta) {
|
||||||
rootObject = obj
|
rootObject = obj
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val AXIS_LENGTH = 400.0
|
|
||||||
private const val CONTROL_MULTIPLIER = 0.1
|
|
||||||
private const val SHIFT_MULTIPLIER = 10.0
|
|
||||||
private const val MOUSE_SPEED = 0.1
|
|
||||||
private const val ROTATION_SPEED = 2.0
|
|
||||||
private const val TRACK_SPEED = 6.0
|
|
||||||
private const val RESIZE_SPEED = 50.0
|
|
||||||
private const val LINE_WIDTH = 1.0
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,174 @@
|
|||||||
|
package hep.dataforge.vis.spatial.fx
|
||||||
|
|
||||||
|
import hep.dataforge.vis.spatial.specifications.CameraSpec
|
||||||
|
import javafx.beans.InvalidationListener
|
||||||
|
import javafx.beans.property.SimpleDoubleProperty
|
||||||
|
import javafx.event.EventHandler
|
||||||
|
import javafx.geometry.Point3D
|
||||||
|
import javafx.scene.Camera
|
||||||
|
import javafx.scene.Node
|
||||||
|
import javafx.scene.SubScene
|
||||||
|
import javafx.scene.input.MouseEvent
|
||||||
|
import javafx.scene.input.ScrollEvent
|
||||||
|
import javafx.scene.shape.Sphere
|
||||||
|
import javafx.scene.transform.Rotate
|
||||||
|
import javafx.scene.transform.Translate
|
||||||
|
import tornadofx.*
|
||||||
|
import kotlin.math.*
|
||||||
|
|
||||||
|
|
||||||
|
class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec: CameraSpec) {
|
||||||
|
|
||||||
|
val distanceProperty = SimpleDoubleProperty(spec.distance)
|
||||||
|
var distance by distanceProperty
|
||||||
|
|
||||||
|
val azimuthProperty = SimpleDoubleProperty(spec.azimuth)
|
||||||
|
var azimuth by azimuthProperty
|
||||||
|
|
||||||
|
val zenithProperty = SimpleDoubleProperty(PI/2 - spec.latitude)
|
||||||
|
var zenith by zenithProperty
|
||||||
|
|
||||||
|
val latitudeProperty = zenithProperty.unaryMinus().plus(PI/2)
|
||||||
|
val latitude by latitudeProperty
|
||||||
|
|
||||||
|
val baseXProperty = SimpleDoubleProperty(0.0)
|
||||||
|
var x by baseXProperty
|
||||||
|
val baseYProperty = SimpleDoubleProperty(0.0)
|
||||||
|
var y by baseYProperty
|
||||||
|
val baseZProperty = SimpleDoubleProperty(0.0)
|
||||||
|
var z by baseZProperty
|
||||||
|
|
||||||
|
// val basePositionProperty: ObjectBinding<Point3D> =
|
||||||
|
// nonNullObjectBinding(baseXProperty, baseYProperty, baseZProperty) {
|
||||||
|
// Point3D(x, y, z)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val basePosition by basePositionProperty
|
||||||
|
|
||||||
|
val centerMarker by lazy {
|
||||||
|
Sphere(10.0).also {
|
||||||
|
it.translateXProperty().bind(baseXProperty)
|
||||||
|
it.translateYProperty().bind(baseYProperty)
|
||||||
|
it.translateZProperty().bind(baseZProperty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val rx = Rotate(0.0, Rotate.X_AXIS)
|
||||||
|
|
||||||
|
private val ry = Rotate(0.0, Rotate.Y_AXIS)
|
||||||
|
|
||||||
|
private val translate = Translate()
|
||||||
|
|
||||||
|
private val rz = Rotate(180.0, Rotate.Z_AXIS)
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
camera.transforms.setAll(ry, rx, translate,rz)
|
||||||
|
update()
|
||||||
|
val listener = InvalidationListener {
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
distanceProperty.addListener(listener)
|
||||||
|
azimuthProperty.addListener(listener)
|
||||||
|
zenithProperty.addListener(listener)
|
||||||
|
baseXProperty.addListener(listener)
|
||||||
|
baseYProperty.addListener(listener)
|
||||||
|
baseZProperty.addListener(listener)
|
||||||
|
|
||||||
|
canvas.apply {
|
||||||
|
camera.translateXProperty().bind(widthProperty().divide(2))
|
||||||
|
camera.translateZProperty().bind(heightProperty().divide(2))
|
||||||
|
handleMouse()
|
||||||
|
}
|
||||||
|
// coordinateContainer?.vbox {
|
||||||
|
// label(distanceProperty.asString())
|
||||||
|
// label(azimuthProperty.asString())
|
||||||
|
// label(zenithProperty.asString())
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun update() {
|
||||||
|
val spherePosition = Point3D(
|
||||||
|
sin(zenith) * sin(azimuth),
|
||||||
|
cos(zenith),
|
||||||
|
sin(zenith) * cos(azimuth)
|
||||||
|
).times(distance)
|
||||||
|
val basePosition = Point3D(x, y, z)
|
||||||
|
//Create direction vector
|
||||||
|
val cameraPosition = basePosition + spherePosition
|
||||||
|
val camDirection: Point3D = (-spherePosition).normalize()
|
||||||
|
|
||||||
|
val xRotation = Math.toDegrees(asin(-camDirection.y))
|
||||||
|
val yRotation = Math.toDegrees(atan2(camDirection.x, camDirection.z))
|
||||||
|
|
||||||
|
rx.pivotX = cameraPosition.x
|
||||||
|
rx.pivotY = cameraPosition.y
|
||||||
|
rx.pivotZ = cameraPosition.z
|
||||||
|
rx.angle = xRotation
|
||||||
|
|
||||||
|
ry.pivotX = cameraPosition.x
|
||||||
|
ry.pivotY = cameraPosition.y
|
||||||
|
ry.pivotZ = cameraPosition.z
|
||||||
|
ry.angle = yRotation
|
||||||
|
|
||||||
|
translate.x = cameraPosition.x
|
||||||
|
translate.y = cameraPosition.y
|
||||||
|
translate.z = cameraPosition.z
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun Node.handleMouse() {
|
||||||
|
|
||||||
|
var mousePosX = 0.0
|
||||||
|
var mousePosY = 0.0
|
||||||
|
var mouseOldX: Double
|
||||||
|
var mouseOldY: Double
|
||||||
|
var mouseDeltaX: Double
|
||||||
|
var mouseDeltaY: Double
|
||||||
|
|
||||||
|
onMousePressed = EventHandler<MouseEvent> { me ->
|
||||||
|
mousePosX = me.sceneX
|
||||||
|
mousePosY = me.sceneY
|
||||||
|
mouseOldX = me.sceneX
|
||||||
|
mouseOldY = me.sceneY
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseDragged = EventHandler<MouseEvent> { me ->
|
||||||
|
mouseOldX = mousePosX
|
||||||
|
mouseOldY = mousePosY
|
||||||
|
mousePosX = me.sceneX
|
||||||
|
mousePosY = me.sceneY
|
||||||
|
mouseDeltaX = mousePosX - mouseOldX
|
||||||
|
mouseDeltaY = mousePosY - mouseOldY
|
||||||
|
|
||||||
|
val modifier = when {
|
||||||
|
me.isControlDown -> CONTROL_MULTIPLIER
|
||||||
|
me.isShiftDown -> SHIFT_MULTIPLIER
|
||||||
|
else -> 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me.isPrimaryButtonDown) {
|
||||||
|
azimuth -= mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED
|
||||||
|
zenith -= mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED
|
||||||
|
} else if (me.isSecondaryButtonDown) {
|
||||||
|
x += mouseDeltaX * MOUSE_SPEED * modifier * TRACK_SPEED
|
||||||
|
z -= mouseDeltaY * MOUSE_SPEED * modifier * TRACK_SPEED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onScroll = EventHandler<ScrollEvent> { event ->
|
||||||
|
distance = max(1.0, distance - MOUSE_SPEED * event.deltaY * RESIZE_SPEED)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val CONTROL_MULTIPLIER = 0.1
|
||||||
|
private const val SHIFT_MULTIPLIER = 10.0
|
||||||
|
private const val MOUSE_SPEED = 0.1
|
||||||
|
private const val ROTATION_SPEED = 0.02
|
||||||
|
private const val TRACK_SPEED = 6.0
|
||||||
|
private const val RESIZE_SPEED = 10.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Camera.orbitControls(canvas: SubScene, spec: CameraSpec) =
|
||||||
|
OrbitControls(this, canvas, spec)
|
@ -2,7 +2,7 @@ package hep.dataforge.vis.spatial.gdml.demo
|
|||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.js.Application
|
import hep.dataforge.js.Application
|
||||||
import hep.dataforge.js.objectTree
|
import hep.dataforge.vis.js.editor.objectTree
|
||||||
import hep.dataforge.js.startApplication
|
import hep.dataforge.js.startApplication
|
||||||
import hep.dataforge.meta.buildMeta
|
import hep.dataforge.meta.buildMeta
|
||||||
import hep.dataforge.meta.withBottom
|
import hep.dataforge.meta.withBottom
|
||||||
@ -20,7 +20,7 @@ import hep.dataforge.vis.spatial.gdml.LUnit
|
|||||||
import hep.dataforge.vis.spatial.gdml.toVisual
|
import hep.dataforge.vis.spatial.gdml.toVisual
|
||||||
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 hep.dataforge.vis.spatial.three.threeOutputConfig
|
import hep.dataforge.vis.spatial.three.threeSettings
|
||||||
import hep.dataforge.vis.spatial.visible
|
import hep.dataforge.vis.spatial.visible
|
||||||
import kotlinx.html.dom.append
|
import kotlinx.html.dom.append
|
||||||
import kotlinx.html.js.p
|
import kotlinx.html.js.p
|
||||||
@ -157,7 +157,7 @@ private class GDMLDemoApp : Application {
|
|||||||
val output = three.output(canvasElement as HTMLElement)
|
val output = three.output(canvasElement as HTMLElement)
|
||||||
|
|
||||||
output.camera.layers.set(0)
|
output.camera.layers.set(0)
|
||||||
configElement.threeOutputConfig(output)
|
configElement.threeSettings(output)
|
||||||
//tree.visualObjectTree(visual, editor::propertyEditor)
|
//tree.visualObjectTree(visual, editor::propertyEditor)
|
||||||
treeElement.objectTree(NameToken("World"), visual) {
|
treeElement.objectTree(NameToken("World"), visual) {
|
||||||
editorElement.propertyEditor(it) { item ->
|
editorElement.propertyEditor(it) { item ->
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
<title>Three js demo for particle physics</title>
|
<title>Three js demo for particle physics</title>
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
||||||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
<link rel="stylesheet" href="css/ru.mipt.npm.muon.monitor.main.css">
|
<link rel="stylesheet" href="css/main.css">
|
||||||
<link rel="stylesheet" href="css/jsoneditor.min.css">
|
<link rel="stylesheet" href="css/jsoneditor.min.css">
|
||||||
<script type="text/javascript" src="ru.mipt.npm.muon.monitor.main.bundle.js"></script>
|
<script type="text/javascript" src="main.bundle.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="testApp">
|
<body class="testApp">
|
||||||
<div class="container" id="drop_zone" data-toggle="tooltip" data-placement="right"
|
<div class="container" id="drop_zone" data-toggle="tooltip" data-placement="right"
|
||||||
|
@ -20,7 +20,7 @@ kotlin {
|
|||||||
js {
|
js {
|
||||||
browser {
|
browser {
|
||||||
webpackTask {
|
webpackTask {
|
||||||
sourceMaps = false
|
sourceMaps = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ package ru.mipt.npm.muon.monitor
|
|||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.js.Application
|
import hep.dataforge.js.Application
|
||||||
import hep.dataforge.js.objectTree
|
|
||||||
import hep.dataforge.js.startApplication
|
import hep.dataforge.js.startApplication
|
||||||
import hep.dataforge.meta.buildMeta
|
import hep.dataforge.meta.buildMeta
|
||||||
import hep.dataforge.meta.withBottom
|
import hep.dataforge.meta.withBottom
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
|
import hep.dataforge.vis.js.editor.objectTree
|
||||||
import hep.dataforge.vis.js.editor.propertyEditor
|
import hep.dataforge.vis.js.editor.propertyEditor
|
||||||
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
|
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
|
||||||
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY
|
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY
|
||||||
@ -15,11 +15,12 @@ import hep.dataforge.vis.spatial.VisualObject3D
|
|||||||
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
|
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
|
||||||
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 hep.dataforge.vis.spatial.three.threeOutputConfig
|
import hep.dataforge.vis.spatial.three.threeSettings
|
||||||
import hep.dataforge.vis.spatial.visible
|
import hep.dataforge.vis.spatial.visible
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
import kotlin.browser.document
|
import kotlin.browser.document
|
||||||
import kotlin.dom.clear
|
import kotlin.dom.clear
|
||||||
|
import kotlin.math.PI
|
||||||
|
|
||||||
private class GDMLDemoApp : Application {
|
private class GDMLDemoApp : Application {
|
||||||
// /**
|
// /**
|
||||||
@ -59,7 +60,8 @@ private class GDMLDemoApp : Application {
|
|||||||
//val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
|
//val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
|
||||||
|
|
||||||
val canvasElement = document.getElementById("canvas") ?: error("Element with id 'canvas' not found on page")
|
val canvasElement = document.getElementById("canvas") ?: error("Element with id 'canvas' not found on page")
|
||||||
val configElement = document.getElementById("layers") ?: error("Element with id 'layers' not found on page")
|
val settingsElement =
|
||||||
|
document.getElementById("settings") ?: error("Element with id 'settings' not found on page")
|
||||||
val treeElement = document.getElementById("tree") ?: error("Element with id 'tree' not found on page")
|
val treeElement = document.getElementById("tree") ?: error("Element with id 'tree' not found on page")
|
||||||
val editorElement = document.getElementById("editor") ?: error("Element with id 'editor' not found on page")
|
val editorElement = document.getElementById("editor") ?: error("Element with id 'editor' not found on page")
|
||||||
canvasElement.clear()
|
canvasElement.clear()
|
||||||
@ -71,7 +73,9 @@ private class GDMLDemoApp : Application {
|
|||||||
val output = three.output(canvasElement as HTMLElement)
|
val output = three.output(canvasElement as HTMLElement)
|
||||||
|
|
||||||
output.camera.layers.set(0)
|
output.camera.layers.set(0)
|
||||||
configElement.threeOutputConfig(output)
|
output.camera.position.z = -2000.0
|
||||||
|
output.camera.position.y = 500.0
|
||||||
|
settingsElement.threeSettings(output)
|
||||||
//tree.visualObjectTree(visual, editor::propertyEditor)
|
//tree.visualObjectTree(visual, editor::propertyEditor)
|
||||||
treeElement.objectTree(NameToken("World"), visual) {
|
treeElement.objectTree(NameToken("World"), visual) {
|
||||||
editorElement.propertyEditor(it) { item ->
|
editorElement.propertyEditor(it) { item ->
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3" id="tree"></div>
|
<div class="col-lg-3" id="tree"></div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="row" id="layers"></div>
|
<div class="row" id="settings"></div>
|
||||||
<div class="row container" id="canvas"></div>
|
<div class="row" id="canvas"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3" id="editor"></div>
|
<div class="col-lg-3" id="editor"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package hep.dataforge.vis.spatial.demo
|
package hep.dataforge.vis.spatial.demo
|
||||||
|
|
||||||
import hep.dataforge.meta.buildMeta
|
import hep.dataforge.meta.buildMeta
|
||||||
|
import hep.dataforge.meta.invoke
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.output.OutputManager
|
import hep.dataforge.output.OutputManager
|
||||||
import hep.dataforge.vis.common.Colors
|
import hep.dataforge.vis.common.Colors
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.spatial.*
|
import hep.dataforge.vis.spatial.*
|
||||||
|
import hep.dataforge.vis.spatial.specifications.CanvasSpec
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
@ -21,10 +23,22 @@ fun OutputManager.demo(name: String, title: String = name, block: VisualGroup3D.
|
|||||||
output.render(action = block)
|
output.render(action = block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val canvasOptions = CanvasSpec {
|
||||||
|
minSize = 500
|
||||||
|
axes {
|
||||||
|
size = 500.0
|
||||||
|
visible = true
|
||||||
|
}
|
||||||
|
camera {
|
||||||
|
distance = 600.0
|
||||||
|
latitude = PI/6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun OutputManager.showcase() {
|
fun OutputManager.showcase() {
|
||||||
demo("shapes", "Basic shapes") {
|
demo("shapes", "Basic shapes") {
|
||||||
box(100.0, 100.0, 100.0) {
|
box(100.0, 100.0, 100.0) {
|
||||||
z = 110.0
|
z = -110.0
|
||||||
}
|
}
|
||||||
sphere(50.0) {
|
sphere(50.0) {
|
||||||
x = 110
|
x = 110
|
||||||
@ -88,6 +102,7 @@ fun OutputManager.showcase() {
|
|||||||
layer(i * 5, 20 * sin(2 * PI / 100 * i), 20 * cos(2 * PI / 100 * i))
|
layer(i * 5, 20 * sin(2 * PI / 100 * i), 20 * cos(2 * PI / 100 * i))
|
||||||
}
|
}
|
||||||
color(Colors.teal)
|
color(Colors.teal)
|
||||||
|
rotationX = -PI / 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,13 +126,13 @@ fun OutputManager.showcase() {
|
|||||||
box(100, 100, 50) {
|
box(100, 100, 50) {
|
||||||
opacity = 0.3
|
opacity = 0.3
|
||||||
}
|
}
|
||||||
label("Hello, world!",fontSize = 15) {
|
label("Hello, world!", fontSize = 12) {
|
||||||
z = -26
|
z = 26
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun OutputManager.showcaseCSG(){
|
fun OutputManager.showcaseCSG() {
|
||||||
demo("CSG.simple", "CSG operations") {
|
demo("CSG.simple", "CSG operations") {
|
||||||
composite(CompositeType.UNION) {
|
composite(CompositeType.UNION) {
|
||||||
box(100, 100, 100) {
|
box(100, 100, 100) {
|
||||||
|
@ -22,27 +22,27 @@ private class ThreeDemoApp : Application {
|
|||||||
ThreeDemoGrid(element).run {
|
ThreeDemoGrid(element).run {
|
||||||
showcase()
|
showcase()
|
||||||
showcaseCSG()
|
showcaseCSG()
|
||||||
demo("dynamicBox", "Dancing boxes") {
|
// demo("dynamicBox", "Dancing boxes") {
|
||||||
val boxes = (-10..10).flatMap { i ->
|
// val boxes = (-10..10).flatMap { i ->
|
||||||
(-10..10).map { j ->
|
// (-10..10).map { j ->
|
||||||
varBox(10, 10, 0, name = "cell_${i}_${j}") {
|
// varBox(10, 10, 0, name = "cell_${i}_${j}") {
|
||||||
x = i * 10
|
// x = i * 10
|
||||||
y = j * 10
|
// y = j * 10
|
||||||
value = 128
|
// value = 128
|
||||||
setProperty(EDGES_ENABLED_KEY, false)
|
// setProperty(EDGES_ENABLED_KEY, false)
|
||||||
setProperty(WIREFRAME_ENABLED_KEY, false)
|
// setProperty(WIREFRAME_ENABLED_KEY, false)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
GlobalScope.launch {
|
// GlobalScope.launch {
|
||||||
while (isActive) {
|
// while (isActive) {
|
||||||
delay(500)
|
// delay(500)
|
||||||
boxes.forEach { box ->
|
// boxes.forEach { box ->
|
||||||
box.value = (box.value + Random.nextInt(-15, 15)).coerceIn(0..255)
|
// box.value = (box.value + Random.nextInt(-15, 15)).coerceIn(0..255)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,11 +3,15 @@ package hep.dataforge.vis.spatial.demo
|
|||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.get
|
import hep.dataforge.meta.get
|
||||||
|
import hep.dataforge.meta.invoke
|
||||||
import hep.dataforge.meta.string
|
import hep.dataforge.meta.string
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.output.OutputManager
|
import hep.dataforge.output.OutputManager
|
||||||
import hep.dataforge.output.Renderer
|
import hep.dataforge.output.Renderer
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
import hep.dataforge.vis.spatial.specifications.AxesSpec
|
||||||
|
import hep.dataforge.vis.spatial.specifications.CameraSpec
|
||||||
|
import hep.dataforge.vis.spatial.specifications.CanvasSpec
|
||||||
import hep.dataforge.vis.spatial.three.ThreeCanvas
|
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
|
||||||
@ -40,18 +44,14 @@ class ThreeDemoGrid(element: Element, meta: Meta = Meta.EMPTY) : OutputManager {
|
|||||||
|
|
||||||
return outputs.getOrPut(name) {
|
return outputs.getOrPut(name) {
|
||||||
if (type != VisualObject::class) error("Supports only DisplayObject")
|
if (type != VisualObject::class) error("Supports only DisplayObject")
|
||||||
val output = three.output(meta = meta) {
|
lateinit var output: ThreeCanvas
|
||||||
"minSize" put 500
|
|
||||||
"axis" put {
|
|
||||||
"size" put 500
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//TODO calculate cell width here using jquery
|
//TODO calculate cell width here using jquery
|
||||||
gridRoot.append {
|
gridRoot.append {
|
||||||
span("border") {
|
span("border") {
|
||||||
div("col-6") {
|
div("col-6") {
|
||||||
div { id = "output-$name" }.also {
|
div { id = "output-$name" }.also {
|
||||||
output.attach(it)
|
output = three.output(it, canvasOptions)
|
||||||
|
//output.attach(it)
|
||||||
}
|
}
|
||||||
hr()
|
hr()
|
||||||
h2 { +(meta["title"].string ?: name.toString()) }
|
h2 { +(meta["title"].string ?: name.toString()) }
|
||||||
|
@ -4,32 +4,14 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<title>Three js demo for particle physics</title>
|
<title>Three js demo for particle physics</title>
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
|
||||||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
||||||
<script type="text/javascript" src="ru.mipt.npm.muon.monitor.main.bundle.js"></script>
|
<script type="text/javascript" src="main.bundle.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="testApp">
|
<body class="testApp">
|
||||||
<!--
|
|
||||||
<div class="container" id="drop_zone" data-toggle="tooltip" data-placement="right"
|
|
||||||
title="Для загрузки данных в текстовом формате, надо перетащить файл сюда">
|
|
||||||
Загрузить данные
|
|
||||||
<br/>
|
|
||||||
(перетащить файл сюда)
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>Demo grid</h1>
|
<h1>Demo grid</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="container" id="canvas"></div>
|
<div class="container" id="canvas"></div>
|
||||||
|
|
||||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
|
|
||||||
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
|
|
||||||
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
|
|
||||||
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,7 +1,5 @@
|
|||||||
package hep.dataforge.vis.spatial.demo
|
package hep.dataforge.vis.spatial.demo
|
||||||
|
|
||||||
import hep.dataforge.vis.spatial.Material3D
|
|
||||||
import hep.dataforge.vis.spatial.gdml.LUnit
|
|
||||||
import hep.dataforge.vis.spatial.gdml.gdml
|
import hep.dataforge.vis.spatial.gdml.gdml
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
@ -14,22 +12,12 @@ class FXDemoApp : App(FXDemoGrid::class) {
|
|||||||
override fun start(stage: Stage) {
|
override fun start(stage: Stage) {
|
||||||
super.start(stage)
|
super.start(stage)
|
||||||
|
|
||||||
stage.width = 400.0
|
stage.width = 600.0
|
||||||
stage.height = 400.0
|
stage.height = 600.0
|
||||||
|
|
||||||
//view.showcase()
|
view.showcase()
|
||||||
view.demo("gdml", "gdml") {
|
view.demo("gdml", "gdml-cubes") {
|
||||||
gdml(Paths.get("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.gdml")) {
|
gdml(Paths.get("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.gdml"))
|
||||||
lUnit = LUnit.CM
|
|
||||||
|
|
||||||
solidConfiguration = { parent, solid ->
|
|
||||||
if (parent.physVolumes.isNotEmpty()) {
|
|
||||||
useStyle("opaque") {
|
|
||||||
Material3D.MATERIAL_OPACITY_KEY put 0.3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//setProperty(Material3D.MATERIAL_WIREFRAME_KEY, true)
|
//setProperty(Material3D.MATERIAL_WIREFRAME_KEY, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,15 @@ import hep.dataforge.output.Renderer
|
|||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.spatial.fx.FX3DPlugin
|
import hep.dataforge.vis.spatial.fx.FX3DPlugin
|
||||||
import hep.dataforge.vis.spatial.fx.FXCanvas3D
|
import hep.dataforge.vis.spatial.fx.FXCanvas3D
|
||||||
|
import hep.dataforge.vis.spatial.specifications.AxesSpec
|
||||||
|
import hep.dataforge.vis.spatial.specifications.CanvasSpec
|
||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
import javafx.scene.Parent
|
import javafx.scene.Parent
|
||||||
import javafx.scene.control.Tab
|
import javafx.scene.control.Tab
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
class FXDemoGrid : View(), OutputManager {
|
class FXDemoGrid : View(title = "DataForge-vis FX demo"), OutputManager {
|
||||||
private val outputs = FXCollections.observableHashMap<Name, FXCanvas3D>()
|
private val outputs = FXCollections.observableHashMap<Name, FXCanvas3D>()
|
||||||
|
|
||||||
override val root: Parent = borderpane {
|
override val root: Parent = borderpane {
|
||||||
@ -32,13 +34,7 @@ class FXDemoGrid : View(), OutputManager {
|
|||||||
override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Renderer<T> {
|
override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Renderer<T> {
|
||||||
return outputs.getOrPut(name) {
|
return outputs.getOrPut(name) {
|
||||||
if (type != VisualObject::class) kotlin.error("Supports only DisplayObject")
|
if (type != VisualObject::class) kotlin.error("Supports only DisplayObject")
|
||||||
val customMeta = buildMeta(meta) {
|
val output = FXCanvas3D(fx3d, canvasOptions)
|
||||||
"minSize" put 500
|
|
||||||
"axis" put {
|
|
||||||
"size" put 500
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val output = FXCanvas3D(fx3d, customMeta)
|
|
||||||
|
|
||||||
output
|
output
|
||||||
} as Renderer<T>
|
} as Renderer<T>
|
||||||
|
Loading…
Reference in New Issue
Block a user