forked from kscience/visionforge
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 firstCSG = first.toCSG()
|
||||||
val secondCSG = second.toCSG()
|
val secondCSG = second.toCSG()
|
||||||
val resultCSG = when (obj.compositeType) {
|
val resultCSG = when (obj.compositeType) {
|
||||||
CompositeType.UNION -> firstCSG.union(secondCSG)
|
CompositeType.SUM, CompositeType.UNION -> firstCSG.union(secondCSG)
|
||||||
CompositeType.INTERSECT -> firstCSG.intersect(secondCSG)
|
CompositeType.INTERSECT -> firstCSG.intersect(secondCSG)
|
||||||
CompositeType.SUBTRACT -> firstCSG.difference(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,26 +163,27 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) {
|
|||||||
newScale: GdmlScale? = null,
|
newScale: GdmlScale? = null,
|
||||||
): T = apply {
|
): T = apply {
|
||||||
newPos?.let {
|
newPos?.let {
|
||||||
val point = Point3D(it.x(settings.lUnit), it.y(settings.lUnit), it.z(settings.lUnit))
|
val gdmlX = it.x(settings.lUnit)
|
||||||
if (point != Point3D.ZERO) {
|
if (gdmlX != 0f) x = gdmlX
|
||||||
position = point
|
val gdmlY = it.y(settings.lUnit)
|
||||||
}
|
if (gdmlY != 0f) y = gdmlY
|
||||||
|
val gdmlZ = it.z(settings.lUnit)
|
||||||
|
if (gdmlZ != 0f) z = gdmlZ
|
||||||
}
|
}
|
||||||
newRotation?.let {
|
newRotation?.let {
|
||||||
val point = Point3D(it.x(settings.aUnit), it.y(settings.aUnit), it.z(settings.aUnit))
|
val gdmlX = it.x(settings.aUnit)
|
||||||
if (point != Point3D.ZERO) {
|
if (gdmlX != 0f) rotationX = gdmlX
|
||||||
rotation = point
|
val gdmlY = it.y(settings.aUnit)
|
||||||
}
|
if (gdmlY != 0f) rotationY = gdmlY
|
||||||
//this@withPosition.rotationOrder = RotationOrder.ZXY
|
val gdmlZ = it.z(settings.aUnit)
|
||||||
|
if (gdmlZ != 0f) rotationZ = gdmlZ
|
||||||
}
|
}
|
||||||
newScale?.let {
|
newScale?.let {
|
||||||
val point = Point3D(it.x, it.y, it.z)
|
if (it.x != 1f) scaleX = it.x
|
||||||
if (point != Point3D.ONE) {
|
if (it.y != 1f) scaleY = it.y
|
||||||
scale = point
|
if (it.z != 1f) scaleZ = it.z
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO convert units if needed
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Solid> T.withPosition(root: Gdml, physVolume: GdmlPhysVolume): T = withPosition(
|
fun <T : Solid> T.withPosition(root: Gdml, physVolume: GdmlPhysVolume): T = withPosition(
|
||||||
physVolume.resolvePosition(root),
|
physVolume.resolvePosition(root),
|
||||||
@ -301,7 +302,7 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) {
|
|||||||
val first: GdmlSolid = solid.first.resolve(root) ?: error("")
|
val first: GdmlSolid = solid.first.resolve(root) ?: error("")
|
||||||
val second: GdmlSolid = solid.second.resolve(root) ?: error("")
|
val second: GdmlSolid = solid.second.resolve(root) ?: error("")
|
||||||
val type: CompositeType = when (solid) {
|
val type: CompositeType = when (solid) {
|
||||||
is GdmlUnion -> CompositeType.UNION
|
is GdmlUnion -> CompositeType.SUM // dumb sum for better performance
|
||||||
is GdmlSubtraction -> CompositeType.SUBTRACT
|
is GdmlSubtraction -> CompositeType.SUBTRACT
|
||||||
is GdmlIntersection -> CompositeType.INTERSECT
|
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.gdml.decodeFromFile
|
||||||
import space.kscience.visionforge.solid.SolidGroup
|
import space.kscience.visionforge.solid.SolidGroup
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
|
||||||
|
|
||||||
public actual typealias Counter = AtomicInteger
|
|
||||||
|
|
||||||
public fun SolidGroup.gdml(
|
public fun SolidGroup.gdml(
|
||||||
file: Path,
|
file: Path,
|
||||||
|
@ -6,7 +6,8 @@ import space.kscience.dataforge.meta.update
|
|||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
|
|
||||||
public enum class CompositeType {
|
public enum class CompositeType {
|
||||||
UNION,
|
SUM, // Dumb sum of meshes
|
||||||
|
UNION, //CSG union
|
||||||
INTERSECT,
|
INTERSECT,
|
||||||
SUBTRACT
|
SUBTRACT
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public interface Solid : Vision {
|
|||||||
public val Y_KEY: Name = "y".asName()
|
public val Y_KEY: Name = "y".asName()
|
||||||
public val Z_KEY: Name = "z".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 X_POSITION_KEY: Name = POSITION_KEY + X_KEY
|
||||||
public val Y_POSITION_KEY: Name = POSITION_KEY + Y_KEY
|
public val Y_POSITION_KEY: Name = POSITION_KEY + Y_KEY
|
||||||
@ -83,6 +83,18 @@ public interface Solid : Vision {
|
|||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node(POSITION_KEY){
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
node(ROTATION_KEY){
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
node(SCALE_KEY){
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
|
||||||
value(DETAIL_KEY) {
|
value(DETAIL_KEY) {
|
||||||
type(ValueType.NUMBER)
|
type(ValueType.NUMBER)
|
||||||
hide()
|
hide()
|
||||||
@ -145,7 +157,7 @@ public var Vision.ignore: Boolean?
|
|||||||
// get() = getProperty(SELECTED_KEY).boolean
|
// get() = getProperty(SELECTED_KEY).boolean
|
||||||
// set(value) = setProperty(SELECTED_KEY, value)
|
// 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> {
|
object : ReadWriteProperty<Solid, Number> {
|
||||||
override fun getValue(thisRef: Solid, property: KProperty<*>): Number {
|
override fun getValue(thisRef: Solid, property: KProperty<*>): Number {
|
||||||
return thisRef.getOwnProperty(name)?.number ?: default
|
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> =
|
internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D?> =
|
||||||
object : ReadWriteProperty<Solid, Point3D> {
|
object : ReadWriteProperty<Solid, Point3D?> {
|
||||||
override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D = object : Point3D {
|
override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D? {
|
||||||
override val x: Float get() = thisRef.getOwnProperty(name + X_KEY)?.float ?: default
|
val item = thisRef.getOwnProperty(name) ?: return null
|
||||||
override val y: Float get() = thisRef.getOwnProperty(name + Y_KEY)?.float ?: default
|
return object : Point3D {
|
||||||
override val z: Float get() = thisRef.getOwnProperty(name + Z_KEY)?.float ?: default
|
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) {
|
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 + X_KEY, value.x)
|
||||||
thisRef.setProperty(name + Y_KEY, value.y)
|
thisRef.setProperty(name + Y_KEY, value.y)
|
||||||
thisRef.setProperty(name + Z_KEY, value.z)
|
thisRef.setProperty(name + Z_KEY, value.z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public var Solid.position: Point3D by point(POSITION_KEY, 0f)
|
public var Solid.position: Point3D? by point(POSITION_KEY, 0f)
|
||||||
public var Solid.rotation: Point3D by point(ROTATION_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.scale: Point3D? by point(SCALE_KEY, 1f)
|
||||||
|
|
||||||
public var Solid.x: Number by number(X_POSITION_KEY, 0f)
|
public var Solid.x: Number by float(X_POSITION_KEY, 0f)
|
||||||
public var Solid.y: Number by number(Y_POSITION_KEY, 0f)
|
public var Solid.y: Number by float(Y_POSITION_KEY, 0f)
|
||||||
public var Solid.z: Number by number(Z_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.rotationX: Number by float(X_ROTATION_KEY, 0f)
|
||||||
public var Solid.rotationY: Number by number(Y_ROTATION_KEY, 0f)
|
public var Solid.rotationY: Number by float(Y_ROTATION_KEY, 0f)
|
||||||
public var Solid.rotationZ: Number by number(Z_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.scaleX: Number by float(X_SCALE_KEY, 1f)
|
||||||
public var Solid.scaleY: Number by number(Y_SCALE_KEY, 1f)
|
public var Solid.scaleY: Number by float(Y_SCALE_KEY, 1f)
|
||||||
public var Solid.scaleZ: Number by number(Z_SCALE_KEY, 1f)
|
public var Solid.scaleZ: Number by float(Z_SCALE_KEY, 1f)
|
@ -1,32 +1,39 @@
|
|||||||
package space.kscience.visionforge.solid.transform
|
package space.kscience.visionforge.solid.transform
|
||||||
|
|
||||||
|
import space.kscience.dataforge.meta.itemSequence
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
import space.kscience.dataforge.names.asName
|
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.*
|
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
|
@DFExperimental
|
||||||
internal fun mergeChild(parent: VisionGroup, child: Vision): Vision {
|
internal fun Vision.updateFrom(other: Vision): Vision {
|
||||||
return child.apply {
|
if (this is Solid && other is Solid) {
|
||||||
|
x += other.x
|
||||||
configure(parent.meta)
|
y += other.y
|
||||||
|
z += other.y
|
||||||
//parent.properties?.let { config.update(it) }
|
rotationX += other.rotationX
|
||||||
|
rotationY += other.rotationY
|
||||||
if (this is Solid && parent is Solid) {
|
rotationZ += other.rotationZ
|
||||||
position += parent.position
|
scaleX *= other.scaleX
|
||||||
rotation += parent.rotation
|
scaleY *= other.scaleY
|
||||||
scale = Point3D(
|
scaleZ *= other.scaleZ
|
||||||
scale.x * parent.scale.x,
|
other.meta.itemSequence().forEach { (name, item) ->
|
||||||
scale.y * parent.scale.y,
|
if (getProperty(name) == null) {
|
||||||
scale.z * parent.scale.z
|
setProperty(name, item)
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
internal object RemoveSingleChild : VisualTreeTransform<SolidGroup>() {
|
internal object RemoveSingleChild : VisualTreeTransform<SolidGroup>() {
|
||||||
|
|
||||||
@ -39,7 +46,7 @@ internal object RemoveSingleChild : VisualTreeTransform<SolidGroup>() {
|
|||||||
}
|
}
|
||||||
if (parent is VisionGroup && parent.children.size == 1) {
|
if (parent is VisionGroup && parent.children.size == 1) {
|
||||||
val child = parent.children.values.first()
|
val child = parent.children.values.first()
|
||||||
val newParent = mergeChild(parent, child)
|
val newParent = child.updateFrom(parent)
|
||||||
newParent.parent = null
|
newParent.parent = null
|
||||||
set(childName.asName(), newParent)
|
set(childName.asName(), newParent)
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ internal object UnRef : VisualTreeTransform<SolidGroup>() {
|
|||||||
}
|
}
|
||||||
children.filter { (it.value as? SolidReferenceGroup)?.refName == name }.forEach { (key, value) ->
|
children.filter { (it.value as? SolidReferenceGroup)?.refName == name }.forEach { (key, value) ->
|
||||||
val reference = value as SolidReferenceGroup
|
val reference = value as SolidReferenceGroup
|
||||||
val newChild = mergeChild(reference, reference.prototype)
|
val newChild = reference.prototype.updateFrom(reference)
|
||||||
newChild.parent = null
|
newChild.parent = null
|
||||||
set(key.asName(), newChild) // replace proxy with merged object
|
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 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")
|
val second = three.buildObject3D(obj.second) as? Mesh ?: error("Second part of composite is not a mesh")
|
||||||
return when (obj.compositeType) {
|
return when (obj.compositeType) {
|
||||||
CompositeType.UNION -> CSG.union(first,second)
|
CompositeType.SUM, CompositeType.UNION -> CSG.union(first, second)
|
||||||
CompositeType.INTERSECT -> CSG.intersect(first,second)
|
CompositeType.INTERSECT -> CSG.intersect(first, second)
|
||||||
CompositeType.SUBTRACT -> CSG.subtract(first,second)
|
CompositeType.SUBTRACT -> CSG.subtract(first, second)
|
||||||
}.apply {
|
}.apply {
|
||||||
updatePosition(obj)
|
updatePosition(obj)
|
||||||
applyProperties(obj)
|
applyProperties(obj)
|
||||||
|
Loading…
Reference in New Issue
Block a user