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() {
override fun render(three: ThreePlugin): Object3D {
override suspend fun render(three: ThreePlugin): Object3D {
val geometry = BoxGeometry(xSize, ySize, 1)
val material = ThreeMaterials.DEFAULT.clone()

View File

@ -14,7 +14,7 @@ import kotlin.reflect.KClass
public object ThreeAmbientLightFactory : ThreeFactory<AmbientLightSource> {
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 {
color = vision.color.threeColor() ?: Color(0x404040)
intensity = vision.intensity.toDouble()

View File

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

View File

@ -22,7 +22,7 @@ import kotlin.reflect.KClass
public object ThreeCanvasLabelFactory : ThreeFactory<SolidLabel> {
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
canvas.width = 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 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()
?: error("First part of composite is not a mesh")
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].
* @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 const val TYPE: String = "threeFactory"
@ -41,14 +41,6 @@ public fun Object3D.updatePosition(vision: Vision) {
if (vision is Solid) {
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
if (quaternion != null) {

View File

@ -1,11 +1,24 @@
package space.kscience.visionforge.solid.three
import three.core.Object3D
import org.w3c.dom.url.URL
import space.kscience.visionforge.solid.SolidBase
import three.core.Object3D
/**
* A custom visual object that has its own Three.js renderer
*/
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> {
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 {
font = vision.fontFamily
size = 20

View File

@ -1,22 +1,22 @@
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.solid.PolyLine
import space.kscience.visionforge.solid.SolidMaterial
import space.kscience.visionforge.solid.color
import space.kscience.visionforge.solid.string
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.reflect.KClass
public object ThreeLineFactory : ThreeFactory<PolyLine> {
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 {
setFromPoints(Array((vision.points.size - 1) * 2) {
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
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 mesh = Mesh(geometry, ThreeMaterials.DEFAULT).apply {

View File

@ -15,7 +15,7 @@ import kotlin.reflect.KClass
public object ThreeMeshLineFactory : ThreeFactory<PolyLine> {
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(
Array((vision.points.size - 1) * 2) {
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 space.kscience.dataforge.context.*
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.update
import space.kscience.dataforge.names.*
import space.kscience.visionforge.ElementVisionRenderer
import space.kscience.visionforge.Vision
@ -47,7 +46,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
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 SolidReference -> ThreeReferenceFactory.build(this, vision, observe)
is SolidGroup -> {

View File

@ -13,7 +13,7 @@ public object ThreePointLightFactory : ThreeFactory<PointLightSource> {
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 {
matrixAutoUpdate = false
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 cachedObject = cache.getOrPut(template) {
three.buildObject3D(template)

View File

@ -7,7 +7,7 @@ import kotlin.reflect.KClass
public object ThreeSmartLineFactory : ThreeFactory<PolyLine> {
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) {
ThreeLineFactory.build(three, vision, observe)
} else {

View File

@ -12,14 +12,10 @@ import three.math.Vector3
import three.objects.Mesh
import three.textures.Texture
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)
internal fun Double.toRadians() = this * PI / 180
internal fun Any.dispose() {
when (this) {
is BufferGeometry -> dispose()