From 7b30b62849c60c7a7aaec7508b9f74e23bbfaa4b Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 11 Jul 2021 13:43:56 +0300 Subject: [PATCH] Reimplemented coordinates as properties --- .../visionforge/solid/FXCompositeFactory.kt | 2 +- .../visionforge/gdml/GdmlOptimizer.kt | 75 ------------------- ...mlTransformerEnv.kt => GdmlTransformer.kt} | 31 ++++---- .../space/kscience/visionforge/gdml/gdmlJs.kt | 8 -- .../kscience/visionforge/gdml/gdmlJVM.kt | 3 - .../kscience/visionforge/solid/Composite.kt | 3 +- .../space/kscience/visionforge/solid/Solid.kt | 67 +++++++++++------ .../solid/transform/RemoveSingleChild.kt | 45 ++++++----- .../visionforge/solid/transform/UnRef.kt | 2 +- .../laht/threekt/utils/BufferGeometryUtils.kt | 15 ++++ .../solid/three/ThreeCompositeFactory.kt | 6 +- 11 files changed, 107 insertions(+), 150 deletions(-) delete mode 100644 visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlOptimizer.kt rename visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/{GdmlTransformerEnv.kt => GdmlTransformer.kt} (95%) delete mode 100644 visionforge-gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/gdmlJs.kt create mode 100644 visionforge-threejs/src/main/kotlin/info/laht/threekt/utils/BufferGeometryUtils.kt diff --git a/visionforge-fx/src/main/kotlin/space/kscience/visionforge/solid/FXCompositeFactory.kt b/visionforge-fx/src/main/kotlin/space/kscience/visionforge/solid/FXCompositeFactory.kt index 5aa7619e..663a927b 100644 --- a/visionforge-fx/src/main/kotlin/space/kscience/visionforge/solid/FXCompositeFactory.kt +++ b/visionforge-fx/src/main/kotlin/space/kscience/visionforge/solid/FXCompositeFactory.kt @@ -48,7 +48,7 @@ class FXCompositeFactory(val plugin: FX3DPlugin) : FX3DFactory { val firstCSG = first.toCSG() val secondCSG = second.toCSG() val resultCSG = when (obj.compositeType) { - CompositeType.UNION -> firstCSG.union(secondCSG) + CompositeType.SUM, CompositeType.UNION -> firstCSG.union(secondCSG) CompositeType.INTERSECT -> firstCSG.intersect(secondCSG) CompositeType.SUBTRACT -> firstCSG.difference(secondCSG) } diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlOptimizer.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlOptimizer.kt deleted file mode 100644 index b2075e3a..00000000 --- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlOptimizer.kt +++ /dev/null @@ -1,75 +0,0 @@ -package space.kscience.visionforge.gdml - -import space.kscience.dataforge.meta.itemSequence -import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.Vision -import space.kscience.visionforge.meta -import space.kscience.visionforge.solid.* - -public expect class Counter() { - public fun get(): Int - public fun incrementAndGet(): Int -} - -@DFExperimental -internal fun Vision.updateFrom(other: Vision): Vision { - if (this is Solid && other is Solid) { - position += other.position - rotation += other.rotation - scaleX = scaleX.toDouble() * other.scaleX.toDouble() - scaleY = scaleY.toDouble() * other.scaleY.toDouble() - scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble() - other.meta.itemSequence().forEach { (name, item) -> - if (getProperty(name) == null) { - setProperty(name, item) - } - } - } - return this -} -// -//@DFExperimental -//private class GdmlOptimizer() : VisionVisitor { -// val logger = KotlinLogging.logger("SingleChildReducer") -// -// private val depthCount = HashMap() -// -// override suspend fun visit(name: Name, vision: Vision) { -// val depth = name.length -// depthCount.getOrPut(depth) { Counter() }.incrementAndGet() -// } -// -// override fun skip(name: Name, vision: Vision): Boolean = vision is Proxy.ProxyChild -// -// override suspend fun visitChildren(name: Name, group: VisionGroup) { -// if (name == "volumes".toName()) return -// if (group !is MutableVisionGroup) return -// -// val newChildren = group.children.entries.associate { (visionToken, vision) -> -// //Reduce single child groups -// if (vision is VisionGroup && vision !is Proxy && vision.children.size == 1) { -// val (token, child) = vision.children.entries.first() -// child.parent = null -// if (token != visionToken) { -// child.config["solidName"] = token.toString() -// } -// visionToken to child.updateFrom(vision) -// } else { -// visionToken to vision -// } -// } -// if (newChildren != group.children) { -// group.removeAll() -// newChildren.forEach { (token, child) -> -// group[token] = child -// } -// } -// } -//} -// -//@DFExperimental -//suspend fun SolidGroup.optimizeGdml(): Job = coroutineScope { -// prototypes?.let { -// VisionVisitor.visitTree(GdmlOptimizer(), this, it) -// } ?: CompletableDeferred(Unit) -//} \ No newline at end of file diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformerEnv.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt similarity index 95% rename from visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformerEnv.kt rename to visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt index 76561fe8..3a7b48af 100644 --- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformerEnv.kt +++ b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt @@ -163,25 +163,26 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) { newScale: GdmlScale? = null, ): T = apply { newPos?.let { - val point = Point3D(it.x(settings.lUnit), it.y(settings.lUnit), it.z(settings.lUnit)) - if (point != Point3D.ZERO) { - position = point - } + val gdmlX = it.x(settings.lUnit) + if (gdmlX != 0f) x = gdmlX + val gdmlY = it.y(settings.lUnit) + if (gdmlY != 0f) y = gdmlY + val gdmlZ = it.z(settings.lUnit) + if (gdmlZ != 0f) z = gdmlZ } newRotation?.let { - val point = Point3D(it.x(settings.aUnit), it.y(settings.aUnit), it.z(settings.aUnit)) - if (point != Point3D.ZERO) { - rotation = point - } - //this@withPosition.rotationOrder = RotationOrder.ZXY + val gdmlX = it.x(settings.aUnit) + if (gdmlX != 0f) rotationX = gdmlX + val gdmlY = it.y(settings.aUnit) + if (gdmlY != 0f) rotationY = gdmlY + val gdmlZ = it.z(settings.aUnit) + if (gdmlZ != 0f) rotationZ = gdmlZ } newScale?.let { - val point = Point3D(it.x, it.y, it.z) - if (point != Point3D.ONE) { - scale = point - } + if (it.x != 1f) scaleX = it.x + if (it.y != 1f) scaleY = it.y + if (it.z != 1f) scaleZ = it.z } - //TODO convert units if needed } fun T.withPosition(root: Gdml, physVolume: GdmlPhysVolume): T = withPosition( @@ -301,7 +302,7 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) { val first: GdmlSolid = solid.first.resolve(root) ?: error("") val second: GdmlSolid = solid.second.resolve(root) ?: error("") val type: CompositeType = when (solid) { - is GdmlUnion -> CompositeType.UNION + is GdmlUnion -> CompositeType.SUM // dumb sum for better performance is GdmlSubtraction -> CompositeType.SUBTRACT is GdmlIntersection -> CompositeType.INTERSECT } diff --git a/visionforge-gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/gdmlJs.kt b/visionforge-gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/gdmlJs.kt deleted file mode 100644 index f90eec29..00000000 --- a/visionforge-gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/gdmlJs.kt +++ /dev/null @@ -1,8 +0,0 @@ -package space.kscience.visionforge.gdml - -public actual class Counter { - private var count: Int = 0 - public actual fun get(): Int = count - - public actual fun incrementAndGet(): Int = count++ -} \ No newline at end of file diff --git a/visionforge-gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/gdmlJVM.kt b/visionforge-gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/gdmlJVM.kt index 7bd17a5c..b67e231e 100644 --- a/visionforge-gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/gdmlJVM.kt +++ b/visionforge-gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/gdmlJVM.kt @@ -4,9 +4,6 @@ import space.kscience.gdml.Gdml import space.kscience.gdml.decodeFromFile import space.kscience.visionforge.solid.SolidGroup import java.nio.file.Path -import java.util.concurrent.atomic.AtomicInteger - -public actual typealias Counter = AtomicInteger public fun SolidGroup.gdml( file: Path, diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Composite.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Composite.kt index 35cf7ab6..d1d41d09 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Composite.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Composite.kt @@ -6,7 +6,8 @@ import space.kscience.dataforge.meta.update import space.kscience.visionforge.* public enum class CompositeType { - UNION, + SUM, // Dumb sum of meshes + UNION, //CSG union INTERSECT, SUBTRACT } diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt index f2b14f2a..0b3dee57 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt @@ -48,7 +48,7 @@ public interface Solid : Vision { public val Y_KEY: Name = "y".asName() public val Z_KEY: Name = "z".asName() - public val POSITION_KEY: Name = "pos".asName() + public val POSITION_KEY: Name = "position".asName() public val X_POSITION_KEY: Name = POSITION_KEY + X_KEY public val Y_POSITION_KEY: Name = POSITION_KEY + Y_KEY @@ -83,6 +83,18 @@ public interface Solid : Vision { hide() } + node(POSITION_KEY){ + hide() + } + + node(ROTATION_KEY){ + hide() + } + + node(SCALE_KEY){ + hide() + } + value(DETAIL_KEY) { type(ValueType.NUMBER) hide() @@ -145,7 +157,7 @@ public var Vision.ignore: Boolean? // get() = getProperty(SELECTED_KEY).boolean // set(value) = setProperty(SELECTED_KEY, value) -internal fun number(name: Name, default: Number): ReadWriteProperty = +internal fun float(name: Name, default: Number): ReadWriteProperty = object : ReadWriteProperty { override fun getValue(thisRef: Solid, property: KProperty<*>): Number { return thisRef.getOwnProperty(name)?.number ?: default @@ -156,33 +168,40 @@ internal fun number(name: Name, default: Number): ReadWriteProperty = - object : ReadWriteProperty { - override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D = object : Point3D { - override val x: Float get() = thisRef.getOwnProperty(name + X_KEY)?.float ?: default - override val y: Float get() = thisRef.getOwnProperty(name + Y_KEY)?.float ?: default - override val z: Float get() = thisRef.getOwnProperty(name + Z_KEY)?.float ?: default +internal fun point(name: Name, default: Float): ReadWriteProperty = + object : ReadWriteProperty { + override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D? { + val item = thisRef.getOwnProperty(name) ?: return null + return object : Point3D { + override val x: Float get() = item[X_KEY]?.float ?: default + override val y: Float get() = item[Y_KEY]?.float ?: default + override val z: Float get() = item[Z_KEY]?.float ?: default + } } - override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D) { - thisRef.setProperty(name + X_KEY, value.x) - thisRef.setProperty(name + Y_KEY, value.y) - thisRef.setProperty(name + Z_KEY, value.z) + override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D?) { + if (value == null) { + thisRef.setProperty(name, null) + } else { + thisRef.setProperty(name + X_KEY, value.x) + thisRef.setProperty(name + Y_KEY, value.y) + thisRef.setProperty(name + Z_KEY, value.z) + } } } -public var Solid.position: Point3D by point(POSITION_KEY, 0f) -public var Solid.rotation: Point3D by point(ROTATION_KEY, 0f) -public var Solid.scale: Point3D by point(SCALE_KEY, 1f) +public var Solid.position: Point3D? by point(POSITION_KEY, 0f) +public var Solid.rotation: Point3D? by point(ROTATION_KEY, 0f) +public var Solid.scale: Point3D? by point(SCALE_KEY, 1f) -public var Solid.x: Number by number(X_POSITION_KEY, 0f) -public var Solid.y: Number by number(Y_POSITION_KEY, 0f) -public var Solid.z: Number by number(Z_POSITION_KEY, 0f) +public var Solid.x: Number by float(X_POSITION_KEY, 0f) +public var Solid.y: Number by float(Y_POSITION_KEY, 0f) +public var Solid.z: Number by float(Z_POSITION_KEY, 0f) -public var Solid.rotationX: Number by number(X_ROTATION_KEY, 0f) -public var Solid.rotationY: Number by number(Y_ROTATION_KEY, 0f) -public var Solid.rotationZ: Number by number(Z_ROTATION_KEY, 0f) +public var Solid.rotationX: Number by float(X_ROTATION_KEY, 0f) +public var Solid.rotationY: Number by float(Y_ROTATION_KEY, 0f) +public var Solid.rotationZ: Number by float(Z_ROTATION_KEY, 0f) -public var Solid.scaleX: Number by number(X_SCALE_KEY, 1f) -public var Solid.scaleY: Number by number(Y_SCALE_KEY, 1f) -public var Solid.scaleZ: Number by number(Z_SCALE_KEY, 1f) \ No newline at end of file +public var Solid.scaleX: Number by float(X_SCALE_KEY, 1f) +public var Solid.scaleY: Number by float(Y_SCALE_KEY, 1f) +public var Solid.scaleZ: Number by float(Z_SCALE_KEY, 1f) \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt index c0c02bc7..a51aaa25 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt @@ -1,32 +1,39 @@ package space.kscience.visionforge.solid.transform +import space.kscience.dataforge.meta.itemSequence import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.asName -import space.kscience.visionforge.* +import space.kscience.visionforge.MutableVisionGroup +import space.kscience.visionforge.Vision +import space.kscience.visionforge.VisionGroup +import space.kscience.visionforge.meta import space.kscience.visionforge.solid.* +private operator fun Number.plus(other: Number) = toFloat() + other.toFloat() +private operator fun Number.times(other: Number) = toFloat() * other.toFloat() + @DFExperimental -internal fun mergeChild(parent: VisionGroup, child: Vision): Vision { - return child.apply { - - configure(parent.meta) - - //parent.properties?.let { config.update(it) } - - if (this is Solid && parent is Solid) { - position += parent.position - rotation += parent.rotation - scale = Point3D( - scale.x * parent.scale.x, - scale.y * parent.scale.y, - scale.z * parent.scale.z - ) - +internal fun Vision.updateFrom(other: Vision): Vision { + if (this is Solid && other is Solid) { + x += other.x + y += other.y + z += other.y + rotationX += other.rotationX + rotationY += other.rotationY + rotationZ += other.rotationZ + scaleX *= other.scaleX + scaleY *= other.scaleY + scaleZ *= other.scaleZ + other.meta.itemSequence().forEach { (name, item) -> + if (getProperty(name) == null) { + setProperty(name, item) + } } - } + return this } + @DFExperimental internal object RemoveSingleChild : VisualTreeTransform() { @@ -39,7 +46,7 @@ internal object RemoveSingleChild : VisualTreeTransform() { } if (parent is VisionGroup && parent.children.size == 1) { val child = parent.children.values.first() - val newParent = mergeChild(parent, child) + val newParent = child.updateFrom(parent) newParent.parent = null set(childName.asName(), newParent) } diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/UnRef.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/UnRef.kt index b6d7c2e6..890c8291 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/UnRef.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/UnRef.kt @@ -31,7 +31,7 @@ internal object UnRef : VisualTreeTransform() { } children.filter { (it.value as? SolidReferenceGroup)?.refName == name }.forEach { (key, value) -> val reference = value as SolidReferenceGroup - val newChild = mergeChild(reference, reference.prototype) + val newChild = reference.prototype.updateFrom(reference) newChild.parent = null set(key.asName(), newChild) // replace proxy with merged object } diff --git a/visionforge-threejs/src/main/kotlin/info/laht/threekt/utils/BufferGeometryUtils.kt b/visionforge-threejs/src/main/kotlin/info/laht/threekt/utils/BufferGeometryUtils.kt new file mode 100644 index 00000000..dd15b514 --- /dev/null +++ b/visionforge-threejs/src/main/kotlin/info/laht/threekt/utils/BufferGeometryUtils.kt @@ -0,0 +1,15 @@ +@file:JsModule("three/examples/jsm/utils/BufferGeometryUtils") +@file:JsNonModule +package info.laht.threekt.utils + +import info.laht.threekt.core.BufferGeometry + + +public external object BufferGeometryUtils { + /** + * Merges a set of geometries into a single instance. All geometries must have compatible attributes. If merge does not succeed, the method returns null. + * @param geometries -- Array of BufferGeometry instances. + * @param useGroups -- Whether groups should be generated for the merged geometry or not. + */ + public fun mergeBufferGeometries(geometries: Array, useGroups: Boolean): BufferGeometry +} \ No newline at end of file diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt index 33304b72..2cdd12d3 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt @@ -42,9 +42,9 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : ThreeFactory val first = three.buildObject3D(obj.first) as? Mesh ?: error("First part of composite is not a mesh") val second = three.buildObject3D(obj.second) as? Mesh ?: error("Second part of composite is not a mesh") return when (obj.compositeType) { - CompositeType.UNION -> CSG.union(first,second) - CompositeType.INTERSECT -> CSG.intersect(first,second) - CompositeType.SUBTRACT -> CSG.subtract(first,second) + CompositeType.SUM, CompositeType.UNION -> CSG.union(first, second) + CompositeType.INTERSECT -> CSG.intersect(first, second) + CompositeType.SUBTRACT -> CSG.subtract(first, second) }.apply { updatePosition(obj) applyProperties(obj)