forked from kscience/visionforge
Make Axes a separate object
This commit is contained in:
parent
2b70afdb86
commit
20851baaf5
22
demo/playground/src/jvmMain/kotlin/axes.kt
Normal file
22
demo/playground/src/jvmMain/kotlin/axes.kt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package space.kscience.visionforge.examples
|
||||||
|
|
||||||
|
import space.kscience.kmath.geometry.Euclidean3DSpace
|
||||||
|
import space.kscience.kmath.geometry.radians
|
||||||
|
import space.kscience.visionforge.html.ResourceLocation
|
||||||
|
import space.kscience.visionforge.solid.*
|
||||||
|
import kotlin.math.PI
|
||||||
|
|
||||||
|
fun main() = makeVisionFile(resourceLocation = ResourceLocation.SYSTEM) {
|
||||||
|
vision("canvas") {
|
||||||
|
requirePlugin(Solids)
|
||||||
|
solid {
|
||||||
|
axes(100, "root-axes")
|
||||||
|
solidGroup("group") {
|
||||||
|
z = 100
|
||||||
|
rotate((PI / 4).radians, Euclidean3DSpace.vector(1, 1, 1))
|
||||||
|
axes(100, "local-axes")
|
||||||
|
box(50, 50, 50, "box")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package space.kscience.visionforge.solid
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import space.kscience.visionforge.MutableVisionContainer
|
||||||
|
import space.kscience.visionforge.VisionBuilder
|
||||||
|
import space.kscience.visionforge.setChild
|
||||||
|
|
||||||
|
public abstract class MiscSolid: SolidBase<MiscSolid>()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("solid.axes")
|
||||||
|
public class AxesSolid(public val size: Double): MiscSolid(){
|
||||||
|
public companion object{
|
||||||
|
public const val AXES_NAME: String = "@xes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisionBuilder
|
||||||
|
public fun MutableVisionContainer<Solid>.axes(
|
||||||
|
size: Number,
|
||||||
|
name: String = "@axes",
|
||||||
|
block: AxesSolid.() -> Unit = {},
|
||||||
|
): AxesSolid = AxesSolid(size.toDouble()).apply(block).also {
|
||||||
|
setChild(name, it)
|
||||||
|
}
|
@ -9,9 +9,7 @@ import space.kscience.dataforge.names.Name
|
|||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.kmath.complex.Quaternion
|
import space.kscience.kmath.complex.Quaternion
|
||||||
import space.kscience.kmath.geometry.RotationOrder
|
import space.kscience.kmath.geometry.*
|
||||||
import space.kscience.kmath.geometry.fromEuler
|
|
||||||
import space.kscience.kmath.geometry.radians
|
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
import space.kscience.visionforge.Vision.Companion.VISIBLE_KEY
|
import space.kscience.visionforge.Vision.Companion.VISIBLE_KEY
|
||||||
import space.kscience.visionforge.solid.Solid.Companion.DETAIL_KEY
|
import space.kscience.visionforge.solid.Solid.Companion.DETAIL_KEY
|
||||||
@ -242,14 +240,13 @@ public var Solid.quaternion: Quaternion
|
|||||||
quaternionValue = value
|
quaternionValue = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//public var Solid.quaternion: Quaternion?
|
|
||||||
// get() = meta[Solid::quaternion.name]?.value?.doubleArray?.let { Quaternion(it) }
|
|
||||||
// set(value) {
|
|
||||||
// meta[Solid::quaternion.name] = value?.values?.asValue()
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
public var Solid.scaleX: Number by float(X_SCALE_KEY, 1f)
|
public var Solid.scaleX: Number by float(X_SCALE_KEY, 1f)
|
||||||
public var Solid.scaleY: Number by float(Y_SCALE_KEY, 1f)
|
public var Solid.scaleY: Number by float(Y_SCALE_KEY, 1f)
|
||||||
public var Solid.scaleZ: Number by float(Z_SCALE_KEY, 1f)
|
public var Solid.scaleZ: Number by float(Z_SCALE_KEY, 1f)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add rotation with given [angle] relative to given [axis]
|
||||||
|
*/
|
||||||
|
public fun Solid.rotate(angle: Angle, axis: DoubleVector3D) {
|
||||||
|
quaternion = Quaternion.fromRotation(angle, axis)
|
||||||
|
}
|
@ -48,6 +48,8 @@ public class Solids(meta: Meta) : VisionPlugin(meta), MutableVisionContainer<Sol
|
|||||||
|
|
||||||
subclass(AmbientLightSource.serializer())
|
subclass(AmbientLightSource.serializer())
|
||||||
subclass(PointLightSource.serializer())
|
subclass(PointLightSource.serializer())
|
||||||
|
|
||||||
|
subclass(AxesSolid.serializer())
|
||||||
}
|
}
|
||||||
|
|
||||||
public val serializersModuleForSolids: SerializersModule = SerializersModule {
|
public val serializersModuleForSolids: SerializersModule = SerializersModule {
|
||||||
|
@ -7,19 +7,19 @@ import space.kscience.visionforge.VisionBuilder
|
|||||||
import space.kscience.visionforge.setChild
|
import space.kscience.visionforge.setChild
|
||||||
|
|
||||||
|
|
||||||
public sealed class StlVision: SolidBase<StlVision>()
|
public sealed class StlSolid: SolidBase<StlSolid>()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("solid.stl.url")
|
@SerialName("solid.stl.url")
|
||||||
public class StlUrlVision(public val url: String) : StlVision()
|
public class StlUrlSolid(public val url: String) : StlSolid()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("solid.stl.binary")
|
@SerialName("solid.stl.binary")
|
||||||
public class StlBinaryVision(public val data: ByteArray) : StlVision()
|
public class StlBinarySolid(public val data: ByteArray) : StlSolid()
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public inline fun MutableVisionContainer<Solid>.stl(
|
public inline fun MutableVisionContainer<Solid>.stl(
|
||||||
url: String,
|
url: String,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
action: StlVision.() -> Unit = {},
|
action: StlSolid.() -> Unit = {},
|
||||||
): StlVision = StlUrlVision(url).apply(action).also { setChild(name, it) }
|
): StlSolid = StlUrlSolid(url).apply(action).also { setChild(name, it) }
|
@ -7,11 +7,13 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
|||||||
import space.kscience.dataforge.meta.descriptors.value
|
import space.kscience.dataforge.meta.descriptors.value
|
||||||
import space.kscience.dataforge.meta.double
|
import space.kscience.dataforge.meta.double
|
||||||
|
|
||||||
|
@Deprecated("Use separate axes object instead")
|
||||||
public class AxesScheme : Scheme() {
|
public class AxesScheme : Scheme() {
|
||||||
public var visible: Boolean by boolean(false)
|
public var visible: Boolean by boolean(false)
|
||||||
public var size: Double by double(AXIS_SIZE)
|
public var size: Double by double(AXIS_SIZE)
|
||||||
public var width: Double by double(AXIS_WIDTH)
|
public var width: Double by double(AXIS_WIDTH)
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
public companion object : SchemeSpec<AxesScheme>(::AxesScheme) {
|
public companion object : SchemeSpec<AxesScheme>(::AxesScheme) {
|
||||||
public const val AXIS_SIZE: Double = 1000.0
|
public const val AXIS_SIZE: Double = 1000.0
|
||||||
public const val AXIS_WIDTH: Double = 3.0
|
public const val AXIS_WIDTH: Double = 3.0
|
||||||
|
@ -59,6 +59,7 @@ public class CanvasSize : Scheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class Canvas3DOptions : Scheme() {
|
public class Canvas3DOptions : Scheme() {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
public var axes: AxesScheme by spec(AxesScheme)
|
public var axes: AxesScheme by spec(AxesScheme)
|
||||||
public var camera: CameraScheme by spec(CameraScheme)
|
public var camera: CameraScheme by spec(CameraScheme)
|
||||||
public var controls: ControlsScheme by spec(ControlsScheme)
|
public var controls: ControlsScheme by spec(ControlsScheme)
|
||||||
@ -75,6 +76,7 @@ public class Canvas3DOptions : Scheme() {
|
|||||||
public companion object : SchemeSpec<Canvas3DOptions>(::Canvas3DOptions) {
|
public companion object : SchemeSpec<Canvas3DOptions>(::Canvas3DOptions) {
|
||||||
override val descriptor: MetaDescriptor by lazy {
|
override val descriptor: MetaDescriptor by lazy {
|
||||||
MetaDescriptor {
|
MetaDescriptor {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
scheme(Canvas3DOptions::axes, AxesScheme)
|
scheme(Canvas3DOptions::axes, AxesScheme)
|
||||||
|
|
||||||
value(Canvas3DOptions::layers) {
|
value(Canvas3DOptions::layers) {
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package space.kscience.visionforge.solid.three
|
||||||
|
|
||||||
|
import space.kscience.visionforge.onPropertyChange
|
||||||
|
import space.kscience.visionforge.solid.AxesSolid
|
||||||
|
import three.helpers.AxesHelper
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
public object ThreeAxesFactory : ThreeFactory<AxesSolid> {
|
||||||
|
override val type: KClass<in AxesSolid> get() = AxesSolid::class
|
||||||
|
|
||||||
|
override suspend fun build(three: ThreePlugin, vision: AxesSolid, observe: Boolean): AxesHelper {
|
||||||
|
val res = AxesHelper(vision.size.toInt())
|
||||||
|
|
||||||
|
if (observe) {
|
||||||
|
vision.onPropertyChange(three.context) { propertyName ->
|
||||||
|
res.updateProperty(vision, propertyName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
@ -57,16 +57,6 @@ public class ThreeCanvas(
|
|||||||
axesObject.name = AXES_NAME
|
axesObject.name = AXES_NAME
|
||||||
add(axesObject)
|
add(axesObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
// //Set up light
|
|
||||||
// options.useProperty(Canvas3DOptions::light, this) { lightConfig ->
|
|
||||||
// //remove old light if present
|
|
||||||
// getObjectByName(LIGHT_NAME)?.let { remove(it) }
|
|
||||||
// //add new light
|
|
||||||
// val lightObject = buildLight(lightConfig)
|
|
||||||
// lightObject.name = LIGHT_NAME
|
|
||||||
// add(lightObject)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -110,7 +100,7 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force camera aspect ration and renderer size recalculation
|
* Force camera aspect ratio and renderer size recalculation
|
||||||
*/
|
*/
|
||||||
private fun updateSize() {
|
private fun updateSize() {
|
||||||
val width = element.clientWidth
|
val width = element.clientWidth
|
||||||
@ -202,7 +192,7 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve full name of the object relative to the global root
|
* Resolve the full name of the object relative to the global root
|
||||||
*/
|
*/
|
||||||
private fun Object3D.fullName(): Name {
|
private fun Object3D.fullName(): Name {
|
||||||
if (root == null) error("Can't resolve element name without the root")
|
if (root == null) error("Can't resolve element name without the root")
|
||||||
@ -213,7 +203,7 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//find first non-static parent in this object ancestry
|
//find the first non-static parent in this object ancestry
|
||||||
private tailrec fun Object3D.upTrace(): Object3D? = if (!name.startsWith("@")) this else parent?.upTrace()
|
private tailrec fun Object3D.upTrace(): Object3D? = if (!name.startsWith("@")) this else parent?.upTrace()
|
||||||
|
|
||||||
private fun pick(): Object3D? {
|
private fun pick(): Object3D? {
|
||||||
@ -267,6 +257,7 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
three.context.launch {
|
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
|
||||||
|
@ -37,7 +37,7 @@ public interface ThreeFactory<in T : Vision> {
|
|||||||
* Update position, rotation and visibility
|
* Update position, rotation and visibility
|
||||||
*/
|
*/
|
||||||
public fun Object3D.updatePosition(vision: Vision) {
|
public fun Object3D.updatePosition(vision: Vision) {
|
||||||
visible = vision.visible ?: true
|
// visible = vision.visible ?: true
|
||||||
if (vision is Solid) {
|
if (vision is Solid) {
|
||||||
position.set(vision.x, vision.y, vision.z)
|
position.set(vision.x, vision.y, vision.z)
|
||||||
|
|
||||||
|
@ -37,7 +37,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory
|
objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory
|
||||||
objectFactories[AmbientLightSource::class] = ThreeAmbientLightFactory
|
objectFactories[AmbientLightSource::class] = ThreeAmbientLightFactory
|
||||||
objectFactories[PointLightSource::class] = ThreePointLightFactory
|
objectFactories[PointLightSource::class] = ThreePointLightFactory
|
||||||
objectFactories[StlVision::class] = ThreeStlFactory
|
objectFactories[StlSolid::class] = ThreeStlFactory
|
||||||
|
objectFactories[AxesSolid::class] = ThreeAxesFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
@ -7,11 +7,13 @@ 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 suspend fun build(three: ThreePlugin, vision: PolyLine, observe: Boolean): Object3D {
|
override suspend fun build(
|
||||||
return if (vision.thickness == 1.0) {
|
three: ThreePlugin,
|
||||||
|
vision: PolyLine,
|
||||||
|
observe: Boolean,
|
||||||
|
): Object3D = if (vision.thickness == 1.0) {
|
||||||
ThreeLineFactory.build(three, vision, observe)
|
ThreeLineFactory.build(three, vision, observe)
|
||||||
} else {
|
} else {
|
||||||
ThreeMeshLineFactory.build(three, vision, observe)
|
ThreeMeshLineFactory.build(three, vision, observe)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@ -2,9 +2,9 @@ package space.kscience.visionforge.solid.three
|
|||||||
|
|
||||||
import org.khronos.webgl.ArrayBuffer
|
import org.khronos.webgl.ArrayBuffer
|
||||||
import org.khronos.webgl.Int8Array
|
import org.khronos.webgl.Int8Array
|
||||||
import space.kscience.visionforge.solid.StlBinaryVision
|
import space.kscience.visionforge.solid.StlBinarySolid
|
||||||
import space.kscience.visionforge.solid.StlUrlVision
|
import space.kscience.visionforge.solid.StlSolid
|
||||||
import space.kscience.visionforge.solid.StlVision
|
import space.kscience.visionforge.solid.StlUrlSolid
|
||||||
import three.core.BufferGeometry
|
import three.core.BufferGeometry
|
||||||
import three.external.loaders.STLLoader
|
import three.external.loaders.STLLoader
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
@ -13,15 +13,15 @@ import kotlin.coroutines.suspendCoroutine
|
|||||||
|
|
||||||
fun ArrayBuffer.toByteArray(): ByteArray = Int8Array(this).unsafeCast<ByteArray>()
|
fun ArrayBuffer.toByteArray(): ByteArray = Int8Array(this).unsafeCast<ByteArray>()
|
||||||
|
|
||||||
public object ThreeStlFactory : ThreeMeshFactory<StlVision>(StlVision::class) {
|
public object ThreeStlFactory : ThreeMeshFactory<StlSolid>(StlSolid::class) {
|
||||||
|
|
||||||
private val loader = STLLoader().apply {
|
private val loader = STLLoader().apply {
|
||||||
requestHeader = listOf("Access-Control-Allow-Origin: *")
|
requestHeader = listOf("Access-Control-Allow-Origin: *")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun buildGeometry(obj: StlVision): BufferGeometry = when (obj) {
|
override suspend fun buildGeometry(obj: StlSolid): BufferGeometry = when (obj) {
|
||||||
is StlBinaryVision -> loader.parse(obj.data)
|
is StlBinarySolid -> loader.parse(obj.data)
|
||||||
is StlUrlVision -> suspendCoroutine { continuation ->
|
is StlUrlSolid -> suspendCoroutine { continuation ->
|
||||||
loader.load(
|
loader.load(
|
||||||
url = obj.url,
|
url = obj.url,
|
||||||
onLoad = {
|
onLoad = {
|
||||||
|
Loading…
Reference in New Issue
Block a user