forked from kscience/visionforge
Working on convex geometry for three
This commit is contained in:
parent
c2d15ded20
commit
a7432a2b33
@ -18,8 +18,8 @@ configure<KotlinFrontendExtension> {
|
||||
downloadNodeJsVersion = "latest"
|
||||
|
||||
configure<NpmExtension> {
|
||||
dependency("three")
|
||||
dependency("three-orbitcontrols")
|
||||
dependency("three-full")
|
||||
//dependency("three-orbitcontrols")
|
||||
dependency("style-loader")
|
||||
devDependency("karma")
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ class ThreeDemoApp : ApplicationBase() {
|
||||
override val stateKeys: List<String> = emptyList()
|
||||
|
||||
override fun start(state: Map<String, Any>) {
|
||||
//require("three-full")
|
||||
//require("three/examples/js/geometries/ConvexGeometry")
|
||||
|
||||
val renderer = ThreeOutput(Global)
|
||||
renderer.start(document.getElementById("canvas")!!)
|
||||
println("started")
|
||||
@ -39,6 +42,17 @@ class ThreeDemoApp : ApplicationBase() {
|
||||
properties.style["color"] = 1530
|
||||
}
|
||||
}
|
||||
convex {
|
||||
point(50,50,-50)
|
||||
point(50,-50,-50)
|
||||
point(-50,-50,-50)
|
||||
point(-50,50,-50)
|
||||
point(50,50,50)
|
||||
point(50,-50,50)
|
||||
point(-50,-50,50)
|
||||
point(-50,50,50)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var color by group.properties.number(1530).int
|
||||
|
@ -0,0 +1,87 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.vis.DisplayObject
|
||||
import hep.dataforge.vis.get
|
||||
import hep.dataforge.vis.onChange
|
||||
import hep.dataforge.vis.spatial.three.ConvexGeometry
|
||||
import hep.dataforge.vis.spatial.three.EdgesGeometry
|
||||
import hep.dataforge.vis.spatial.three.euler
|
||||
import info.laht.threekt.core.Object3D
|
||||
import info.laht.threekt.geometries.BoxBufferGeometry
|
||||
import info.laht.threekt.math.Vector3
|
||||
import info.laht.threekt.objects.LineSegments
|
||||
import info.laht.threekt.objects.Mesh
|
||||
|
||||
/**
|
||||
* Builder and updater for three.js object
|
||||
*/
|
||||
interface ThreeObjectBuilder<in T : DisplayObject> {
|
||||
|
||||
operator fun invoke(obj: T): Object3D
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Update position, rotation and visibility
|
||||
*/
|
||||
internal fun updatePosition(obj: DisplayObject, target: Object3D) {
|
||||
target.apply {
|
||||
position.set(obj.x, obj.y, obj.z)
|
||||
setRotationFromEuler(obj.euler)
|
||||
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
|
||||
visible = obj.visible
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class GenericThreeBuilder<in T : DisplayObject, R : Object3D> : ThreeObjectBuilder<T> {
|
||||
/**
|
||||
* Build an object
|
||||
*/
|
||||
abstract fun build(obj: T): R
|
||||
|
||||
/**
|
||||
* Update an object
|
||||
*/
|
||||
abstract fun update(obj: T, target: R)
|
||||
|
||||
override fun invoke(obj: T): R {
|
||||
val target = build(obj)
|
||||
ThreeObjectBuilder.updatePosition(obj, target)
|
||||
obj.onChange(this) { _, _, _ ->
|
||||
ThreeObjectBuilder.updatePosition(obj, target)
|
||||
update(obj, target)
|
||||
}
|
||||
return target
|
||||
}
|
||||
}
|
||||
|
||||
object ThreeBoxBuilder : GenericThreeBuilder<Box, Mesh>() {
|
||||
override fun build(obj: Box): Mesh {
|
||||
val geometry = BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
|
||||
return Mesh(geometry, obj["color"].material()).also { mesh ->
|
||||
mesh.add(LineSegments(EdgesGeometry(geometry), Materials.DEFAULT))
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(obj: Box, target: Mesh) {
|
||||
target.geometry = BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
|
||||
target.material = obj["color"].material()
|
||||
}
|
||||
}
|
||||
|
||||
fun Point3D.asVector(): Vector3 = this.asDynamic() as Vector3
|
||||
|
||||
object ThreeConvexBuilder: GenericThreeBuilder<Convex,Mesh>(){
|
||||
override fun build(obj: Convex): Mesh {
|
||||
val geometry = ConvexGeometry(obj.points.map { it.asVector() }.toTypedArray())
|
||||
return Mesh(geometry, obj["color"].material()).also { mesh ->
|
||||
mesh.add(LineSegments(EdgesGeometry(geometry), Materials.DEFAULT))
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(obj: Convex, target: Mesh) {
|
||||
target.geometry = ConvexGeometry(obj.points.map { it.asVector() }.toTypedArray())
|
||||
target.material = obj["color"].material()
|
||||
}
|
||||
}
|
@ -5,18 +5,13 @@ import hep.dataforge.io.Output
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.vis.DisplayGroup
|
||||
import hep.dataforge.vis.DisplayObject
|
||||
import hep.dataforge.vis.get
|
||||
import hep.dataforge.vis.onChange
|
||||
import hep.dataforge.vis.spatial.three.Group
|
||||
import info.laht.threekt.WebGLRenderer
|
||||
import info.laht.threekt.cameras.PerspectiveCamera
|
||||
import info.laht.threekt.core.Object3D
|
||||
import info.laht.threekt.external.controls.OrbitControls
|
||||
import info.laht.threekt.geometries.BoxBufferGeometry
|
||||
import info.laht.threekt.geometries.WireframeGeometry
|
||||
import info.laht.threekt.lights.AmbientLight
|
||||
import info.laht.threekt.math.ColorConstants
|
||||
import info.laht.threekt.objects.LineSegments
|
||||
import info.laht.threekt.objects.Mesh
|
||||
import info.laht.threekt.scenes.Scene
|
||||
import org.w3c.dom.Element
|
||||
import kotlin.browser.window
|
||||
@ -66,47 +61,24 @@ class ThreeOutput(override val context: Context) : Output<DisplayObject> {
|
||||
|
||||
|
||||
private fun buildNode(obj: DisplayObject): Object3D? {
|
||||
|
||||
// general properties updater
|
||||
val updateProperties: Object3D.(DisplayObject) -> Unit = {
|
||||
position.set(obj.x, obj.y, obj.z)
|
||||
setRotationFromEuler(obj.euler)
|
||||
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
|
||||
visible = obj.visible
|
||||
}
|
||||
|
||||
return when (obj) {
|
||||
is DisplayGroup -> Group(obj.children.mapNotNull { buildNode(it) })
|
||||
is Box -> {
|
||||
val geometry = BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
|
||||
val update: Mesh.(Box) -> Unit = { box ->
|
||||
this.geometry = BoxBufferGeometry(box.xSize, box.ySize, box.zSize)
|
||||
material = box["color"].material()
|
||||
}
|
||||
Mesh(geometry, obj["color"].material()).also { mesh ->
|
||||
//TODO replace by edges after adding it to three.kt
|
||||
mesh.add(LineSegments(WireframeGeometry(geometry),Materials.DEFAULT))
|
||||
obj.onChange(this) { _, _, _ ->
|
||||
mesh.updateProperties(obj)
|
||||
mesh.update(obj)
|
||||
}
|
||||
}
|
||||
is DisplayGroup -> Group(obj.children.mapNotNull { buildNode(it) }).apply {
|
||||
ThreeObjectBuilder.updatePosition(obj, this)
|
||||
}
|
||||
else -> {
|
||||
logger.error { "No renderer defined for ${obj::class}" }
|
||||
return null
|
||||
}
|
||||
}.apply {
|
||||
updateProperties(obj)
|
||||
is Box -> ThreeBoxBuilder(obj)
|
||||
//is Convex -> ThreeConvexBuilder(obj)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun render(obj: DisplayObject, meta: Meta) {
|
||||
buildNode(obj)?.let {
|
||||
scene.add(it)
|
||||
}
|
||||
} ?: error("Renderer for ${obj::class} not found")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// init {
|
||||
// val cube: Mesh
|
||||
//
|
||||
@ -142,6 +114,4 @@ class ThreeOutput(override val context: Context) : Output<DisplayObject> {
|
||||
//
|
||||
// // Create the final object to add to the scene
|
||||
// Line(geometry, material).apply(scene::add)
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
@ -0,0 +1,7 @@
|
||||
@file:JsQualifier("THREE")
|
||||
package hep.dataforge.vis.spatial.three
|
||||
|
||||
import info.laht.threekt.core.BufferGeometry
|
||||
import info.laht.threekt.math.Vector3
|
||||
|
||||
external class ConvexGeometry(points: Array<Vector3>) : BufferGeometry
|
@ -0,0 +1,11 @@
|
||||
@file:JsModule("three")
|
||||
@file:JsNonModule
|
||||
|
||||
package hep.dataforge.vis.spatial.three
|
||||
|
||||
import info.laht.threekt.core.BufferGeometry
|
||||
import info.laht.threekt.core.Geometry
|
||||
|
||||
external class EdgesGeometry(geometry: Geometry, thresholdAngle: Int = definedExternally) : BufferGeometry {
|
||||
constructor(geometry: BufferGeometry, thresholdAngle: Int = definedExternally)
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
package hep.dataforge.vis.spatial.three
|
||||
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.meta.float
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.node
|
||||
import hep.dataforge.vis.DisplayObject
|
||||
import hep.dataforge.vis.spatial.rotationOrder
|
||||
import hep.dataforge.vis.spatial.rotationX
|
||||
import hep.dataforge.vis.spatial.rotationY
|
||||
import hep.dataforge.vis.spatial.rotationZ
|
||||
import info.laht.threekt.core.Object3D
|
||||
import info.laht.threekt.math.Euler
|
||||
import info.laht.threekt.math.Vector3
|
@ -0,0 +1,41 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.vis.DisplayGroup
|
||||
import hep.dataforge.vis.DisplayLeaf
|
||||
import hep.dataforge.vis.DisplayObject
|
||||
|
||||
class Convex(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) {
|
||||
|
||||
val points = points(properties["points"] ?: error("Vertices not defined"))
|
||||
|
||||
companion object {
|
||||
const val TYPE = "geometry.spatial.convex"
|
||||
|
||||
fun points(item: MetaItem<*>): List<Point3D> {
|
||||
return item.node?.getAll("point".toName())?.map { (_, value) ->
|
||||
Point3D(value.node["x"].number ?: 0, value.node["y"].number ?: 0, value.node["y"].number ?: 0)
|
||||
} ?: emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun DisplayGroup.convex(meta: Meta = EmptyMeta, action: ConvexBuilder.() -> Unit = {}) =
|
||||
ConvexBuilder().apply(action).build(this, meta).also { addChild(it) }
|
||||
|
||||
class ConvexBuilder {
|
||||
private val points = ArrayList<Point3D>()
|
||||
|
||||
fun point(x: Number, y: Number, z: Number) {
|
||||
points.add(Point3D(x, y, z))
|
||||
}
|
||||
|
||||
fun build(parent: DisplayObject?, meta: Meta): Convex {
|
||||
val builder = meta.builder()
|
||||
points.forEachIndexed { index, value ->
|
||||
builder["points.point[$index]"] = value.toMeta()
|
||||
}
|
||||
return Convex(parent, builder.seal())
|
||||
}
|
||||
}
|
@ -1,6 +1,18 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaRepr
|
||||
import hep.dataforge.meta.buildMeta
|
||||
|
||||
|
||||
data class Point2D(val x: Number, val y: Number)
|
||||
|
||||
typealias Shape2D = List<Point2D>
|
||||
typealias Shape2D = List<Point2D>
|
||||
|
||||
data class Point3D(val x: Number, val y: Number, val z: Number): MetaRepr{
|
||||
override fun toMeta(): Meta = buildMeta {
|
||||
"x" to x
|
||||
"y" to y
|
||||
"z" to z
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user