Make threeJS object generation suspend

This commit is contained in:
Alexander Nozik 2023-06-03 20:49:57 +03:00
parent 442fcb6c5b
commit 8204eb63c3
16 changed files with 39 additions and 37 deletions

View File

@ -25,7 +25,7 @@ internal fun SolidGroup.varBox(
internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision() { internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision() {
override fun render(three: ThreePlugin): Object3D { override suspend fun render(three: ThreePlugin): Object3D {
val geometry = BoxGeometry(xSize, ySize, 1) val geometry = BoxGeometry(xSize, ySize, 1)
val material = ThreeMaterials.DEFAULT.clone() val material = ThreeMaterials.DEFAULT.clone()

View File

@ -14,7 +14,7 @@ import kotlin.reflect.KClass
public object ThreeAmbientLightFactory : ThreeFactory<AmbientLightSource> { public object ThreeAmbientLightFactory : ThreeFactory<AmbientLightSource> {
override val type: KClass<in AmbientLightSource> get() = AmbientLightSource::class override val type: KClass<in AmbientLightSource> get() = AmbientLightSource::class
override fun build(three: ThreePlugin, vision: AmbientLightSource, observe: Boolean): AmbientLight { override suspend fun build(three: ThreePlugin, vision: AmbientLightSource, observe: Boolean): AmbientLight {
val res = AmbientLight().apply { val res = AmbientLight().apply {
color = vision.color.threeColor() ?: Color(0x404040) color = vision.color.threeColor() ?: Color(0x404040)
intensity = vision.intensity.toDouble() intensity = vision.intensity.toDouble()

View File

@ -1,6 +1,7 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import kotlinx.browser.window import kotlinx.browser.window
import kotlinx.coroutines.launch
import org.w3c.dom.Element import org.w3c.dom.Element
import org.w3c.dom.HTMLCanvasElement import org.w3c.dom.HTMLCanvasElement
import org.w3c.dom.Node import org.w3c.dom.Node
@ -264,11 +265,12 @@ public class ThreeCanvas(
scene.findChild("@root".asName())?.let { scene.remove(it) } scene.findChild("@root".asName())?.let { scene.remove(it) }
root?.dispose() root?.dispose()
} }
three.context.launch {
val object3D = three.buildObject3D(vision) val object3D = three.buildObject3D(vision)
object3D.name = "@root" object3D.name = "@root"
scene.add(object3D) scene.add(object3D)
root = object3D root = object3D
}
} }
private var selected: Object3D? = null private var selected: Object3D? = null

View File

@ -22,7 +22,7 @@ import kotlin.reflect.KClass
public object ThreeCanvasLabelFactory : ThreeFactory<SolidLabel> { public object ThreeCanvasLabelFactory : ThreeFactory<SolidLabel> {
override val type: KClass<in SolidLabel> get() = SolidLabel::class override val type: KClass<in SolidLabel> get() = SolidLabel::class
override fun build(three: ThreePlugin, vision: SolidLabel, observe: Boolean): Object3D { override suspend fun build(three: ThreePlugin, vision: SolidLabel, observe: Boolean): Object3D {
val canvas = document.createElement("canvas") as HTMLCanvasElement val canvas = document.createElement("canvas") as HTMLCanvasElement
canvas.width = 200 canvas.width = 200
canvas.height = 200 canvas.height = 200

View File

@ -38,7 +38,7 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : ThreeFactory
override val type: KClass<in Composite> get() = Composite::class override val type: KClass<in Composite> get() = Composite::class
override fun build(three: ThreePlugin, vision: Composite, observe: Boolean): Mesh { override suspend fun build(three: ThreePlugin, vision: Composite, observe: Boolean): Mesh {
val first = three.buildObject3D(vision.first, observe).takeIfMesh() val first = three.buildObject3D(vision.first, observe).takeIfMesh()
?: error("First part of composite is not a mesh") ?: error("First part of composite is not a mesh")
val second = three.buildObject3D(vision.second, observe).takeIfMesh() val second = three.buildObject3D(vision.second, observe).takeIfMesh()

View File

@ -26,7 +26,7 @@ public interface ThreeFactory<in T : Vision> {
* Build an [Object3D] from [vision]. * Build an [Object3D] from [vision].
* @param observe if false, does not observe the changes in [vision] after render (useful for statics). * @param observe if false, does not observe the changes in [vision] after render (useful for statics).
*/ */
public fun build(three: ThreePlugin, vision: T, observe: Boolean = true): Object3D public suspend fun build(three: ThreePlugin, vision: T, observe: Boolean = true): Object3D
public companion object { public companion object {
public const val TYPE: String = "threeFactory" public const val TYPE: String = "threeFactory"
@ -41,14 +41,6 @@ public fun Object3D.updatePosition(vision: Vision) {
if (vision is Solid) { if (vision is Solid) {
position.set(vision.x, vision.y, vision.z) position.set(vision.x, vision.y, vision.z)
// val quaternion = obj.quaternion
//
// if (quaternion != null) {
// val (x, y, z, w) = quaternion
// setRotationFromQuaternion(Quaternion(x, y, z, w))
// } else {
// setRotationFromEuler( Euler(obj.rotationX, obj.rotationY, obj.rotationZ, obj.rotationOrder.name))
// }
val quaternion = vision.quaternionValue val quaternion = vision.quaternionValue
if (quaternion != null) { if (quaternion != null) {

View File

@ -1,11 +1,24 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import three.core.Object3D import org.w3c.dom.url.URL
import space.kscience.visionforge.solid.SolidBase import space.kscience.visionforge.solid.SolidBase
import three.core.Object3D
/** /**
* A custom visual object that has its own Three.js renderer * A custom visual object that has its own Three.js renderer
*/ */
public abstract class ThreeJsVision : SolidBase<ThreeJsVision>() { public abstract class ThreeJsVision : SolidBase<ThreeJsVision>() {
public abstract fun render(three: ThreePlugin): Object3D public abstract suspend fun render(three: ThreePlugin): Object3D
}
public class ThreeStlVision(val url: URL): ThreeJsVision(){
override suspend fun render(three: ThreePlugin): Object3D {
// suspendCoroutine {
//
// }
// STLLoader()
TODO()
}
} }

View File

@ -17,7 +17,7 @@ import kotlin.reflect.KClass
public object ThreeLabelFactory : ThreeFactory<SolidLabel> { public object ThreeLabelFactory : ThreeFactory<SolidLabel> {
override val type: KClass<in SolidLabel> get() = SolidLabel::class override val type: KClass<in SolidLabel> get() = SolidLabel::class
override fun build(three: ThreePlugin, vision: SolidLabel, observe: Boolean): Object3D { override suspend fun build(three: ThreePlugin, vision: SolidLabel, observe: Boolean): Object3D {
val textGeo = TextBufferGeometry(vision.text, jso { val textGeo = TextBufferGeometry(vision.text, jso {
font = vision.fontFamily font = vision.fontFamily
size = 20 size = 20

View File

@ -1,22 +1,22 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import three.core.BufferGeometry
import three.core.Object3D
import three.math.Color
import three.objects.LineSegments
import space.kscience.visionforge.onPropertyChange import space.kscience.visionforge.onPropertyChange
import space.kscience.visionforge.solid.PolyLine import space.kscience.visionforge.solid.PolyLine
import space.kscience.visionforge.solid.SolidMaterial import space.kscience.visionforge.solid.SolidMaterial
import space.kscience.visionforge.solid.color import space.kscience.visionforge.solid.color
import space.kscience.visionforge.solid.string import space.kscience.visionforge.solid.string
import space.kscience.visionforge.solid.three.ThreeMaterials.DEFAULT_LINE_COLOR import space.kscience.visionforge.solid.three.ThreeMaterials.DEFAULT_LINE_COLOR
import three.core.BufferGeometry
import three.core.Object3D
import three.math.Color
import three.objects.LineSegments
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.reflect.KClass import kotlin.reflect.KClass
public object ThreeLineFactory : ThreeFactory<PolyLine> { public object ThreeLineFactory : ThreeFactory<PolyLine> {
override val type: KClass<PolyLine> get() = PolyLine::class override val type: KClass<PolyLine> get() = PolyLine::class
override fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D { override suspend fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D {
val geometry = BufferGeometry().apply { val geometry = BufferGeometry().apply {
setFromPoints(Array((vision.points.size - 1) * 2) { setFromPoints(Array((vision.points.size - 1) * 2) {
vision.points[ceil(it / 2.0).toInt()].toVector() vision.points[ceil(it / 2.0).toInt()].toVector()

View File

@ -26,7 +26,7 @@ public abstract class ThreeMeshFactory<in T : Solid>(
*/ */
public abstract fun buildGeometry(obj: T): BufferGeometry public abstract fun buildGeometry(obj: T): BufferGeometry
override fun build(three: ThreePlugin, vision: T, observe: Boolean): Mesh { override suspend fun build(three: ThreePlugin, vision: T, observe: Boolean): Mesh {
val geometry = buildGeometry(vision) val geometry = buildGeometry(vision)
val mesh = Mesh(geometry, ThreeMaterials.DEFAULT).apply { val mesh = Mesh(geometry, ThreeMaterials.DEFAULT).apply {

View File

@ -15,7 +15,7 @@ import kotlin.reflect.KClass
public object ThreeMeshLineFactory : ThreeFactory<PolyLine> { public object ThreeMeshLineFactory : ThreeFactory<PolyLine> {
override val type: KClass<in PolyLine> get() = PolyLine::class override val type: KClass<in PolyLine> get() = PolyLine::class
override fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D { override suspend fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D {
val geometry = MeshLine( val geometry = MeshLine(
Array((vision.points.size - 1) * 2) { Array((vision.points.size - 1) * 2) {
vision.points[ceil(it / 2.0).toInt()].toVector() vision.points[ceil(it / 2.0).toInt()].toVector()

View File

@ -6,7 +6,6 @@ import org.w3c.dom.Element
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import space.kscience.dataforge.context.* import space.kscience.dataforge.context.*
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.update
import space.kscience.dataforge.names.* import space.kscience.dataforge.names.*
import space.kscience.visionforge.ElementVisionRenderer import space.kscience.visionforge.ElementVisionRenderer
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
@ -47,7 +46,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
as ThreeFactory<Solid>? as ThreeFactory<Solid>?
} }
public fun buildObject3D(vision: Solid, observe: Boolean = true): Object3D = when (vision) { public suspend fun buildObject3D(vision: Solid, observe: Boolean = true): Object3D = when (vision) {
is ThreeJsVision -> vision.render(this) is ThreeJsVision -> vision.render(this)
is SolidReference -> ThreeReferenceFactory.build(this, vision, observe) is SolidReference -> ThreeReferenceFactory.build(this, vision, observe)
is SolidGroup -> { is SolidGroup -> {

View File

@ -13,7 +13,7 @@ public object ThreePointLightFactory : ThreeFactory<PointLightSource> {
private val DEFAULT_COLOR = Color(0x404040) private val DEFAULT_COLOR = Color(0x404040)
override fun build(three: ThreePlugin, vision: PointLightSource, observe: Boolean): PointLight { override suspend fun build(three: ThreePlugin, vision: PointLightSource, observe: Boolean): PointLight {
val res = PointLight().apply { val res = PointLight().apply {
matrixAutoUpdate = false matrixAutoUpdate = false
color = vision.color.threeColor() ?: DEFAULT_COLOR color = vision.color.threeColor() ?: DEFAULT_COLOR

View File

@ -31,7 +31,7 @@ public object ThreeReferenceFactory : ThreeFactory<SolidReference> {
} }
} }
override fun build(three: ThreePlugin, vision: SolidReference, observe: Boolean): Object3D { override suspend fun build(three: ThreePlugin, vision: SolidReference, observe: Boolean): Object3D {
val template = vision.prototype val template = vision.prototype
val cachedObject = cache.getOrPut(template) { val cachedObject = cache.getOrPut(template) {
three.buildObject3D(template) three.buildObject3D(template)

View File

@ -7,7 +7,7 @@ import kotlin.reflect.KClass
public object ThreeSmartLineFactory : ThreeFactory<PolyLine> { public object ThreeSmartLineFactory : ThreeFactory<PolyLine> {
override val type: KClass<in PolyLine> get() = PolyLine::class override val type: KClass<in PolyLine> get() = PolyLine::class
override fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D { override suspend fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D {
return if (vision.thickness == 1.0) { return if (vision.thickness == 1.0) {
ThreeLineFactory.build(three, vision, observe) ThreeLineFactory.build(three, vision, observe)
} else { } else {

View File

@ -12,14 +12,10 @@ import three.math.Vector3
import three.objects.Mesh import three.objects.Mesh
import three.textures.Texture import three.textures.Texture
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.math.PI
public val Meta.vector: Vector3 get() = Vector3(this["x"].float ?: 0f, this["y"].float ?: 0f, this["z"].float ?: 0f) public val Meta.vector: Vector3 get() = Vector3(this["x"].float ?: 0f, this["y"].float ?: 0f, this["z"].float ?: 0f)
internal fun Double.toRadians() = this * PI / 180
internal fun Any.dispose() { internal fun Any.dispose() {
when (this) { when (this) {
is BufferGeometry -> dispose() is BufferGeometry -> dispose()