Fix light for GDML and ambient lighg updates

This commit is contained in:
Alexander Nozik 2022-08-24 09:59:10 +03:00
parent 56d577453a
commit f0a6e12358
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
8 changed files with 66 additions and 72 deletions

View File

@ -1,20 +1,13 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import space.kscience.gdml.GdmlShowCase import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.Colors
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.set
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) { fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
vision("canvas") { vision("canvas") {
requirePlugin(Solids) requirePlugin(Solids)
GdmlShowCase.cubes().toVision().also { GdmlShowCase.cubes().toVision()
it.ambientLight {
color.set(Colors.white)
}
}
} }
} }

View File

@ -223,7 +223,7 @@ fun main() = makeVisionFile(Path.of("curves.html"), resourceLocation = ResourceL
} }
} }
}.toVision { }.toVision {
configure { _, solid, _ -> solids { _, solid, _ ->
//disable visibility for the world box //disable visibility for the world box
if(solid.name == "world"){ if(solid.name == "world"){
visible = false visible = false

View File

@ -4,9 +4,7 @@ import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.gdml.* import space.kscience.gdml.*
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.SolidMaterial
import space.kscience.visionforge.solid.set
import space.kscience.visionforge.useStyle import space.kscience.visionforge.useStyle
import kotlin.random.Random import kotlin.random.Random
@ -70,7 +68,7 @@ public class GdmlLoaderOptions {
} }
private set private set
public fun configure(block: Solid.(parent: GdmlVolume, solid: GdmlSolid, material: GdmlMaterial) -> Unit) { public fun solids(block: Solid.(parent: GdmlVolume, solid: GdmlSolid, material: GdmlMaterial) -> Unit) {
val oldConfigure = configureSolid val oldConfigure = configureSolid
configureSolid = { parent: GdmlVolume, solid: GdmlSolid, material: GdmlMaterial -> configureSolid = { parent: GdmlVolume, solid: GdmlSolid, material: GdmlMaterial ->
oldConfigure(parent, solid, material) oldConfigure(parent, solid, material)
@ -79,6 +77,8 @@ public class GdmlLoaderOptions {
} }
public var light: LightSource? = AmbientLightSource()
public companion object { public companion object {
private val random: Random = Random(222) private val random: Random = Random(222)

View File

@ -27,10 +27,10 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
/** /**
* A special group for local templates * A special group for local templates
*/ */
private val proto = SolidGroup() private val templates = SolidGroup()
private val solids = proto.solidGroup(solidsName) { private val solids = templates.solidGroup(solidsName) {
properties["edges.enabled"] = false edges(false)
} }
private val referenceStore = HashMap<Name, MutableList<SolidReference>>() private val referenceStore = HashMap<Name, MutableList<SolidReference>>()
@ -46,7 +46,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
private fun proxySolid(root: Gdml, group: SolidGroup, solid: GdmlSolid, name: String): SolidReference { private fun proxySolid(root: Gdml, group: SolidGroup, solid: GdmlSolid, name: String): SolidReference {
val templateName = solidsName + name val templateName = solidsName + name
if (proto[templateName] == null) { if (templates[templateName] == null) {
solids.addSolid(root, solid, name) solids.addSolid(root, solid, name)
} }
val ref = group.ref(templateName, name) val ref = group.ref(templateName, name)
@ -61,8 +61,8 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
volume: GdmlGroup, volume: GdmlGroup,
): SolidReference { ): SolidReference {
val templateName = volumesName + volume.name.asName() val templateName = volumesName + volume.name.asName()
if (proto[templateName] == null) { if (templates[templateName] == null) {
proto.setChild(templateName, volume(root, volume)) templates.setChild(templateName, volume(root, volume))
} }
val ref = group.ref(templateName, physVolume.name).withPosition(root, physVolume) val ref = group.ref(templateName, physVolume.name).withPosition(root, physVolume)
referenceStore.getOrPut(templateName) { ArrayList() }.add(ref) referenceStore.getOrPut(templateName) { ArrayList() }.add(ref)
@ -139,6 +139,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
angle = solid.deltaphi * aScale, angle = solid.deltaphi * aScale,
name = name name = name
) )
is GdmlCone -> if (solid.rmin1.toDouble() == 0.0 && solid.rmin2.toDouble() == 0.0) { is GdmlCone -> if (solid.rmin1.toDouble() == 0.0 && solid.rmin2.toDouble() == 0.0) {
cone( cone(
bottomRadius = solid.rmax1 * lScale, bottomRadius = solid.rmax1 * lScale,
@ -160,6 +161,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
name = name name = name
) )
} }
is GdmlXtru -> extruded(name) { is GdmlXtru -> extruded(name) {
shape { shape {
solid.vertices.forEach { solid.vertices.forEach {
@ -175,6 +177,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
) )
} }
} }
is GdmlScaledSolid -> { is GdmlScaledSolid -> {
//Add solid with modified scale //Add solid with modified scale
val innerSolid: GdmlSolid = solid.solidref.resolve(root) val innerSolid: GdmlSolid = solid.solidref.resolve(root)
@ -186,6 +189,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
scaleZ = solid.scale.z.toFloat() scaleZ = solid.scale.z.toFloat()
} }
} }
is GdmlSphere -> sphereLayer( is GdmlSphere -> sphereLayer(
outerRadius = solid.rmax * lScale, outerRadius = solid.rmax * lScale,
innerRadius = solid.rmin * lScale, innerRadius = solid.rmin * lScale,
@ -195,6 +199,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
thetaStart = solid.starttheta * aScale, thetaStart = solid.starttheta * aScale,
name = name, name = name,
) )
is GdmlOrb -> sphere(solid.r * lScale, name = name) is GdmlOrb -> sphere(solid.r * lScale, name = name)
is GdmlPolyhedra -> extruded(name) { is GdmlPolyhedra -> extruded(name) {
//getting the radius of first //getting the radius of first
@ -211,6 +216,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
layer(plane.z * lScale, scale = plane.rmax * lScale / baseRadius) layer(plane.z * lScale, scale = plane.rmax * lScale / baseRadius)
} }
} }
is GdmlBoolSolid -> { is GdmlBoolSolid -> {
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("")
@ -235,6 +241,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
} }
} }
is GdmlTrapezoid -> { is GdmlTrapezoid -> {
val dxBottom = solid.x1.toDouble() / 2 val dxBottom = solid.x1.toDouble() / 2
val dxTop = solid.x2.toDouble() / 2 val dxTop = solid.x2.toDouble() / 2
@ -251,6 +258,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
val node8 = Point3D(-dxTop, dyTop, dz) val node8 = Point3D(-dxTop, dyTop, dz)
hexagon(node1, node2, node3, node4, node5, node6, node7, node8, name) hexagon(node1, node2, node3, node4, node5, node6, node7, node8, name)
} }
is GdmlEllipsoid -> TODO("Renderer for $solid not supported yet") is GdmlEllipsoid -> TODO("Renderer for $solid not supported yet")
is GdmlElTube -> TODO("Renderer for $solid not supported yet") is GdmlElTube -> TODO("Renderer for $solid not supported yet")
is GdmlElCone -> TODO("Renderer for $solid not supported yet") is GdmlElCone -> TODO("Renderer for $solid not supported yet")
@ -271,9 +279,11 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
GdmlLoaderOptions.Action.ADD -> { GdmlLoaderOptions.Action.ADD -> {
addSolid(root, solid, name) addSolid(root, solid, name)
} }
GdmlLoaderOptions.Action.PROTOTYPE -> { GdmlLoaderOptions.Action.PROTOTYPE -> {
proxySolid(root, this, solid, name ?: solid.name) proxySolid(root, this, solid, name ?: solid.name)
} }
GdmlLoaderOptions.Action.REJECT -> { GdmlLoaderOptions.Action.REJECT -> {
//ignore //ignore
null null
@ -304,9 +314,11 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
val group: SolidGroup = volume(root, volume) val group: SolidGroup = volume(root, volume)
this.setChild(physVolume.name, group.withPosition(root, physVolume)) this.setChild(physVolume.name, group.withPosition(root, physVolume))
} }
GdmlLoaderOptions.Action.PROTOTYPE -> { GdmlLoaderOptions.Action.PROTOTYPE -> {
proxyVolume(root, this, physVolume, volume) proxyVolume(root, this, physVolume, volume)
} }
GdmlLoaderOptions.Action.REJECT -> { GdmlLoaderOptions.Action.REJECT -> {
//ignore //ignore
} }
@ -348,35 +360,36 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) {
} }
} }
private fun finalize(final: SolidGroup): SolidGroup { fun transform(root: Gdml): SolidGroup {
val rootStyle by final.style("gdml") { val rootSolid = volume(root, root.world.resolve(root) ?: error("GDML root is not resolved"))
val rootStyle by rootSolid.style("gdml") {
Solid.ROTATION_ORDER_KEY put RotationOrder.ZXY Solid.ROTATION_ORDER_KEY put RotationOrder.ZXY
} }
final.useStyle(rootStyle, false)
final.prototypes { rootSolid.useStyle(rootStyle, false)
proto.items.forEach { (token, item) ->
rootSolid.prototypes {
templates.items.forEach { (token, item) ->
item.parent = null item.parent = null
setChild(token.asName(), item as? Solid) setChild(token.asName(), item as? Solid)
} }
} }
settings.styleCache.forEach { settings.styleCache.forEach {
final.styleSheet { rootSolid.styleSheet {
define(it.key.toString(), it.value) define(it.key.toString(), it.value)
} }
} }
return final return rootSolid
} }
fun transform(root: Gdml): SolidGroup =
finalize(volume(root, root.world.resolve(root) ?: error("GDML root is not resolved")))
} }
public fun Gdml.toVision(block: GdmlLoaderOptions.() -> Unit = {}): SolidGroup { public fun Gdml.toVision(block: GdmlLoaderOptions.() -> Unit = {}): SolidGroup {
val settings = GdmlLoaderOptions().apply(block) val settings = GdmlLoaderOptions().apply(block)
val context = GdmlLoader(settings) return GdmlLoader(settings).transform(this).also {
return context.transform(this) it.children["light"] = settings.light
}
} }
/** /**

View File

@ -28,8 +28,10 @@ public class ColorAccessor(
} }
} }
public fun Vision.color(): ReadOnlyProperty<Vision, ColorAccessor> = ReadOnlyProperty { _, property -> public fun Vision.color(
ColorAccessor(properties.root(true), property.name.asName()) propertyName: Name? = null,
): ReadOnlyProperty<Vision, ColorAccessor> = ReadOnlyProperty { _, property ->
ColorAccessor(properties.root(true), propertyName ?: property.name.asName())
} }
public var ColorAccessor?.string: String? public var ColorAccessor?.string: String?

View File

@ -7,16 +7,20 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.node import space.kscience.dataforge.meta.descriptors.node
import space.kscience.dataforge.meta.descriptors.value import space.kscience.dataforge.meta.descriptors.value
import space.kscience.dataforge.meta.number import space.kscience.dataforge.meta.number
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName
import space.kscience.visionforge.* import space.kscience.visionforge.*
@Serializable @Serializable
public abstract class LightSource : SolidBase<LightSource>() { public abstract class LightSource : SolidBase<LightSource>() {
override val descriptor: MetaDescriptor get() = LightSource.descriptor override val descriptor: MetaDescriptor get() = LightSource.descriptor
public val color: ColorAccessor by color() public val color: ColorAccessor by color(SolidMaterial.COLOR_KEY)
public var intensity: Number by properties.root(includeStyles = false).number { 1.0 } public var intensity: Number by properties.root(includeStyles = false).number(INTENSITY_KEY) { 1.0 }
public companion object { public companion object {
public val INTENSITY_KEY: Name = "intensity".asName()
public val descriptor: MetaDescriptor by lazy { public val descriptor: MetaDescriptor by lazy {
MetaDescriptor { MetaDescriptor {
value(Vision.VISIBLE_KEY, ValueType.BOOLEAN) { value(Vision.VISIBLE_KEY, ValueType.BOOLEAN) {
@ -27,6 +31,7 @@ public abstract class LightSource : SolidBase<LightSource>() {
value(LightSource::color.name, ValueType.STRING, ValueType.NUMBER) { value(LightSource::color.name, ValueType.STRING, ValueType.NUMBER) {
inherited = false inherited = false
widgetType = "color" widgetType = "color"
default(Colors.white)
} }
value(LightSource::intensity.name, ValueType.NUMBER) { value(LightSource::intensity.name, ValueType.NUMBER) {
@ -34,11 +39,6 @@ public abstract class LightSource : SolidBase<LightSource>() {
default(1.0) default(1.0)
} }
value(SolidMaterial.COLOR_KEY, ValueType.STRING, ValueType.NUMBER) {
inherited = false
widgetType = "color"
}
node(Solid.POSITION_KEY) { node(Solid.POSITION_KEY) {
hide() hide()
} }

View File

@ -1,6 +1,12 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Vision
import space.kscience.visionforge.onPropertyChange
import space.kscience.visionforge.solid.AmbientLightSource import space.kscience.visionforge.solid.AmbientLightSource
import space.kscience.visionforge.solid.LightSource
import space.kscience.visionforge.solid.SolidMaterial
import space.kscience.visionforge.visible
import three.lights.AmbientLight import three.lights.AmbientLight
import three.math.Color import three.math.Color
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -14,6 +20,16 @@ public object ThreeAmbientLightFactory : ThreeFactory<AmbientLightSource> {
intensity = vision.intensity.toDouble() intensity = vision.intensity.toDouble()
} }
if (observe) {
vision.onPropertyChange(three.context) { propertyName: Name ->
when (propertyName) {
Vision.VISIBLE_KEY -> res.visible = vision.visible ?: true
SolidMaterial.COLOR_KEY -> res.color = vision.color.threeColor() ?: Color(0x404040)
LightSource.INTENSITY_KEY -> res.intensity = vision.intensity.toDouble()
}
}
}
return res return res
} }
} }

View File

@ -29,8 +29,6 @@ public abstract class ThreeMeshFactory<in T : Solid>(
override fun build(three: ThreePlugin, vision: T, observe: Boolean): Mesh { override fun build(three: ThreePlugin, vision: T, observe: Boolean): Mesh {
val geometry = buildGeometry(vision) val geometry = buildGeometry(vision)
//val meshMeta: Meta = obj.properties[Material3D.MATERIAL_KEY]?.node ?: Meta.empty
val mesh = Mesh(geometry, ThreeMaterials.DEFAULT).apply { val mesh = Mesh(geometry, ThreeMaterials.DEFAULT).apply {
matrixAutoUpdate = false matrixAutoUpdate = false
//set position for mesh //set position for mesh
@ -46,11 +44,10 @@ public abstract class ThreeMeshFactory<in T : Solid>(
val oldGeometry = mesh.geometry val oldGeometry = mesh.geometry
val newGeometry = buildGeometry(vision) val newGeometry = buildGeometry(vision)
oldGeometry.attributes = newGeometry.attributes oldGeometry.attributes = newGeometry.attributes
//mesh.applyWireFrame(obj)
mesh.applyEdges(vision) mesh.applyEdges(vision)
newGeometry.dispose() newGeometry.dispose()
} }
//name.startsWith(WIREFRAME_KEY) -> mesh.applyWireFrame(obj)
name.startsWith(EDGES_KEY) -> mesh.applyEdges(vision) name.startsWith(EDGES_KEY) -> mesh.applyEdges(vision)
else -> mesh.updateProperty(vision, name) else -> mesh.updateProperty(vision, name)
} }
@ -62,18 +59,12 @@ public abstract class ThreeMeshFactory<in T : Solid>(
public companion object { public companion object {
internal const val EDGES_OBJECT_NAME: String = "@edges" internal const val EDGES_OBJECT_NAME: String = "@edges"
//public val WIREFRAME_KEY: Name = "wireframe".asName()
//public val WIREFRAME_ENABLED_KEY: Name = WIREFRAME_KEY + ENABLED_KEY
//public val WIREFRAME_MATERIAL_KEY: Name = WIREFRAME_KEY + SolidMaterial.MATERIAL_KEY
} }
} }
internal fun Mesh.applyProperties(vision: Solid): Mesh = apply { internal fun Mesh.applyProperties(vision: Solid): Mesh = apply {
setMaterial(vision) setMaterial(vision)
applyEdges(vision) applyEdges(vision)
//applyWireFrame(obj)
layers.set(vision.layer) layers.set(vision.layer)
children.forEach { children.forEach {
it.layers.set(vision.layer) it.layers.set(vision.layer)
@ -104,24 +95,3 @@ public fun Mesh.applyEdges(vision: Solid) {
} }
} }
} }
//public fun Mesh.applyWireFrame(obj: Solid) {
// children.find { it.name == "@wireframe" }?.let {
// remove(it)
// (it as LineSegments).dispose()
// }
// //inherited wireframe definition, disabled by default
// if (obj.getProperty(MeshThreeFactory.WIREFRAME_ENABLED_KEY).boolean == true) {
// val bufferGeometry = geometry as? BufferGeometry ?: return
// val material =
// ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.WIREFRAME_MATERIAL_KEY).node, true)
// add(
// LineSegments(
// WireframeGeometry(bufferGeometry),
// material
// ).apply {
// name = "@wireframe"
// }
// )
// }
//}