Working on convex geometry for three
This commit is contained in:
parent
c2d15ded20
commit
a7432a2b33
@ -18,8 +18,8 @@ configure<KotlinFrontendExtension> {
|
|||||||
downloadNodeJsVersion = "latest"
|
downloadNodeJsVersion = "latest"
|
||||||
|
|
||||||
configure<NpmExtension> {
|
configure<NpmExtension> {
|
||||||
dependency("three")
|
dependency("three-full")
|
||||||
dependency("three-orbitcontrols")
|
//dependency("three-orbitcontrols")
|
||||||
dependency("style-loader")
|
dependency("style-loader")
|
||||||
devDependency("karma")
|
devDependency("karma")
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,9 @@ class ThreeDemoApp : ApplicationBase() {
|
|||||||
override val stateKeys: List<String> = emptyList()
|
override val stateKeys: List<String> = emptyList()
|
||||||
|
|
||||||
override fun start(state: Map<String, Any>) {
|
override fun start(state: Map<String, Any>) {
|
||||||
|
//require("three-full")
|
||||||
|
//require("three/examples/js/geometries/ConvexGeometry")
|
||||||
|
|
||||||
val renderer = ThreeOutput(Global)
|
val renderer = ThreeOutput(Global)
|
||||||
renderer.start(document.getElementById("canvas")!!)
|
renderer.start(document.getElementById("canvas")!!)
|
||||||
println("started")
|
println("started")
|
||||||
@ -39,6 +42,17 @@ class ThreeDemoApp : ApplicationBase() {
|
|||||||
properties.style["color"] = 1530
|
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
|
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.meta.Meta
|
||||||
import hep.dataforge.vis.DisplayGroup
|
import hep.dataforge.vis.DisplayGroup
|
||||||
import hep.dataforge.vis.DisplayObject
|
import hep.dataforge.vis.DisplayObject
|
||||||
import hep.dataforge.vis.get
|
import hep.dataforge.vis.spatial.three.Group
|
||||||
import hep.dataforge.vis.onChange
|
|
||||||
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.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import info.laht.threekt.external.controls.OrbitControls
|
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.lights.AmbientLight
|
||||||
import info.laht.threekt.math.ColorConstants
|
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 info.laht.threekt.scenes.Scene
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import kotlin.browser.window
|
import kotlin.browser.window
|
||||||
@ -66,47 +61,24 @@ class ThreeOutput(override val context: Context) : Output<DisplayObject> {
|
|||||||
|
|
||||||
|
|
||||||
private fun buildNode(obj: DisplayObject): Object3D? {
|
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) {
|
return when (obj) {
|
||||||
is DisplayGroup -> Group(obj.children.mapNotNull { buildNode(it) })
|
is DisplayGroup -> Group(obj.children.mapNotNull { buildNode(it) }).apply {
|
||||||
is Box -> {
|
ThreeObjectBuilder.updatePosition(obj, this)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> {
|
is Box -> ThreeBoxBuilder(obj)
|
||||||
logger.error { "No renderer defined for ${obj::class}" }
|
//is Convex -> ThreeConvexBuilder(obj)
|
||||||
return null
|
else -> null
|
||||||
}
|
|
||||||
}.apply {
|
|
||||||
updateProperties(obj)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun render(obj: DisplayObject, meta: Meta) {
|
override fun render(obj: DisplayObject, meta: Meta) {
|
||||||
buildNode(obj)?.let {
|
buildNode(obj)?.let {
|
||||||
scene.add(it)
|
scene.add(it)
|
||||||
}
|
} ?: error("Renderer for ${obj::class} not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// init {
|
// init {
|
||||||
// val cube: Mesh
|
// val cube: Mesh
|
||||||
//
|
//
|
||||||
@ -143,5 +115,3 @@ class ThreeOutput(override val context: Context) : Output<DisplayObject> {
|
|||||||
// // Create the final object to add to the scene
|
// // Create the final object to add to the scene
|
||||||
// Line(geometry, material).apply(scene::add)
|
// 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.MetaItem
|
||||||
import hep.dataforge.meta.float
|
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.DisplayObject
|
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.core.Object3D
|
||||||
import info.laht.threekt.math.Euler
|
import info.laht.threekt.math.Euler
|
||||||
import info.laht.threekt.math.Vector3
|
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
|
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)
|
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