Reimplemented coordinates as properties
This commit is contained in:
parent
2b6942b827
commit
7b30b62849
@ -48,7 +48,7 @@ class FXCompositeFactory(val plugin: FX3DPlugin) : FX3DFactory<Composite> {
|
||||
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)
|
||||
}
|
||||
|
@ -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<Int, Counter>()
|
||||
//
|
||||
// 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)
|
||||
//}
|
@ -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 : Solid> 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
|
||||
}
|
@ -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++
|
||||
}
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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<Solid, Number> =
|
||||
internal fun float(name: Name, default: Number): ReadWriteProperty<Solid, Number> =
|
||||
object : ReadWriteProperty<Solid, Number> {
|
||||
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<Solid, Numbe
|
||||
}
|
||||
}
|
||||
|
||||
internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D> =
|
||||
object : ReadWriteProperty<Solid, Point3D> {
|
||||
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<Solid, Point3D?> =
|
||||
object : ReadWriteProperty<Solid, Point3D?> {
|
||||
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)
|
||||
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)
|
@ -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<SolidGroup>() {
|
||||
|
||||
@ -39,7 +46,7 @@ internal object RemoveSingleChild : VisualTreeTransform<SolidGroup>() {
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ internal object UnRef : VisualTreeTransform<SolidGroup>() {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -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<BufferGeometry>, useGroups: Boolean): BufferGeometry
|
||||
}
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user