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
import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.Colors
import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.solid.ambientLight
import space.kscience.visionforge.solid.set
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
vision("canvas") {
requirePlugin(Solids)
GdmlShowCase.cubes().toVision().also {
it.ambientLight {
color.set(Colors.white)
}
}
GdmlShowCase.cubes().toVision()
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,12 @@
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.LightSource
import space.kscience.visionforge.solid.SolidMaterial
import space.kscience.visionforge.visible
import three.lights.AmbientLight
import three.math.Color
import kotlin.reflect.KClass
@ -14,6 +20,16 @@ public object ThreeAmbientLightFactory : ThreeFactory<AmbientLightSource> {
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
}
}

View File

@ -29,8 +29,6 @@ public abstract class ThreeMeshFactory<in T : Solid>(
override fun build(three: ThreePlugin, vision: T, observe: Boolean): Mesh {
val geometry = buildGeometry(vision)
//val meshMeta: Meta = obj.properties[Material3D.MATERIAL_KEY]?.node ?: Meta.empty
val mesh = Mesh(geometry, ThreeMaterials.DEFAULT).apply {
matrixAutoUpdate = false
//set position for mesh
@ -46,11 +44,10 @@ public abstract class ThreeMeshFactory<in T : Solid>(
val oldGeometry = mesh.geometry
val newGeometry = buildGeometry(vision)
oldGeometry.attributes = newGeometry.attributes
//mesh.applyWireFrame(obj)
mesh.applyEdges(vision)
newGeometry.dispose()
}
//name.startsWith(WIREFRAME_KEY) -> mesh.applyWireFrame(obj)
name.startsWith(EDGES_KEY) -> mesh.applyEdges(vision)
else -> mesh.updateProperty(vision, name)
}
@ -62,18 +59,12 @@ public abstract class ThreeMeshFactory<in T : Solid>(
public companion object {
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 {
setMaterial(vision)
applyEdges(vision)
//applyWireFrame(obj)
layers.set(vision.layer)
children.forEach {
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"
// }
// )
// }
//}