Working on convex geometry for three

This commit is contained in:
Alexander Nozik 2019-03-09 11:39:01 +03:00
parent c2d15ded20
commit a7432a2b33
9 changed files with 190 additions and 44 deletions

View File

@ -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")
}

View File

@ -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

View File

@ -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()
}
}

View File

@ -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
//
@ -143,5 +115,3 @@ class ThreeOutput(override val context: Context) : Output<DisplayObject> {
// // Create the final object to add to the scene
// Line(geometry, material).apply(scene::add)
// }
}

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -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())
}
}

View File

@ -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>
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
}
}