diff --git a/visionforge-threejs/build.gradle.kts b/visionforge-threejs/build.gradle.kts index 86b8702c..8be1b7a1 100644 --- a/visionforge-threejs/build.gradle.kts +++ b/visionforge-threejs/build.gradle.kts @@ -10,6 +10,6 @@ kotlin{ dependencies { api(project(":visionforge-solid")) - implementation(npm("three", "0.137.5")) + implementation(npm("three", "0.143.0")) implementation(npm("three-csg-ts", "3.1.10")) } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt index 586abe32..747b722a 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt @@ -212,7 +212,7 @@ public class ThreeCanvas( } //find first non-static parent in this object ancestry - private fun Object3D?.upTrace(): Object3D? = if (this?.name?.startsWith("@") == true) parent else this + private tailrec fun Object3D.upTrace(): Object3D? = if (!name.startsWith("@")) this else parent?.upTrace() private fun pick(): Object3D? { // update the picking ray with the camera and mouse position @@ -222,8 +222,8 @@ public class ThreeCanvas( return root?.let { root -> val intersects = raycaster.intersectObject(root, true) //skip invisible objects - val obj = intersects.map { it.`object` }.firstOrNull { it.visible } - obj.upTrace() + val obj: Object3D? = intersects.map { it.`object` }.firstOrNull { it.visible } + obj?.upTrace() } } @@ -280,20 +280,22 @@ public class ThreeCanvas( edgesName: String, material: LineBasicMaterial = SELECTED_MATERIAL, ) { + if (userData[DO_NOT_HIGHLIGHT_TAG] == true) { return } - if (this is Mesh) { - val edges = getObjectByName(edgesName) ?: LineSegments( + + if (isMesh(this)) { + val highlightMesh = getObjectByName(edgesName) ?: LineSegments( EdgesGeometry(geometry), material ).also { it.name = edgesName add(it) } - edges.visible = highlight + highlightMesh.visible = highlight } else { - children.filter { it.name != edgesName }.forEach { + children.filter { !it.name.startsWith("@") && it.name != edgesName }.forEach { it.toggleHighlight(highlight, edgesName, material) } } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt index 5c4c6cd5..0f38640c 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt @@ -3,7 +3,6 @@ package space.kscience.visionforge.solid.three import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.Object3D import info.laht.threekt.math.Euler -import info.laht.threekt.objects.Mesh import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.startsWith @@ -50,7 +49,7 @@ public fun Object3D.updatePosition(vision: Vision) { // setRotationFromEuler( Euler(obj.rotationX, obj.rotationY, obj.rotationZ, obj.rotationOrder.name)) // } - setRotationFromEuler( Euler(vision.rotationX, vision.rotationY, vision.rotationZ, vision.rotationOrder.name)) + setRotationFromEuler(Euler(vision.rotationX, vision.rotationY, vision.rotationZ, vision.rotationOrder.name)) scale.set(vision.scaleX, vision.scaleY, vision.scaleZ) updateMatrix() @@ -62,7 +61,7 @@ public fun Object3D.updatePosition(vision: Vision) { */ public fun Object3D.updateProperty(source: Vision, propertyName: Name) { // console.log("$source updated $propertyName with ${source.computeProperty(propertyName)}") - if (this is Mesh && propertyName.startsWith(MATERIAL_KEY)) { + if (isMesh(this) && propertyName.startsWith(MATERIAL_KEY)) { updateMaterialProperty(source, propertyName) } else if ( propertyName.startsWith(Solid.POSITION_KEY) diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMaterials.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMaterials.kt index 57e90750..3826f11d 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMaterials.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMaterials.kt @@ -39,13 +39,13 @@ public object ThreeMaterials { public val SELECTED_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply { color.set(Colors.ivory) - linewidth = 8.0 + linewidth = 2.0 cached = true } public val HIGHLIGHT_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply { color.set(Colors.blue) - linewidth = 8.0 + linewidth = 2.0 cached = true } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt index 96fa2621..1a68985f 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt @@ -17,6 +17,7 @@ import space.kscience.visionforge.solid.SolidMaterial import space.kscience.visionforge.solid.layer import space.kscience.visionforge.solid.three.ThreeMeshFactory.Companion.EDGES_ENABLED_KEY import space.kscience.visionforge.solid.three.ThreeMeshFactory.Companion.EDGES_MATERIAL_KEY +import space.kscience.visionforge.solid.three.ThreeMeshFactory.Companion.EDGES_OBJECT_NAME import kotlin.reflect.KClass /** @@ -66,6 +67,7 @@ public abstract class ThreeMeshFactory( public companion object { public val EDGES_KEY: Name = "edges".asName() + internal const val EDGES_OBJECT_NAME: String = "@edges" //public val WIREFRAME_KEY: Name = "wireframe".asName() public val ENABLED_KEY: Name = "enabled".asName() @@ -93,7 +95,7 @@ internal fun Mesh.applyProperties(vision: Solid): Mesh = apply { } public fun Mesh.applyEdges(vision: Solid) { - val edges = children.find { it.name == "@edges" } as? LineSegments + val edges = children.find { it.name == EDGES_OBJECT_NAME } as? LineSegments //inherited edges definition, enabled by default if (vision.properties.getValue(EDGES_ENABLED_KEY, inherit = true)?.boolean != false) { val bufferGeometry = geometry as? BufferGeometry ?: return @@ -104,7 +106,7 @@ public fun Mesh.applyEdges(vision: Solid) { EdgesGeometry(bufferGeometry), material ).apply { - name = "@edges" + name = EDGES_OBJECT_NAME } ) } else { diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt index ec60ddb3..b0e1d69c 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt @@ -17,11 +17,10 @@ public object ThreeReferenceFactory : ThreeFactory { override val type: KClass = SolidReference::class private fun Object3D.replicate(): Object3D { - return when (this) { - is Mesh -> Mesh(geometry, material).also { + return when { + isMesh(this) -> Mesh(geometry, material).also { it.applyMatrix4(matrix) } - else -> clone(false) }.also { obj: Object3D -> obj.name = this.name @@ -40,7 +39,7 @@ public object ThreeReferenceFactory : ThreeFactory { val object3D: Object3D = cachedObject.replicate() object3D.updatePosition(vision) - if (object3D is Mesh) { + if (isMesh(object3D)) { //object3D.material = ThreeMaterials.buildMaterial(obj.getProperty(SolidMaterial.MATERIAL_KEY).node!!) object3D.applyProperties(vision) } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/three.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/three.kt index d21ff544..94262052 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/three.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/three.kt @@ -11,6 +11,7 @@ import info.laht.threekt.textures.Texture import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.float import space.kscience.dataforge.meta.get +import kotlin.contracts.contract import kotlin.math.PI public val Meta.vector: Vector3 get() = Vector3(this["x"].float ?: 0f, this["y"].float ?: 0f, this["z"].float ?: 0f) @@ -34,6 +35,14 @@ internal fun Any.dispose() { public fun Layers.check(layer: Int): Boolean = (mask shr (layer) and 0x00000001) > 0 + +internal fun isMesh(object3D: Object3D): Boolean{ + contract { + returns(true) implies (object3D is Mesh) + } + return object3D.asDynamic().isMesh as? Boolean ?: false +} + internal fun Object3D.takeIfMesh(): Mesh? { val d = asDynamic() return if(d.isMesh as Boolean){