GDML optimization

This commit is contained in:
Alexander Nozik 2020-08-26 21:12:39 +03:00
parent a5eba1789b
commit b362f86f9b
12 changed files with 179 additions and 223 deletions

View File

@ -20,7 +20,7 @@ fun cubes(): GDML = GDML {
val circle = volume("composite", boxMaterial, smallBox.ref()) { val circle = volume("composite", boxMaterial, smallBox.ref()) {
for (i in 0 until 6) { for (i in 0 until 6) {
physVolume(segmentVolume) { physVolume(segmentVolume) {
name = "segment$i" name = "segment_$i"
positionref = center.ref() positionref = center.ref()
rotation { rotation {
z = 60 * i z = 60 * i

View File

@ -10,11 +10,21 @@ import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class GDMLVisualTest { class GDMLVisualTest {
val gdml = cubes()
// @Test
// fun testCubesStyles(){
// val cubes = gdml.toVision()
// val segment = cubes["composite000.segment_0".toName()] as Solid
// println(segment.styles)
// println(segment.material)
// }
@Test @Test
fun testPrototypeProperty() { fun testPrototypeProperty() {
val gdml = cubes()
val visual = gdml.toVision() val visual = gdml.toVision()
visual["composite000.segment0".toName()]?.setItem(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue()) visual["composite000.segment_0".toName()]?.setItem(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
assertEquals("red", visual["composite000.segment0".toName()]?.getItem(SolidMaterial.MATERIAL_COLOR_KEY).string) assertEquals("red", visual["composite000.segment_0".toName()]?.getItem(SolidMaterial.MATERIAL_COLOR_KEY).string)
} }
} }

View File

@ -84,7 +84,6 @@ class StyleSheet private constructor(private val styleMap: MutableMap<String, Me
override fun serialize(encoder: Encoder, value: StyleSheet) { override fun serialize(encoder: Encoder, value: StyleSheet) {
mapSerializer.serialize(encoder, value.items) mapSerializer.serialize(encoder, value.items)
} }
} }
} }
@ -93,7 +92,7 @@ class StyleSheet private constructor(private val styleMap: MutableMap<String, Me
* Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment. * Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
*/ */
fun Vision.useStyle(name: String) { fun Vision.useStyle(name: String) {
styles = styles + name styles = properties[Vision.STYLE_KEY].stringList + name
} }
/** /**

View File

@ -5,7 +5,6 @@ import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.provider.Type import hep.dataforge.provider.Type
import hep.dataforge.values.asValue
import hep.dataforge.vision.Vision.Companion.TYPE import hep.dataforge.vision.Vision.Companion.TYPE
import kotlinx.serialization.PolymorphicSerializer import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
@ -63,7 +62,7 @@ interface Vision : Configurable {
var styles: List<String> var styles: List<String>
get() = properties[STYLE_KEY].stringList get() = properties[STYLE_KEY].stringList
set(value) { set(value) {
setItem(STYLE_KEY,value.map { it.asValue() }.asValue()) config[STYLE_KEY] = value
} }
companion object { companion object {

View File

@ -6,7 +6,6 @@ import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vision.get
import hep.dataforge.vision.set import hep.dataforge.vision.set
import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.*
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
@ -27,6 +26,7 @@ class GDMLTransformer(val root: GDML) {
} }
var lUnit: LUnit = LUnit.MM var lUnit: LUnit = LUnit.MM
var aUnit: AUnit = AUnit.RADIAN
var solidAction: (GDMLSolid) -> Action = { Action.CACHE } var solidAction: (GDMLSolid) -> Action = { Action.CACHE }
var volumeAction: (GDMLGroup) -> Action = { Action.CACHE } var volumeAction: (GDMLGroup) -> Action = { Action.CACHE }
@ -65,10 +65,6 @@ class GDMLTransformer(val root: GDML) {
obj.solidConfiguration(parent, solid) obj.solidConfiguration(parent, solid)
} }
//
// internal fun solidAdded(solid: GDMLSolid) {
// solidCounter[solid.name] = (solidCounter[solid.name] ?: 0) + 1
// }
var onFinish: GDMLTransformer.() -> Unit = {} var onFinish: GDMLTransformer.() -> Unit = {}
@ -94,6 +90,7 @@ class GDMLTransformer(val root: GDML) {
private fun Solid.withPosition( private fun Solid.withPosition(
lUnit: LUnit, lUnit: LUnit,
aUnit: AUnit = AUnit.RADIAN,
newPos: GDMLPosition? = null, newPos: GDMLPosition? = null,
newRotation: GDMLRotation? = null, newRotation: GDMLRotation? = null,
newScale: GDMLScale? = null newScale: GDMLScale? = null
@ -105,7 +102,7 @@ private fun Solid.withPosition(
} }
} }
newRotation?.let { newRotation?.let {
val point = Point3D(it.x(), it.y(), it.z()) val point = Point3D(it.x(aUnit), it.y(aUnit), it.z(aUnit))
if (rotation != null || point != World.ZERO) { if (rotation != null || point != World.ZERO) {
rotation = point rotation = point
} }
@ -120,6 +117,13 @@ private fun Solid.withPosition(
//TODO convert units if needed //TODO convert units if needed
} }
private fun Solid.withPosition(context: GDMLTransformer, physVolume: GDMLPhysVolume) = withPosition(
context.lUnit, context.aUnit,
physVolume.resolvePosition(context.root),
physVolume.resolveRotation(context.root),
physVolume.resolveScale(context.root)
)
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
private inline operator fun Number.times(d: Double) = toDouble() * d private inline operator fun Number.times(d: Double) = toDouble() * d
@ -129,8 +133,7 @@ private inline operator fun Number.times(f: Float) = toFloat() * f
private fun SolidGroup.addSolid( private fun SolidGroup.addSolid(
context: GDMLTransformer, context: GDMLTransformer,
solid: GDMLSolid, solid: GDMLSolid,
name: String = "", name: String = ""
block: Solid.() -> Unit = {}
): Solid { ): Solid {
//context.solidAdded(solid) //context.solidAdded(solid)
val lScale = solid.lscale(context.lUnit) val lScale = solid.lscale(context.lUnit)
@ -168,11 +171,10 @@ private fun SolidGroup.addSolid(
} }
is GDMLScaledSolid -> { is GDMLScaledSolid -> {
//Add solid with modified scale //Add solid with modified scale
val innerSolid = solid.solidref.resolve(context.root) val innerSolid: GDMLSolid = solid.solidref.resolve(context.root)
?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined") ?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined")
addSolid(context, innerSolid, name) { addSolid(context, innerSolid, name).apply {
block()
scaleX *= solid.scale.x.toFloat() scaleX *= solid.scale.x.toFloat()
scaleY *= solid.scale.y.toFloat() scaleY *= solid.scale.y.toFloat()
scaleZ = solid.scale.z.toFloat() scaleZ = solid.scale.z.toFloat()
@ -199,8 +201,8 @@ private fun SolidGroup.addSolid(
} }
} }
is GDMLBoolSolid -> { is GDMLBoolSolid -> {
val first = solid.first.resolve(context.root) ?: error("") val first: GDMLSolid = solid.first.resolve(context.root) ?: error("")
val second = solid.second.resolve(context.root) ?: error("") val second: GDMLSolid = solid.second.resolve(context.root) ?: error("")
val type: CompositeType = when (solid) { val type: CompositeType = when (solid) {
is GDMLUnion -> CompositeType.UNION is GDMLUnion -> CompositeType.UNION
is GDMLSubtraction -> CompositeType.SUBTRACT is GDMLSubtraction -> CompositeType.SUBTRACT
@ -208,54 +210,51 @@ private fun SolidGroup.addSolid(
} }
return composite(type, name) { return composite(type, name) {
addSolid(context, first) { addSolid(context, first).withPosition(
withPosition( context.lUnit, context.aUnit,
context.lUnit,
solid.resolveFirstPosition(context.root), solid.resolveFirstPosition(context.root),
solid.resolveFirstRotation(context.root), solid.resolveFirstRotation(context.root),
null null
) )
}
addSolid(context, second) { addSolid(context, second).withPosition(
withPosition( context.lUnit, context.aUnit,
context.lUnit,
solid.resolvePosition(context.root), solid.resolvePosition(context.root),
solid.resolveRotation(context.root), solid.resolveRotation(context.root),
null null
) )
}
} }
} }
else -> error("Renderer for $solid not supported yet") else -> error("Renderer for $solid not supported yet")
}.apply(block) }
} }
private val solidsName = "solids".asName()
private fun SolidGroup.addSolidWithCaching( private fun SolidGroup.addSolidWithCaching(
context: GDMLTransformer, context: GDMLTransformer,
solid: GDMLSolid, solid: GDMLSolid,
volume: GDMLVolume,
name: String = solid.name name: String = solid.name
) { ): Solid? {
when (context.solidAction(solid)) { return when (context.solidAction(solid)) {
GDMLTransformer.Action.ACCEPT -> { GDMLTransformer.Action.ACCEPT -> {
addSolid(context, solid, name) { addSolid(context, solid, name)
context.configureSolid(this, volume, solid)
}
} }
GDMLTransformer.Action.CACHE -> { GDMLTransformer.Action.CACHE -> {
if (context.proto[solid.name] == null) { val fullName = solidsName + solid.name.asName()
context.proto.addSolid(context, solid, name) { if (context.proto[fullName] == null) {
context.configureSolid(this, volume, solid) val parent = (context.proto[solidsName] as? SolidGroup) ?: context.proto.group(solidsName)
parent.addSolid(context, solid, solid.name)
} }
} ref(fullName, name)
ref(solid.name.asName(), name)
} }
GDMLTransformer.Action.REJECT -> { GDMLTransformer.Action.REJECT -> {
//ignore //ignore
null
} }
} }
} }
private val volumesName = "volumes".asName() private val volumesName = "volumes".asName()
@ -268,31 +267,20 @@ private fun SolidGroup.addPhysicalVolume(
?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved") ?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved")
// a special case for single solid volume // a special case for single solid volume
// if (volume is GDMLVolume && volume.physVolumes.isEmpty() && volume.placement == null) { if (volume is GDMLVolume && volume.physVolumes.isEmpty() && volume.placement == null) {
// val solid = volume.solidref.resolve(context.root) val solid = volume.solidref.resolve(context.root)
// ?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined") ?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined")
// addSolidWithCaching(context, solid, volume, physVolume.name ?: "").apply { addSolidWithCaching(context, solid, physVolume.name ?: "")?.apply {
// withPosition( context.configureSolid(this, volume, solid)
// context.lUnit, withPosition(context, physVolume)
// physVolume.resolvePosition(context.root), }
// physVolume.resolveRotation(context.root), return
// physVolume.resolveScale(context.root) }
// )
// }
// return
// }
when (context.volumeAction(volume)) { when (context.volumeAction(volume)) {
GDMLTransformer.Action.ACCEPT -> { GDMLTransformer.Action.ACCEPT -> {
val group: SolidGroup = volume(context, volume) val group: SolidGroup = volume(context, volume)
this[physVolume.name ?: ""] = group.apply { this[physVolume.name ?: ""] = group.withPosition(context, physVolume)
withPosition(
context.lUnit,
physVolume.resolvePosition(context.root),
physVolume.resolveRotation(context.root),
physVolume.resolveScale(context.root)
)
}
} }
GDMLTransformer.Action.CACHE -> { GDMLTransformer.Action.CACHE -> {
val fullName = volumesName + volume.name.asName() val fullName = volumesName + volume.name.asName()
@ -300,14 +288,7 @@ private fun SolidGroup.addPhysicalVolume(
context.proto[fullName] = volume(context, volume) context.proto[fullName] = volume(context, volume)
} }
this[physVolume.name ?: ""] = Proxy(this, fullName).apply { this[physVolume.name ?: ""] = Proxy(this, fullName).withPosition(context, physVolume)
withPosition(
context.lUnit,
physVolume.resolvePosition(context.root),
physVolume.resolveRotation(context.root),
physVolume.resolveScale(context.root)
)
}
} }
GDMLTransformer.Action.REJECT -> { GDMLTransformer.Action.REJECT -> {
//ignore //ignore
@ -326,8 +307,6 @@ private fun SolidGroup.addDivisionVolume(
set(Name.EMPTY, volume(context, volume)) set(Name.EMPTY, volume(context, volume))
} }
//private val solidsName = "solids".asName()
private fun volume( private fun volume(
context: GDMLTransformer, context: GDMLTransformer,
group: GDMLGroup group: GDMLGroup
@ -336,7 +315,9 @@ private fun volume(
val solid: GDMLSolid = group.solidref.resolve(context.root) val solid: GDMLSolid = group.solidref.resolve(context.root)
?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined") ?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined")
addSolidWithCaching(context, solid, group) addSolidWithCaching(context, solid)?.apply {
context.configureSolid(this, group, solid)
}
when (val vol: GDMLPlacement? = group.placement) { when (val vol: GDMLPlacement? = group.placement) {
is GDMLPhysVolume -> addPhysicalVolume(context, vol) is GDMLPhysVolume -> addPhysicalVolume(context, vol)

View File

@ -5,7 +5,6 @@ package hep.dataforge.vision.solid
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.* import hep.dataforge.names.*
import hep.dataforge.values.asValue
import hep.dataforge.vision.* import hep.dataforge.vision.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -13,36 +12,8 @@ import kotlinx.serialization.Transient
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
import kotlin.collections.set import kotlin.collections.set
abstract class AbstractProxy : AbstractVision(), VisionGroup {
class AbstractProxy abstract val prototype: Vision
/**
* A proxy [Solid] to reuse a template object
*/
@Serializable
@SerialName("solid.proxy")
class Proxy private constructor(
val templateName: Name
) : AbstractVision(), VisionGroup, Solid {
constructor(parent: SolidGroup, templateName: Name) : this(templateName) {
this.parent = parent
}
override var position: Point3D? = null
override var rotation: Point3D? = null
override var scale: Point3D? = null
override var properties: Config? = null
/**
* Recursively search for defined template in the parent
*/
val prototype: Solid
get() = (parent as? SolidGroup)?.getPrototype(templateName)
?: error("Prototype with name $templateName not found in $parent")
override val styleSheet: StyleSheet get() = parent?.styleSheet ?: StyleSheet(this)
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) { return if (inherit) {
@ -61,23 +32,10 @@ class Proxy private constructor(
} }
} }
override val children: Map<NameToken, ProxyChild> override var styles: List<String>
get() = (prototype as? VisionGroup)?.children get() = properties[Vision.STYLE_KEY].stringList + prototype.styles
?.filter { !it.key.toString().startsWith("@") } set(value) {
?.mapValues { config[Vision.STYLE_KEY] = value
ProxyChild(it.key.asName())
} ?: emptyMap()
@Transient
private val propertyCache: HashMap<Name, Config> = HashMap()
fun childPropertyName(childName: Name, propertyName: Name): Name {
return NameToken(PROXY_CHILD_PROPERTY_PREFIX, childName.toString()) + propertyName
}
private fun prototypeFor(name: Name): Vision {
return (prototype as? VisionGroup)?.get(name)
?: error("Prototype with name $name not found in $this")
} }
override fun getAllProperties(): Laminate = override fun getAllProperties(): Laminate =
@ -87,28 +45,76 @@ class Proxy private constructor(
//do nothing //do nothing
} }
//override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) }) override val descriptor: NodeDescriptor? get() = prototype.descriptor
}
override var styles: List<String> /**
get() = properties[Vision.STYLE_KEY].stringList + prototype.styles * A proxy [Solid] to reuse a template object
set(value) { */
setItem(Vision.STYLE_KEY, value.map { it.asValue() }.asValue()) @Serializable
@SerialName("solid.proxy")
class Proxy private constructor(
val templateName: Name
) : AbstractProxy(), Solid {
constructor(parent: SolidGroup, templateName: Name) : this(templateName) {
this.parent = parent
} }
override val descriptor: NodeDescriptor? override var position: Point3D? = null
get() = prototype.descriptor override var rotation: Point3D? = null
override var scale: Point3D? = null
inner class ProxyChild(val name: Name) : AbstractVision(), VisionGroup { override var properties: Config? = null
val prototype: Vision get() = prototypeFor(name) /**
* Recursively search for defined template in the parent
*/
override val prototype: Solid
get() = (parent as? SolidGroup)?.getPrototype(templateName)
?: error("Prototype with name $templateName not found in $parent")
override val styleSheet: StyleSheet get() = parent?.styleSheet ?: StyleSheet(this)
@Transient
private val propertyCache: HashMap<Name, Config> = HashMap()
override val children: Map<NameToken, Proxy.ProxyChild>
get() = (prototype as? VisionGroup)?.children
?.filter { !it.key.toString().startsWith("@") }
?.mapValues {
ProxyChild(it.key.asName())
} ?: emptyMap()
private fun childPropertyName(childName: Name, propertyName: Name): Name {
return NameToken(PROXY_CHILD_PROPERTY_PREFIX, childName.toString()) + propertyName
}
private fun prototypeFor(name: Name): Vision {
return (prototype as? VisionGroup)?.get(name)
?: error("Prototype with name $name not found in $this")
}
override val descriptor: NodeDescriptor? get() = prototype.descriptor
//override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) })
/**
* A ProxyChild is created temporarily only to interact with properties, it does not store any values
* (properties are stored in external cache) and created and destroyed on-demand).
*/
inner class ProxyChild(val name: Name) : AbstractProxy() {
override val prototype: Vision get() = prototypeFor(name)
override val styleSheet: StyleSheet get() = this@Proxy.styleSheet override val styleSheet: StyleSheet get() = this@Proxy.styleSheet
override val children: Map<NameToken, Vision> override val children: Map<NameToken, Vision>
get() = (prototype as? VisionGroup)?.children?.mapValues { (key, _) -> get() = (prototype as? VisionGroup)?.children
ProxyChild( ?.filter { !it.key.toString().startsWith("@") }
name + key.asName() ?.mapValues { (key, _) ->
) ProxyChild(name + key.asName())
} ?: emptyMap() } ?: emptyMap()
override var properties: Config? override var properties: Config?
@ -128,39 +134,6 @@ class Proxy private constructor(
} }
} }
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) {
sequence {
yield(properties?.get(name))
yieldAll(getStyleItems(name))
yield(prototype.getItem(name))
yield(parent?.getProperty(name, inherit))
}.merge()
} else {
sequence {
yield(properties?.get(name))
yieldAll(getStyleItems(name))
yield(prototype.getProperty(name, false))
}.merge()
}
}
override fun attachChildren() {
//do nothing
}
override fun getAllProperties(): Laminate =
Laminate(properties, allStyles, prototype.getAllProperties(), parent?.getAllProperties())
override var styles: List<String>
get() = properties[Vision.STYLE_KEY].stringList + prototype.styles
set(value) {
setItem(Vision.STYLE_KEY, value.map { it.asValue() }.asValue())
}
override val descriptor: NodeDescriptor?
get() = prototype.descriptor
} }
companion object { companion object {
@ -170,8 +143,7 @@ class Proxy private constructor(
val Vision.prototype: Vision val Vision.prototype: Vision
get() = when (this) { get() = when (this) {
is Proxy -> prototype is AbstractProxy -> prototype
is Proxy.ProxyChild -> prototype
else -> this else -> this
} }

View File

@ -99,13 +99,14 @@ fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup {
tailrec fun PrototypeHolder.getPrototype(name: Name): Solid? = tailrec fun PrototypeHolder.getPrototype(name: Name): Solid? =
prototypes?.get(name) as? Solid ?: (parent as? PrototypeHolder)?.getPrototype(name) prototypes?.get(name) as? Solid ?: (parent as? PrototypeHolder)?.getPrototype(name)
fun MutableVisionGroup.group(name: Name = Name.EMPTY, action: SolidGroup.() -> Unit = {}): SolidGroup =
SolidGroup().apply(action).also { set(name, it) }
/** /**
* Define a group with given [name], attach it to this parent and return it. * Define a group with given [name], attach it to this parent and return it.
*/ */
fun MutableVisionGroup.group(name: String = "", action: SolidGroup.() -> Unit = {}): SolidGroup = fun MutableVisionGroup.group(name: String, action: SolidGroup.() -> Unit = {}): SolidGroup =
SolidGroup().apply(action).also { SolidGroup().apply(action).also { set(name, it) }
set(name, it)
}
/** /**
* A special class which works as a holder for prototypes * A special class which works as a holder for prototypes

View File

@ -35,19 +35,11 @@ abstract class MeshThreeFactory<in T : Solid>(
//val meshMeta: Meta = obj.properties[Material3D.MATERIAL_KEY]?.node ?: Meta.empty //val meshMeta: Meta = obj.properties[Material3D.MATERIAL_KEY]?.node ?: Meta.empty
val mesh = Mesh(geometry, getMaterial(obj, true)).apply { val mesh = Mesh(geometry, null).apply{
matrixAutoUpdate = false matrixAutoUpdate = false
applyEdges(obj)
applyWireFrame(obj)
//set position for mesh //set position for mesh
updatePosition(obj) updatePosition(obj)
}.applyProperties(obj)
layers.enable(obj.layer)
children.forEach {
it.layers.enable(obj.layer)
}
}
//add listener to object properties //add listener to object properties
obj.onPropertyChange(this) { name -> obj.onPropertyChange(this) { name ->
@ -79,6 +71,16 @@ abstract class MeshThreeFactory<in T : Solid>(
} }
} }
fun Mesh.applyProperties(obj: Solid): Mesh = apply{
material = getMaterial(obj, true)
applyEdges(obj)
applyWireFrame(obj)
layers.enable(obj.layer)
children.forEach {
it.layers.enable(obj.layer)
}
}
fun Mesh.applyEdges(obj: Solid) { fun Mesh.applyEdges(obj: Solid) {
val edges = children.find { it.name == "@edges" } as? LineSegments val edges = children.find { it.name == "@edges" } as? LineSegments
//inherited edges definition, enabled by default //inherited edges definition, enabled by default

View File

@ -41,18 +41,6 @@ fun Object3D.updatePosition(obj: Vision) {
} }
} }
///**
// * Unsafe invocation of a factory
// */
//operator fun <T : VisualObject3D> ThreeFactory<T>.invoke(obj: Any): Object3D {
// if (type.isInstance(obj)) {
// @Suppress("UNCHECKED_CAST")
// return invoke(obj as T)
// } else {
// error("The object of type ${obj::class} could not be rendered by this factory")
// }
//}
/** /**
* Update non-position non-geometry property * Update non-position non-geometry property
*/ */

View File

@ -4,7 +4,6 @@ import hep.dataforge.names.toName
import hep.dataforge.vision.solid.Proxy import hep.dataforge.vision.solid.Proxy
import hep.dataforge.vision.solid.Proxy.Companion.PROXY_CHILD_PROPERTY_PREFIX import hep.dataforge.vision.solid.Proxy.Companion.PROXY_CHILD_PROPERTY_PREFIX
import hep.dataforge.vision.solid.Solid import hep.dataforge.vision.solid.Solid
import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
import info.laht.threekt.objects.Mesh import info.laht.threekt.objects.Mesh
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -14,16 +13,16 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy> {
override val type: KClass<Proxy> = Proxy::class override val type: KClass<Proxy> = Proxy::class
private fun Object3D.replicate(): Object3D { // private fun Object3D.replicate(): Object3D {
return when (this) { // return when (this) {
is Mesh -> Mesh(geometry as BufferGeometry, material) // is Mesh -> Mesh(geometry as BufferGeometry, material)
else -> clone(false) // else -> clone(false)
}.also { obj: Object3D -> // }.also { obj: Object3D ->
children.forEach { child: Object3D -> // children.forEach { child: Object3D ->
obj.add(child.replicate()) // obj.add(child.replicate())
} // }
} // }
} // }
override fun invoke(obj: Proxy): Object3D { override fun invoke(obj: Proxy): Object3D {
val template = obj.prototype val template = obj.prototype
@ -31,10 +30,13 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy> {
three.buildObject3D(template) three.buildObject3D(template)
} }
val object3D: Object3D = cachedObject.replicate() val object3D: Object3D = cachedObject.clone()//cachedObject.replicate()
object3D.updatePosition(obj) object3D.updatePosition(obj)
if(object3D is Mesh){
object3D.applyProperties(obj)
}
obj.onPropertyChange(this) { name -> obj.onPropertyChange(this) { name ->
if (name.first()?.body == PROXY_CHILD_PROPERTY_PREFIX) { if (name.first()?.body == PROXY_CHILD_PROPERTY_PREFIX) {
val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'") val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'")

View File

@ -1,6 +1,7 @@
package hep.dataforge.vision.solid.three package hep.dataforge.vision.solid.three
import hep.dataforge.js.requireJS import hep.dataforge.js.requireJS
import hep.dataforge.meta.DFExperimental
import hep.dataforge.vision.bootstrap.accordion import hep.dataforge.vision.bootstrap.accordion
import hep.dataforge.vision.bootstrap.entry import hep.dataforge.vision.bootstrap.entry
import hep.dataforge.vision.solid.SolidGroup import hep.dataforge.vision.solid.SolidGroup
@ -31,6 +32,7 @@ private fun saveData(event: Event, fileName: String, mimeType: String = "text/pl
fileSaver.saveAs(blob, fileName) fileSaver.saveAs(blob, fileName)
} }
@OptIn(DFExperimental::class)
fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") { fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") {
entry("Settings") { entry("Settings") {
div("row") { div("row") {

View File

@ -33,8 +33,8 @@ import info.laht.threekt.materials.Material
open external class Mesh : Object3D { open external class Mesh : Object3D {
constructor(geometry: Geometry, material: Material) constructor(geometry: Geometry?, material: Material?)
constructor(geometry: BufferGeometry, material: Material) constructor(geometry: BufferGeometry?, material: Material?)
var geometry: dynamic var geometry: dynamic
var material: Material var material: Material