GDML optimization
This commit is contained in:
parent
a5eba1789b
commit
b362f86f9b
@ -20,7 +20,7 @@ fun cubes(): GDML = GDML {
|
||||
val circle = volume("composite", boxMaterial, smallBox.ref()) {
|
||||
for (i in 0 until 6) {
|
||||
physVolume(segmentVolume) {
|
||||
name = "segment$i"
|
||||
name = "segment_$i"
|
||||
positionref = center.ref()
|
||||
rotation {
|
||||
z = 60 * i
|
||||
|
@ -10,11 +10,21 @@ import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
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
|
||||
fun testPrototypeProperty() {
|
||||
val gdml = cubes()
|
||||
val visual = gdml.toVision()
|
||||
visual["composite000.segment0".toName()]?.setItem(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
|
||||
assertEquals("red", visual["composite000.segment0".toName()]?.getItem(SolidMaterial.MATERIAL_COLOR_KEY).string)
|
||||
visual["composite000.segment_0".toName()]?.setItem(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
|
||||
assertEquals("red", visual["composite000.segment_0".toName()]?.getItem(SolidMaterial.MATERIAL_COLOR_KEY).string)
|
||||
}
|
||||
}
|
@ -84,7 +84,6 @@ class StyleSheet private constructor(private val styleMap: MutableMap<String, Me
|
||||
override fun serialize(encoder: Encoder, value: StyleSheet) {
|
||||
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.
|
||||
*/
|
||||
fun Vision.useStyle(name: String) {
|
||||
styles = styles + name
|
||||
styles = properties[Vision.STYLE_KEY].stringList + name
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,6 @@ import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.provider.Type
|
||||
import hep.dataforge.values.asValue
|
||||
import hep.dataforge.vision.Vision.Companion.TYPE
|
||||
import kotlinx.serialization.PolymorphicSerializer
|
||||
import kotlinx.serialization.Transient
|
||||
@ -63,7 +62,7 @@ interface Vision : Configurable {
|
||||
var styles: List<String>
|
||||
get() = properties[STYLE_KEY].stringList
|
||||
set(value) {
|
||||
setItem(STYLE_KEY,value.map { it.asValue() }.asValue())
|
||||
config[STYLE_KEY] = value
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -6,7 +6,6 @@ import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.vision.get
|
||||
import hep.dataforge.vision.set
|
||||
import hep.dataforge.vision.solid.*
|
||||
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 aUnit: AUnit = AUnit.RADIAN
|
||||
|
||||
var solidAction: (GDMLSolid) -> Action = { Action.CACHE }
|
||||
var volumeAction: (GDMLGroup) -> Action = { Action.CACHE }
|
||||
@ -65,10 +65,6 @@ class GDMLTransformer(val root: GDML) {
|
||||
|
||||
obj.solidConfiguration(parent, solid)
|
||||
}
|
||||
//
|
||||
// internal fun solidAdded(solid: GDMLSolid) {
|
||||
// solidCounter[solid.name] = (solidCounter[solid.name] ?: 0) + 1
|
||||
// }
|
||||
|
||||
var onFinish: GDMLTransformer.() -> Unit = {}
|
||||
|
||||
@ -94,6 +90,7 @@ class GDMLTransformer(val root: GDML) {
|
||||
|
||||
private fun Solid.withPosition(
|
||||
lUnit: LUnit,
|
||||
aUnit: AUnit = AUnit.RADIAN,
|
||||
newPos: GDMLPosition? = null,
|
||||
newRotation: GDMLRotation? = null,
|
||||
newScale: GDMLScale? = null
|
||||
@ -105,7 +102,7 @@ private fun Solid.withPosition(
|
||||
}
|
||||
}
|
||||
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) {
|
||||
rotation = point
|
||||
}
|
||||
@ -120,6 +117,13 @@ private fun Solid.withPosition(
|
||||
//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")
|
||||
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(
|
||||
context: GDMLTransformer,
|
||||
solid: GDMLSolid,
|
||||
name: String = "",
|
||||
block: Solid.() -> Unit = {}
|
||||
name: String = ""
|
||||
): Solid {
|
||||
//context.solidAdded(solid)
|
||||
val lScale = solid.lscale(context.lUnit)
|
||||
@ -168,11 +171,10 @@ private fun SolidGroup.addSolid(
|
||||
}
|
||||
is GDMLScaledSolid -> {
|
||||
//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")
|
||||
|
||||
addSolid(context, innerSolid, name) {
|
||||
block()
|
||||
addSolid(context, innerSolid, name).apply {
|
||||
scaleX *= solid.scale.x.toFloat()
|
||||
scaleY *= solid.scale.y.toFloat()
|
||||
scaleZ = solid.scale.z.toFloat()
|
||||
@ -199,8 +201,8 @@ private fun SolidGroup.addSolid(
|
||||
}
|
||||
}
|
||||
is GDMLBoolSolid -> {
|
||||
val first = solid.first.resolve(context.root) ?: error("")
|
||||
val second = solid.second.resolve(context.root) ?: error("")
|
||||
val first: GDMLSolid = solid.first.resolve(context.root) ?: error("")
|
||||
val second: GDMLSolid = solid.second.resolve(context.root) ?: error("")
|
||||
val type: CompositeType = when (solid) {
|
||||
is GDMLUnion -> CompositeType.UNION
|
||||
is GDMLSubtraction -> CompositeType.SUBTRACT
|
||||
@ -208,54 +210,51 @@ private fun SolidGroup.addSolid(
|
||||
}
|
||||
|
||||
return composite(type, name) {
|
||||
addSolid(context, first) {
|
||||
withPosition(
|
||||
context.lUnit,
|
||||
addSolid(context, first).withPosition(
|
||||
context.lUnit, context.aUnit,
|
||||
solid.resolveFirstPosition(context.root),
|
||||
solid.resolveFirstRotation(context.root),
|
||||
null
|
||||
)
|
||||
}
|
||||
addSolid(context, second) {
|
||||
withPosition(
|
||||
context.lUnit,
|
||||
|
||||
addSolid(context, second).withPosition(
|
||||
context.lUnit, context.aUnit,
|
||||
solid.resolvePosition(context.root),
|
||||
solid.resolveRotation(context.root),
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else -> error("Renderer for $solid not supported yet")
|
||||
}.apply(block)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val solidsName = "solids".asName()
|
||||
|
||||
private fun SolidGroup.addSolidWithCaching(
|
||||
context: GDMLTransformer,
|
||||
solid: GDMLSolid,
|
||||
volume: GDMLVolume,
|
||||
name: String = solid.name
|
||||
) {
|
||||
when (context.solidAction(solid)) {
|
||||
): Solid? {
|
||||
return when (context.solidAction(solid)) {
|
||||
GDMLTransformer.Action.ACCEPT -> {
|
||||
addSolid(context, solid, name) {
|
||||
context.configureSolid(this, volume, solid)
|
||||
}
|
||||
addSolid(context, solid, name)
|
||||
}
|
||||
GDMLTransformer.Action.CACHE -> {
|
||||
if (context.proto[solid.name] == null) {
|
||||
context.proto.addSolid(context, solid, name) {
|
||||
context.configureSolid(this, volume, solid)
|
||||
val fullName = solidsName + solid.name.asName()
|
||||
if (context.proto[fullName] == null) {
|
||||
val parent = (context.proto[solidsName] as? SolidGroup) ?: context.proto.group(solidsName)
|
||||
parent.addSolid(context, solid, solid.name)
|
||||
}
|
||||
}
|
||||
ref(solid.name.asName(), name)
|
||||
ref(fullName, name)
|
||||
}
|
||||
GDMLTransformer.Action.REJECT -> {
|
||||
//ignore
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val volumesName = "volumes".asName()
|
||||
@ -268,31 +267,20 @@ private fun SolidGroup.addPhysicalVolume(
|
||||
?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved")
|
||||
|
||||
// a special case for single solid volume
|
||||
// if (volume is GDMLVolume && volume.physVolumes.isEmpty() && volume.placement == null) {
|
||||
// val solid = volume.solidref.resolve(context.root)
|
||||
// ?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined")
|
||||
// addSolidWithCaching(context, solid, volume, physVolume.name ?: "").apply {
|
||||
// withPosition(
|
||||
// context.lUnit,
|
||||
// physVolume.resolvePosition(context.root),
|
||||
// physVolume.resolveRotation(context.root),
|
||||
// physVolume.resolveScale(context.root)
|
||||
// )
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
if (volume is GDMLVolume && volume.physVolumes.isEmpty() && volume.placement == null) {
|
||||
val solid = volume.solidref.resolve(context.root)
|
||||
?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined")
|
||||
addSolidWithCaching(context, solid, physVolume.name ?: "")?.apply {
|
||||
context.configureSolid(this, volume, solid)
|
||||
withPosition(context, physVolume)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
when (context.volumeAction(volume)) {
|
||||
GDMLTransformer.Action.ACCEPT -> {
|
||||
val group: SolidGroup = volume(context, volume)
|
||||
this[physVolume.name ?: ""] = group.apply {
|
||||
withPosition(
|
||||
context.lUnit,
|
||||
physVolume.resolvePosition(context.root),
|
||||
physVolume.resolveRotation(context.root),
|
||||
physVolume.resolveScale(context.root)
|
||||
)
|
||||
}
|
||||
this[physVolume.name ?: ""] = group.withPosition(context, physVolume)
|
||||
}
|
||||
GDMLTransformer.Action.CACHE -> {
|
||||
val fullName = volumesName + volume.name.asName()
|
||||
@ -300,14 +288,7 @@ private fun SolidGroup.addPhysicalVolume(
|
||||
context.proto[fullName] = volume(context, volume)
|
||||
}
|
||||
|
||||
this[physVolume.name ?: ""] = Proxy(this, fullName).apply {
|
||||
withPosition(
|
||||
context.lUnit,
|
||||
physVolume.resolvePosition(context.root),
|
||||
physVolume.resolveRotation(context.root),
|
||||
physVolume.resolveScale(context.root)
|
||||
)
|
||||
}
|
||||
this[physVolume.name ?: ""] = Proxy(this, fullName).withPosition(context, physVolume)
|
||||
}
|
||||
GDMLTransformer.Action.REJECT -> {
|
||||
//ignore
|
||||
@ -326,8 +307,6 @@ private fun SolidGroup.addDivisionVolume(
|
||||
set(Name.EMPTY, volume(context, volume))
|
||||
}
|
||||
|
||||
//private val solidsName = "solids".asName()
|
||||
|
||||
private fun volume(
|
||||
context: GDMLTransformer,
|
||||
group: GDMLGroup
|
||||
@ -336,7 +315,9 @@ private fun volume(
|
||||
val solid: GDMLSolid = group.solidref.resolve(context.root)
|
||||
?: 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) {
|
||||
is GDMLPhysVolume -> addPhysicalVolume(context, vol)
|
||||
|
@ -5,7 +5,6 @@ package hep.dataforge.vision.solid
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||
import hep.dataforge.names.*
|
||||
import hep.dataforge.values.asValue
|
||||
import hep.dataforge.vision.*
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
@ -13,36 +12,8 @@ import kotlinx.serialization.Transient
|
||||
import kotlinx.serialization.UseSerializers
|
||||
import kotlin.collections.set
|
||||
|
||||
|
||||
class AbstractProxy
|
||||
|
||||
/**
|
||||
* 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)
|
||||
abstract class AbstractProxy : AbstractVision(), VisionGroup {
|
||||
abstract val prototype: Vision
|
||||
|
||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
||||
return if (inherit) {
|
||||
@ -61,23 +32,10 @@ class Proxy private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override val children: Map<NameToken, ProxyChild>
|
||||
get() = (prototype as? VisionGroup)?.children
|
||||
?.filter { !it.key.toString().startsWith("@") }
|
||||
?.mapValues {
|
||||
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 var styles: List<String>
|
||||
get() = properties[Vision.STYLE_KEY].stringList + prototype.styles
|
||||
set(value) {
|
||||
config[Vision.STYLE_KEY] = value
|
||||
}
|
||||
|
||||
override fun getAllProperties(): Laminate =
|
||||
@ -87,28 +45,76 @@ class Proxy private constructor(
|
||||
//do nothing
|
||||
}
|
||||
|
||||
//override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) })
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
override val descriptor: NodeDescriptor?
|
||||
get() = prototype.descriptor
|
||||
/**
|
||||
* A proxy [Solid] to reuse a template object
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("solid.proxy")
|
||||
class Proxy private constructor(
|
||||
val templateName: Name
|
||||
) : AbstractProxy(), Solid {
|
||||
|
||||
inner class ProxyChild(val name: Name) : AbstractVision(), VisionGroup {
|
||||
constructor(parent: SolidGroup, templateName: Name) : this(templateName) {
|
||||
this.parent = parent
|
||||
}
|
||||
|
||||
val prototype: Vision get() = prototypeFor(name)
|
||||
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
|
||||
*/
|
||||
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 children: Map<NameToken, Vision>
|
||||
get() = (prototype as? VisionGroup)?.children?.mapValues { (key, _) ->
|
||||
ProxyChild(
|
||||
name + key.asName()
|
||||
)
|
||||
get() = (prototype as? VisionGroup)?.children
|
||||
?.filter { !it.key.toString().startsWith("@") }
|
||||
?.mapValues { (key, _) ->
|
||||
ProxyChild(name + key.asName())
|
||||
} ?: emptyMap()
|
||||
|
||||
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 {
|
||||
@ -170,8 +143,7 @@ class Proxy private constructor(
|
||||
|
||||
val Vision.prototype: Vision
|
||||
get() = when (this) {
|
||||
is Proxy -> prototype
|
||||
is Proxy.ProxyChild -> prototype
|
||||
is AbstractProxy -> prototype
|
||||
else -> this
|
||||
}
|
||||
|
||||
|
@ -99,13 +99,14 @@ fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup {
|
||||
tailrec fun PrototypeHolder.getPrototype(name: Name): Solid? =
|
||||
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.
|
||||
*/
|
||||
fun MutableVisionGroup.group(name: String = "", action: SolidGroup.() -> Unit = {}): SolidGroup =
|
||||
SolidGroup().apply(action).also {
|
||||
set(name, it)
|
||||
}
|
||||
fun MutableVisionGroup.group(name: String, action: SolidGroup.() -> Unit = {}): SolidGroup =
|
||||
SolidGroup().apply(action).also { set(name, it) }
|
||||
|
||||
/**
|
||||
* A special class which works as a holder for prototypes
|
||||
|
@ -35,19 +35,11 @@ abstract class MeshThreeFactory<in T : Solid>(
|
||||
|
||||
//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
|
||||
applyEdges(obj)
|
||||
applyWireFrame(obj)
|
||||
|
||||
//set position for mesh
|
||||
updatePosition(obj)
|
||||
|
||||
layers.enable(obj.layer)
|
||||
children.forEach {
|
||||
it.layers.enable(obj.layer)
|
||||
}
|
||||
}
|
||||
}.applyProperties(obj)
|
||||
|
||||
//add listener to object properties
|
||||
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) {
|
||||
val edges = children.find { it.name == "@edges" } as? LineSegments
|
||||
//inherited edges definition, enabled by default
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -4,7 +4,6 @@ import hep.dataforge.names.toName
|
||||
import hep.dataforge.vision.solid.Proxy
|
||||
import hep.dataforge.vision.solid.Proxy.Companion.PROXY_CHILD_PROPERTY_PREFIX
|
||||
import hep.dataforge.vision.solid.Solid
|
||||
import info.laht.threekt.core.BufferGeometry
|
||||
import info.laht.threekt.core.Object3D
|
||||
import info.laht.threekt.objects.Mesh
|
||||
import kotlin.reflect.KClass
|
||||
@ -14,16 +13,16 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy> {
|
||||
|
||||
override val type: KClass<Proxy> = Proxy::class
|
||||
|
||||
private fun Object3D.replicate(): Object3D {
|
||||
return when (this) {
|
||||
is Mesh -> Mesh(geometry as BufferGeometry, material)
|
||||
else -> clone(false)
|
||||
}.also { obj: Object3D ->
|
||||
children.forEach { child: Object3D ->
|
||||
obj.add(child.replicate())
|
||||
}
|
||||
}
|
||||
}
|
||||
// private fun Object3D.replicate(): Object3D {
|
||||
// return when (this) {
|
||||
// is Mesh -> Mesh(geometry as BufferGeometry, material)
|
||||
// else -> clone(false)
|
||||
// }.also { obj: Object3D ->
|
||||
// children.forEach { child: Object3D ->
|
||||
// obj.add(child.replicate())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
override fun invoke(obj: Proxy): Object3D {
|
||||
val template = obj.prototype
|
||||
@ -31,10 +30,13 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy> {
|
||||
three.buildObject3D(template)
|
||||
}
|
||||
|
||||
val object3D: Object3D = cachedObject.replicate()
|
||||
|
||||
val object3D: Object3D = cachedObject.clone()//cachedObject.replicate()
|
||||
object3D.updatePosition(obj)
|
||||
|
||||
if(object3D is Mesh){
|
||||
object3D.applyProperties(obj)
|
||||
}
|
||||
|
||||
obj.onPropertyChange(this) { name ->
|
||||
if (name.first()?.body == PROXY_CHILD_PROPERTY_PREFIX) {
|
||||
val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'")
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hep.dataforge.vision.solid.three
|
||||
|
||||
import hep.dataforge.js.requireJS
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.vision.bootstrap.accordion
|
||||
import hep.dataforge.vision.bootstrap.entry
|
||||
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)
|
||||
}
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") {
|
||||
entry("Settings") {
|
||||
div("row") {
|
||||
|
@ -33,8 +33,8 @@ import info.laht.threekt.materials.Material
|
||||
|
||||
open external class Mesh : Object3D {
|
||||
|
||||
constructor(geometry: Geometry, material: Material)
|
||||
constructor(geometry: BufferGeometry, material: Material)
|
||||
constructor(geometry: Geometry?, material: Material?)
|
||||
constructor(geometry: BufferGeometry?, material: Material?)
|
||||
|
||||
var geometry: dynamic
|
||||
var material: Material
|
||||
|
Loading…
Reference in New Issue
Block a user