Refactor to ThreeJS v 130

This commit is contained in:
Alexander Nozik 2021-07-10 16:51:57 +03:00
parent 18b6ac2c37
commit 199cad1dc1
45 changed files with 304 additions and 521 deletions

View File

@ -11,7 +11,7 @@ import space.kscience.visionforge.solid.plus
class SC1( class SC1(
val name: String, val name: String,
val center: Point3D, val center: Point3D,
val xSize: Double = PIXEL_XY_SIZE, val ySize: Double = PIXEL_XY_SIZE, val zSize: Double = PIXEL_Z_SIZE val xSize: Float = PIXEL_XY_SIZE, val ySize: Float = PIXEL_XY_SIZE, val zSize: Float = PIXEL_Z_SIZE
) )
class SC16( class SC16(
@ -121,12 +121,12 @@ internal expect fun readMonitorConfig(): String
object Monitor { object Monitor {
const val GEOMETRY_TOLERANCE = 0.01 const val GEOMETRY_TOLERANCE = 0.01
const val PIXEL_XY_SIZE = 122.0 const val PIXEL_XY_SIZE = 122.0f
const val PIXEL_XY_SPACING = 123.2 const val PIXEL_XY_SPACING = 123.2f
const val PIXEL_Z_SIZE = 30.0 const val PIXEL_Z_SIZE = 30.0f
const val CENTRAL_LAYER_Z = 0.0 const val CENTRAL_LAYER_Z = 0.0f
const val UPPER_LAYER_Z = -166.0 const val UPPER_LAYER_Z = -166.0f
const val LOWER_LAYER_Z = 180.0 const val LOWER_LAYER_Z = 180.0f
/** /**
* Build map for the whole monitor * Build map for the whole monitor

View File

@ -17,19 +17,19 @@ import kotlin.random.Random
internal class SC1Aux(val sc: SC1, var efficiency: Double = 1.0) { internal class SC1Aux(val sc: SC1, var efficiency: Double = 1.0) {
// val layer: Layer = findLayer(center.z); // val layer: Layer = findLayer(center.z);
private val upLayer = private val upLayer =
findLayer(sc.center.z + sc.zSize / 2.0)//Layer("${name}_up", center.z + zSize / 2.0); findLayer(sc.center.z + sc.zSize / 2f)//Layer("${name}_up", center.z + zSize / 2.0);
private val bottomLayer = private val bottomLayer =
findLayer(sc.center.z - sc.zSize / 2.0)//Layer("${name}_bottom", center.z - zSize / 2.0); findLayer(sc.center.z - sc.zSize / 2f)//Layer("${name}_bottom", center.z - zSize / 2.0);
private val centralLayer = findLayer(sc.center.z) private val centralLayer = findLayer(sc.center.z)
private val center = Vector3D(sc.center.x, sc.center.y, sc.center.z) private val center = Vector3D(sc.center.x.toDouble(), sc.center.y.toDouble(), sc.center.z.toDouble())
private val sideLayers: Array<Plane> = arrayOf( private val sideLayers: Array<Plane> = arrayOf(
Plane(center.add(Vector3D(PIXEL_XY_SIZE / 2, 0.0, 0.0)), Vector3D(1.0, 0.0, 0.0), GEOMETRY_TOLERANCE), Plane(center.add(Vector3D(PIXEL_XY_SIZE / 2.0, 0.0, 0.0)), Vector3D(1.0, 0.0, 0.0), GEOMETRY_TOLERANCE),
Plane(center.add(Vector3D(-PIXEL_XY_SIZE / 2, 0.0, 0.0)), Vector3D(-1.0, 0.0, 0.0), GEOMETRY_TOLERANCE), Plane(center.add(Vector3D(-PIXEL_XY_SIZE / 2.0, 0.0, 0.0)), Vector3D(-1.0, 0.0, 0.0), GEOMETRY_TOLERANCE),
Plane(center.add(Vector3D(0.0, PIXEL_XY_SIZE / 2, 0.0)), Vector3D(0.0, 1.0, 0.0), GEOMETRY_TOLERANCE), Plane(center.add(Vector3D(0.0, PIXEL_XY_SIZE / 2.0, 0.0)), Vector3D(0.0, 1.0, 0.0), GEOMETRY_TOLERANCE),
Plane(center.add(Vector3D(0.0, -PIXEL_XY_SIZE / 2, 0.0)), Vector3D(0.0, -1.0, 0.0), GEOMETRY_TOLERANCE) Plane(center.add(Vector3D(0.0, -PIXEL_XY_SIZE / 2.0, 0.0)), Vector3D(0.0, -1.0, 0.0), GEOMETRY_TOLERANCE)
); )
//TODO add efficiency //TODO add efficiency
private fun containsPoint(x: Double, y: Double, z: Double, tolerance: Double = GEOMETRY_TOLERANCE): Boolean { private fun containsPoint(x: Double, y: Double, z: Double, tolerance: Double = GEOMETRY_TOLERANCE): Boolean {
@ -63,8 +63,8 @@ internal class SC1Aux(val sc: SC1, var efficiency: Double = 1.0) {
* The layer number from up to bottom * The layer number from up to bottom
*/ */
fun getLayerNumber(): Int { fun getLayerNumber(): Int {
return when (this.center.z) { return when (this.center.z.toFloat()) {
UPPER_LAYER_Z -> 1; UPPER_LAYER_Z -> 1
CENTRAL_LAYER_Z -> 2; CENTRAL_LAYER_Z -> 2;
LOWER_LAYER_Z -> 3; LOWER_LAYER_Z -> 3;
else -> throw RuntimeException("Unknown layer"); else -> throw RuntimeException("Unknown layer");

View File

@ -45,7 +45,7 @@ fun makeTrack(start: Vector3D, direction: Vector3D): Line {
fun makeTrack(x: Double, y: Double, theta: Double, phi: Double): Line { fun makeTrack(x: Double, y: Double, theta: Double, phi: Double): Line {
//TODO check angle definitions //TODO check angle definitions
return makeTrack( return makeTrack(
Vector3D(x, y, CENTRAL_LAYER_Z), Vector3D(x, y, CENTRAL_LAYER_Z.toDouble()),
Vector3D(phi, theta) Vector3D(phi, theta)
) )
} }

View File

@ -13,12 +13,12 @@ import ru.mipt.npm.muon.monitor.readResource
internal const val MINIMAL_TRACK_LENGTH = 10.0 internal const val MINIMAL_TRACK_LENGTH = 10.0
private val layerCache = HashMap<Double, Plane>() private val layerCache = HashMap<Float, Plane>()
fun findLayer(z: Double): Plane = layerCache.getOrPut(z) { fun findLayer(z: Float): Plane = layerCache.getOrPut(z) {
Plane( Plane(
Vector3D(0.0, 0.0, z), Vector3D(0.0, 0.0, 1.0), Vector3D(0.0, 0.0, z.toDouble()), Vector3D(0.0, 0.0, 1.0),
Monitor.GEOMETRY_TOLERANCE Monitor.GEOMETRY_TOLERANCE.toDouble()
) )
} }

View File

@ -28,8 +28,8 @@ interface TrackGenerator {
*/ */
class UniformTrackGenerator( class UniformTrackGenerator(
override val rnd: RandomGenerator, override val rnd: RandomGenerator,
val maxX: Double = 4 * PIXEL_XY_SIZE, val maxX: Float = 4 * PIXEL_XY_SIZE,
val maxY: Double = 4 * PIXEL_XY_SIZE val maxY: Float = 4 * PIXEL_XY_SIZE
) : ) :
TrackGenerator { TrackGenerator {
override fun generate(): Line { override fun generate(): Line {
@ -44,8 +44,8 @@ class UniformTrackGenerator(
class FixedAngleGenerator( class FixedAngleGenerator(
override val rnd: RandomGenerator, override val rnd: RandomGenerator,
val phi: Double, val theta: Double, val phi: Double, val theta: Double,
val maxX: Double = 4 * PIXEL_XY_SIZE, val maxX: Float = 4 * PIXEL_XY_SIZE,
val maxY: Double = 4 * PIXEL_XY_SIZE val maxY: Float = 4 * PIXEL_XY_SIZE
) : TrackGenerator { ) : TrackGenerator {
override fun generate(): Line { override fun generate(): Line {
val x = (1 - rnd.nextDouble() * 2.0) * maxX val x = (1 - rnd.nextDouble() * 2.0) * maxX
@ -60,8 +60,8 @@ class FixedAngleGenerator(
class Cos2TrackGenerator( class Cos2TrackGenerator(
override val rnd: RandomGenerator, override val rnd: RandomGenerator,
val power: Double = 2.0, val power: Double = 2.0,
val maxX: Double = 4 * PIXEL_XY_SIZE, val maxX: Float = 4 * PIXEL_XY_SIZE,
val maxY: Double = 4 * PIXEL_XY_SIZE val maxY: Float = 4 * PIXEL_XY_SIZE
) : ) :
TrackGenerator { TrackGenerator {
override fun generate(): Line { override fun generate(): Line {

View File

@ -3,6 +3,7 @@ package space.kscience.visionforge.examples
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.gdml.GdmlShowCase import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
fun main() { fun main() {
@ -10,7 +11,7 @@ fun main() {
plugin(Solids) plugin(Solids)
} }
context.makeVisionFile { context.makeVisionFile(resourceLocation = ResourceLocation.EMBED) {
vision("canvas") { GdmlShowCase.babyIaxo().toVision() } vision("canvas") { GdmlShowCase.babyIaxo().toVision() }
} }
} }

View File

@ -1,7 +1,7 @@
package space.kscience.visionforge.solid.demo package space.kscience.visionforge.solid.demo
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
import info.laht.threekt.geometries.BoxBufferGeometry import info.laht.threekt.geometries.BoxGeometry
import info.laht.threekt.objects.Mesh import info.laht.threekt.objects.Mesh
import space.kscience.dataforge.meta.int import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.number import space.kscience.dataforge.meta.number
@ -26,7 +26,7 @@ internal fun SolidGroup.varBox(
internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeVision() { internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeVision() {
override fun render(three: ThreePlugin): Object3D { override fun render(three: ThreePlugin): Object3D {
val geometry = BoxBufferGeometry(xSize, ySize, 1) val geometry = BoxGeometry(xSize, ySize, 1)
val material = ThreeMaterials.DEFAULT.clone() val material = ThreeMaterials.DEFAULT.clone()

View File

@ -4,9 +4,9 @@ plugins {
description = "Jupyter api artifact for GDML rendering" description = "Jupyter api artifact for GDML rendering"
kotlin{ kotlin {
explicitApi = null explicitApi = null
js{ js {
useCommonJs() useCommonJs()
browser { browser {
webpackTask { webpackTask {
@ -25,19 +25,17 @@ kotlin{
tasks.getByName<ProcessResources>("jvmProcessResources") { tasks.getByName<ProcessResources>("jvmProcessResources") {
dependsOn(jsBrowserDistribution) dependsOn(jsBrowserDistribution)
afterEvaluate { from(jsBrowserDistribution)
from(jsBrowserDistribution)
}
} }
} }
sourceSets{ sourceSets {
commonMain { commonMain {
dependencies { dependencies {
api(project(":visionforge-solid")) api(project(":visionforge-solid"))
} }
} }
jvmMain{ jvmMain {
dependencies { dependencies {
implementation(project(":visionforge-gdml")) implementation(project(":visionforge-gdml"))
} }
@ -52,10 +50,10 @@ kotlin{
} }
} }
kscience{ kscience {
useJupyter() useJupyter()
} }
readme{ readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
} }

View File

@ -16,8 +16,6 @@ pluginManagement {
} }
} }
//enableFeaturePreview("GRADLE_METADATA")
rootProject.name = "visionforge" rootProject.name = "visionforge"

View File

@ -58,6 +58,7 @@ public operator fun VisionGroup.iterator(): Iterator<Vision> = children.values.i
public val VisionGroup.isEmpty: Boolean get() = this.children.isEmpty() public val VisionGroup.isEmpty: Boolean get() = this.children.isEmpty()
public interface VisionContainerBuilder<in V : Vision> { public interface VisionContainerBuilder<in V : Vision> {
//TODO add documentation
public operator fun set(name: Name?, child: V?) public operator fun set(name: Name?, child: V?)
} }

View File

@ -4,6 +4,7 @@ import javafx.application.Platform
import javafx.beans.property.ObjectProperty import javafx.beans.property.ObjectProperty
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty
import javafx.scene.* import javafx.scene.*
import javafx.scene.layout.BorderPane
import javafx.scene.paint.Color import javafx.scene.paint.Color
import org.fxyz3d.scene.Axes import org.fxyz3d.scene.Axes
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
@ -11,31 +12,32 @@ import space.kscience.dataforge.context.ContextAware
import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import tornadofx.* import tornadofx.*
class FXCanvas3D( public class FXCanvas3D(
val plugin: FX3DPlugin, public val fx3d: FX3DPlugin,
val spec: Canvas3DOptions = Canvas3DOptions.empty(), public val options: Canvas3DOptions = Canvas3DOptions.empty(),
) : Fragment(), ContextAware { ) : Fragment(), ContextAware {
override val context: Context get() = plugin.context override val context: Context get() = fx3d.context
val world = Group().apply { public val world: Group = Group().apply {
//transforms.add(Rotate(180.0, Rotate.Z_AXIS)) //transforms.add(Rotate(180.0, Rotate.Z_AXIS))
} }
val axes = Axes().also { public val axes: Axes = Axes().also {
it.setHeight(spec.axes.size) it.setHeight(options.axes.size)
it.setRadius(spec.axes.width) it.setRadius(options.axes.width)
it.isVisible = spec.axes.visible it.isVisible = options.axes.visible
world.add(it) world.add(it)
} }
val light = AmbientLight() public val light: AmbientLight = AmbientLight()
private val camera = PerspectiveCamera().apply { private val camera = PerspectiveCamera().apply {
nearClip = spec.camera.nearClip nearClip = options.camera.nearClip
farClip = spec.camera.farClip farClip = options.camera.farClip
fieldOfView = spec.camera.fov.toDouble() fieldOfView = options.camera.fov.toDouble()
this.add(light)
add(light)
} }
private val canvas = SubScene( private val canvas = SubScene(
@ -49,19 +51,19 @@ class FXCanvas3D(
scene.camera = camera scene.camera = camera
} }
override val root = borderpane { override val root: BorderPane = borderpane {
center = canvas center = canvas
} }
val controls = camera.orbitControls(canvas, spec.camera).also { public val controls: OrbitControls = camera.orbitControls(canvas, options.camera).also {
world.add(it.centerMarker) world.add(it.centerMarker)
} }
val rootObjectProperty: ObjectProperty<Solid> = SimpleObjectProperty() public val rootObjectProperty: ObjectProperty<Solid> = SimpleObjectProperty()
var rootObject: Solid? by rootObjectProperty public var rootObject: Solid? by rootObjectProperty
private val rootNodeProperty = rootObjectProperty.objectBinding { private val rootNodeProperty = rootObjectProperty.objectBinding {
it?.let { plugin.buildNode(it) } it?.let { fx3d.buildNode(it) }
} }
init { init {
@ -79,7 +81,7 @@ class FXCanvas3D(
} }
} }
fun render(vision: Solid) { public fun render(vision: Solid) {
rootObject = vision rootObject = vision
} }
} }

View File

@ -11,7 +11,10 @@ object FXConvexFactory : FX3DFactory<Convex> {
override val type: KClass<in Convex> get() = Convex::class override val type: KClass<in Convex> get() = Convex::class
override fun invoke(obj: Convex, binding: VisualObjectFXBinding): Node { override fun invoke(obj: Convex, binding: VisualObjectFXBinding): Node {
val hull = HullUtil.hull(obj.points.map { Vector3d.xyz(it.x, it.y, it.z) }, PropertyStorage()) val hull = HullUtil.hull(
obj.points.map { Vector3d.xyz(it.x.toDouble(), it.y.toDouble(), it.z.toDouble()) },
PropertyStorage()
)
return hull.toNode() return hull.toNode()
} }

View File

@ -1,6 +1,7 @@
package space.kscience.visionforge.solid package space.kscience.visionforge.solid
import javafx.beans.InvalidationListener import javafx.beans.InvalidationListener
import javafx.beans.property.SimpleBooleanProperty
import javafx.beans.property.SimpleDoubleProperty import javafx.beans.property.SimpleDoubleProperty
import javafx.event.EventHandler import javafx.event.EventHandler
import javafx.geometry.Point3D import javafx.geometry.Point3D
@ -17,26 +18,26 @@ import kotlin.math.*
import space.kscience.visionforge.solid.specifications.Camera as CameraSpec import space.kscience.visionforge.solid.specifications.Camera as CameraSpec
class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec: CameraSpec) { public class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec: CameraSpec) {
val distanceProperty = SimpleDoubleProperty(spec.distance) public val distanceProperty: SimpleDoubleProperty = SimpleDoubleProperty(spec.distance)
var distance by distanceProperty public var distance: Double by distanceProperty
val azimuthProperty = SimpleDoubleProperty(spec.azimuth) public val azimuthProperty: SimpleDoubleProperty = SimpleDoubleProperty(spec.azimuth)
var azimuth by azimuthProperty public var azimuth: Double by azimuthProperty
val zenithProperty = SimpleDoubleProperty(PI / 2 - spec.latitude) public val zenithProperty: SimpleDoubleProperty = SimpleDoubleProperty(PI / 2 - spec.latitude)
var zenith by zenithProperty public var zenith: Double by zenithProperty
//
// public val latitudeProperty: DoubleBinding = zenithProperty.unaryMinus().plus(PI / 2)
// public val latitude by latitudeProperty
val latitudeProperty = zenithProperty.unaryMinus().plus(PI / 2) public val baseXProperty: SimpleDoubleProperty = SimpleDoubleProperty(0.0)
val latitude by latitudeProperty public var x: Double by baseXProperty
public val baseYProperty: SimpleDoubleProperty = SimpleDoubleProperty(0.0)
val baseXProperty = SimpleDoubleProperty(0.0) public var y: Double by baseYProperty
var x by baseXProperty public val baseZProperty: SimpleDoubleProperty = SimpleDoubleProperty(0.0)
val baseYProperty = SimpleDoubleProperty(0.0) public var z: Double by baseZProperty
var y by baseYProperty
val baseZProperty = SimpleDoubleProperty(0.0)
var z by baseZProperty
private val baseTranslate = Translate() private val baseTranslate = Translate()
@ -47,13 +48,15 @@ class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec:
// //
// val basePosition by basePositionProperty // val basePosition by basePositionProperty
val centerMarker by lazy { private val inProgressProperty = SimpleBooleanProperty(false)
public val centerMarker: Node by lazy {
Sphere(10.0).also { Sphere(10.0).also {
it.transforms.setAll(baseTranslate) it.transforms.setAll(baseTranslate)
it.visibleProperty().bind(inProgressProperty)
} }
} }
//private val center = Translate()
private val rx = Rotate(0.0, Rotate.X_AXIS) private val rx = Rotate(0.0, Rotate.X_AXIS)
@ -65,7 +68,7 @@ class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec:
init { init {
camera.transforms.setAll(rx, ry, rz, translate) camera.transforms.setAll(rx, ry, rz, baseTranslate, translate)
update() update()
val listener = InvalidationListener { val listener = InvalidationListener {
update() update()
@ -136,6 +139,7 @@ class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec:
mousePosY = me.sceneY mousePosY = me.sceneY
mouseOldX = me.sceneX mouseOldX = me.sceneX
mouseOldY = me.sceneY mouseOldY = me.sceneY
inProgressProperty.set(true)
} }
onMouseDragged = EventHandler<MouseEvent> { me -> onMouseDragged = EventHandler<MouseEvent> { me ->
@ -154,18 +158,23 @@ class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec:
if (me.isPrimaryButtonDown) { if (me.isPrimaryButtonDown) {
azimuth = (azimuth - mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED).coerceIn(0.0, 2 * PI) azimuth = (azimuth - mouseDeltaX * MOUSE_SPEED * modifier * ROTATION_SPEED).coerceIn(0.0, 2 * PI)
zenith = (zenith - mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED).coerceIn(0.0,PI) zenith = (zenith - mouseDeltaY * MOUSE_SPEED * modifier * ROTATION_SPEED).coerceIn(0.0, PI)
} else if (me.isSecondaryButtonDown) { } else if (me.isSecondaryButtonDown) {
x += MOUSE_SPEED * modifier * TRACK_SPEED * (mouseDeltaX * cos(azimuth) + mouseDeltaY * sin(azimuth)) x += MOUSE_SPEED * modifier * TRACK_SPEED * (mouseDeltaX * cos(azimuth) + mouseDeltaY * sin(azimuth))
z += MOUSE_SPEED * modifier * TRACK_SPEED * (-mouseDeltaX * sin(azimuth) + mouseDeltaY * cos(azimuth)) z += MOUSE_SPEED * modifier * TRACK_SPEED * (-mouseDeltaX * sin(azimuth) + mouseDeltaY * cos(azimuth))
} }
} }
onMouseReleased = EventHandler {
inProgressProperty.set(false)
}
onScroll = EventHandler<ScrollEvent> { event -> onScroll = EventHandler<ScrollEvent> { event ->
distance = max(1.0, distance - MOUSE_SPEED * event.deltaY * RESIZE_SPEED) distance = max(1.0, distance - MOUSE_SPEED * event.deltaY * RESIZE_SPEED)
} }
} }
companion object { public companion object {
private const val CONTROL_MULTIPLIER = 0.1 private const val CONTROL_MULTIPLIER = 0.1
private const val SHIFT_MULTIPLIER = 10.0 private const val SHIFT_MULTIPLIER = 10.0
private const val MOUSE_SPEED = 0.1 private const val MOUSE_SPEED = 0.1
@ -175,5 +184,5 @@ class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec:
} }
} }
fun Camera.orbitControls(canvas: SubScene, spec: CameraSpec) = public fun Camera.orbitControls(canvas: SubScene, spec: CameraSpec): OrbitControls =
OrbitControls(this, canvas, spec) OrbitControls(this, canvas, spec)

View File

@ -41,7 +41,7 @@ public class GdmlTransformer {
internal val styleCache = HashMap<Name, Meta>() internal val styleCache = HashMap<Name, Meta>()
public fun Solid.useStyle(name: String, builder: MetaBuilder.() -> Unit) { public fun Solid.registerAndUseStyle(name: String, builder: MetaBuilder.() -> Unit) {
styleCache.getOrPut(name.toName()) { styleCache.getOrPut(name.toName()) {
Meta(builder) Meta(builder)
} }
@ -49,7 +49,7 @@ public class GdmlTransformer {
} }
public fun Solid.transparent() { public fun Solid.transparent() {
useStyle("transparent") { registerAndUseStyle("transparent") {
SolidMaterial.MATERIAL_OPACITY_KEY put 0.3 SolidMaterial.MATERIAL_OPACITY_KEY put 0.3
"edges.enabled" put true "edges.enabled" put true
} }
@ -75,7 +75,7 @@ public class GdmlTransformer {
if (parent.physVolumes.isNotEmpty()) transparent() if (parent.physVolumes.isNotEmpty()) transparent()
useStyle(styleName) { registerAndUseStyle(styleName) {
val vfMaterial = SolidMaterial().apply { val vfMaterial = SolidMaterial().apply {
configurePaint(material, solid) configurePaint(material, solid)
} }
@ -125,7 +125,11 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) {
fun Solid.configureSolid(root: Gdml, parent: GdmlVolume, solid: GdmlSolid) { fun Solid.configureSolid(root: Gdml, parent: GdmlVolume, solid: GdmlSolid) {
val material = parent.materialref.resolve(root) ?: GdmlElement(parent.materialref.ref) val material = parent.materialref.resolve(root) ?: GdmlElement(parent.materialref.ref)
settings.run { configureSolid(parent, solid, material) } with(settings) {
with(this@configureSolid) {
configureSolid(parent, solid, material)
}
}
} }
private fun proxySolid(root: Gdml, group: SolidGroup, solid: GdmlSolid, name: String): SolidReferenceGroup { private fun proxySolid(root: Gdml, group: SolidGroup, solid: GdmlSolid, name: String): SolidReferenceGroup {

View File

@ -156,21 +156,21 @@ private fun Solid.position(): Point3D =
public var Solid.x: Number public var Solid.x: Number
get() = position?.x ?: 0f get() = position?.x ?: 0f
set(value) { set(value) {
position().x = value.toDouble() position().x = value.toFloat()
invalidateProperty(Solid.X_POSITION_KEY) invalidateProperty(Solid.X_POSITION_KEY)
} }
public var Solid.y: Number public var Solid.y: Number
get() = position?.y ?: 0f get() = position?.y ?: 0f
set(value) { set(value) {
position().y = value.toDouble() position().y = value.toFloat()
invalidateProperty(Solid.Y_POSITION_KEY) invalidateProperty(Solid.Y_POSITION_KEY)
} }
public var Solid.z: Number public var Solid.z: Number
get() = position?.z ?: 0f get() = position?.z ?: 0f
set(value) { set(value) {
position().z = value.toDouble() position().z = value.toFloat()
invalidateProperty(Solid.Z_POSITION_KEY) invalidateProperty(Solid.Z_POSITION_KEY)
} }
@ -180,21 +180,21 @@ private fun Solid.rotation(): Point3D =
public var Solid.rotationX: Number public var Solid.rotationX: Number
get() = rotation?.x ?: 0f get() = rotation?.x ?: 0f
set(value) { set(value) {
rotation().x = value.toDouble() rotation().x = value.toFloat()
invalidateProperty(Solid.X_ROTATION_KEY) invalidateProperty(Solid.X_ROTATION_KEY)
} }
public var Solid.rotationY: Number public var Solid.rotationY: Number
get() = rotation?.y ?: 0f get() = rotation?.y ?: 0f
set(value) { set(value) {
rotation().y = value.toDouble() rotation().y = value.toFloat()
invalidateProperty(Solid.Y_ROTATION_KEY) invalidateProperty(Solid.Y_ROTATION_KEY)
} }
public var Solid.rotationZ: Number public var Solid.rotationZ: Number
get() = rotation?.z ?: 0f get() = rotation?.z ?: 0f
set(value) { set(value) {
rotation().z = value.toDouble() rotation().z = value.toFloat()
invalidateProperty(Solid.Z_ROTATION_KEY) invalidateProperty(Solid.Z_ROTATION_KEY)
} }
@ -204,20 +204,20 @@ private fun Solid.scale(): Point3D =
public var Solid.scaleX: Number public var Solid.scaleX: Number
get() = scale?.x ?: 1f get() = scale?.x ?: 1f
set(value) { set(value) {
scale().x = value.toDouble() scale().x = value.toFloat()
invalidateProperty(Solid.X_SCALE_KEY) invalidateProperty(Solid.X_SCALE_KEY)
} }
public var Solid.scaleY: Number public var Solid.scaleY: Number
get() = scale?.y ?: 1f get() = scale?.y ?: 1f
set(value) { set(value) {
scale().y = value.toDouble() scale().y = value.toFloat()
invalidateProperty(Solid.Y_SCALE_KEY) invalidateProperty(Solid.Y_SCALE_KEY)
} }
public var Solid.scaleZ: Number public var Solid.scaleZ: Number
get() = scale?.z ?: 1f get() = scale?.z ?: 1f
set(value) { set(value) {
scale().z = value.toDouble() scale().z = value.toFloat()
invalidateProperty(Solid.Z_SCALE_KEY) invalidateProperty(Solid.Z_SCALE_KEY)
} }

View File

@ -3,29 +3,31 @@ package space.kscience.visionforge.solid
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MetaBuilder import space.kscience.dataforge.meta.MetaBuilder
import space.kscience.dataforge.meta.double import space.kscience.dataforge.meta.float
import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.get
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.pow
import kotlin.math.sqrt
public const val PI2: Float = 2 * PI.toFloat() public const val PI2: Float = 2 * PI.toFloat()
@Serializable @Serializable
public data class Point2D(public var x: Double, public var y: Double) public data class Point2D(public var x: Float, public var y: Float)
public fun Point2D(x: Number, y: Number): Point2D = Point2D(x.toDouble(), y.toDouble()) public fun Point2D(x: Number, y: Number): Point2D = Point2D(x.toFloat(), y.toFloat())
public fun Point2D.toMeta(): Meta = Meta { public fun Point2D.toMeta(): Meta = Meta {
Solid.X_KEY put x Solid.X_KEY put x
Solid.Y_KEY put y Solid.Y_KEY put y
} }
internal fun Meta.point2D(): Point2D = Point2D(this["x"].double ?: 0.0, this["y"].double ?: 0.0) internal fun Meta.point2D(): Point2D = Point2D(this["x"].float ?: 0f, this["y"].float ?: 0f)
@Serializable @Serializable
public data class Point3D( public data class Point3D(
public var x: Double, public var x: Float,
public var y: Double, public var y: Float,
public var z: Double, public var z: Float,
) { ) {
public companion object { public companion object {
public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0) public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0)
@ -33,7 +35,7 @@ public data class Point3D(
} }
} }
public fun Point3D(x: Number, y: Number, z: Number): Point3D = Point3D(x.toDouble(), y.toDouble(), z.toDouble()) public fun Point3D(x: Number, y: Number, z: Number): Point3D = Point3D(x.toFloat(), y.toFloat(), z.toFloat())
public operator fun Point3D.plus(other: Point3D): Point3D = Point3D( public operator fun Point3D.plus(other: Point3D): Point3D = Point3D(
this.x + other.x, this.x + other.x,
@ -41,7 +43,32 @@ public operator fun Point3D.plus(other: Point3D): Point3D = Point3D(
this.z + other.z this.z + other.z
) )
internal fun Meta.point3D() = Point3D(this["x"].double ?: 0.0, this["y"].double ?: 0.0, this["y"].double ?: 0.0) public operator fun Point3D.minus(other: Point3D): Point3D = Point3D(
this.x - other.x,
this.y - other.y,
this.z - other.z
)
public operator fun Point3D.unaryMinus(): Point3D = Point3D(
-x,
-y,
-z
)
public infix fun Point3D.cross(other: Point3D): Point3D = Point3D(
y * other.z - z * other.y,
z * other.x - x * other.z,
x * other.y - y * other.x
)
public fun Point3D.normalizeInPlace(){
val norm = sqrt(x.pow(2) + y.pow(2) + z.pow(2))
x /= norm
y /= norm
z /= norm
}
internal fun Meta.point3D() = Point3D(this["x"].float ?: 0.0, this["y"].float ?: 0.0, this["y"].float ?: 0.0)
public fun Point3D.toMeta(): MetaBuilder = Meta { public fun Point3D.toMeta(): MetaBuilder = Meta {
Solid.X_KEY put x Solid.X_KEY put x

View File

@ -4,6 +4,6 @@ plugins {
dependencies { dependencies {
api(project(":visionforge-solid")) api(project(":visionforge-solid"))
implementation(npm("three", "0.124.0")) implementation(npm("three", "0.130.1"))
implementation(npm("three-csg-ts", "2.2.2")) implementation(npm("three-csg-ts", "3.1.4"))
} }

View File

@ -44,6 +44,7 @@ abstract external class BufferAttribute protected constructor(
* Default is 0. Position at whcih to start update. * Default is 0. Position at whcih to start update.
*/ */
var offset: Int var offset: Int
/** /**
* Default is -1, which means don't use update ranges. * Default is -1, which means don't use update ranges.
@ -56,16 +57,19 @@ abstract external class BufferAttribute protected constructor(
* UUID of this object instance. This gets automatically assigned and this shouldn't be edited. * UUID of this object instance. This gets automatically assigned and this shouldn't be edited.
*/ */
val uuid: String val uuid: String
/** /**
* Optional name for this attribute instance. Default is an empty string. * Optional name for this attribute instance. Default is an empty string.
*/ */
var name: String var name: String
var array: dynamic var array: dynamic
/** /**
* The length of vectors that are being stored in the array. * The length of vectors that are being stored in the array.
*/ */
val itemSize: Int val itemSize: Int
/** /**
* Stores the array's length divided by the itemSize. * Stores the array's length divided by the itemSize.
* *
@ -73,6 +77,7 @@ abstract external class BufferAttribute protected constructor(
* then this will count the number of such vectors stored. * then this will count the number of such vectors stored.
*/ */
val count: Int val count: Int
/** /**
* Indicates how the underlying data in the buffer maps to the values in the GLSL shader code. See the constructor above for details. * Indicates how the underlying data in the buffer maps to the values in the GLSL shader code. See the constructor above for details.
*/ */
@ -86,6 +91,7 @@ abstract external class BufferAttribute protected constructor(
* This corresponds to the gl.DYNAMIC_DRAW flag. * This corresponds to the gl.DYNAMIC_DRAW flag.
*/ */
var dynamic: Boolean var dynamic: Boolean
/** /**
* This can be used to only update some components of stored vectors ( * This can be used to only update some components of stored vectors (
* for example, just the component related to color). * for example, just the component related to color).
@ -99,8 +105,16 @@ abstract external class BufferAttribute protected constructor(
*/ */
var needsUpdate: Boolean var needsUpdate: Boolean
/**
* A callback function that is executed after the Renderer has transferred the attribute array data to the GPU.
*/
var onUploadCallback: () -> Unit var onUploadCallback: () -> Unit
/**
* Sets the value of the [onUploadCallback] property.
*/
fun onUpload(callback: () -> Unit)
/** /**
* A version number, incremented every time the needsUpdate property is set to true. * A version number, incremented every time the needsUpdate property is set to true.
*/ */
@ -119,6 +133,7 @@ abstract external class BufferAttribute protected constructor(
fun getW(index: Int): Number fun getW(index: Int): Number
fun copy(source: BufferAttribute): BufferAttribute fun copy(source: BufferAttribute): BufferAttribute
/** /**
* Copy a vector from bufferAttribute[index2] to array[index1]. * Copy a vector from bufferAttribute[index2] to array[index1].
*/ */
@ -205,3 +220,22 @@ abstract external class BufferAttribute protected constructor(
*/ */
fun setXYZW(index: Int, x: Number, y: Number, z: Number, w: Number) fun setXYZW(index: Int, x: Number, y: Number, z: Number, w: Number)
} }
external class Float32BufferAttribute(
array: FloatArray,
itemSize: Int,
normalized: Boolean = definedExternally
) : BufferAttribute
external class Int32BufferAttribute(
array: IntArray,
itemSize: Int,
normalized: Boolean = definedExternally
) : BufferAttribute
external class Int16BufferAttribute(
array: ShortArray,
itemSize: Int,
normalized: Boolean = definedExternally
) : BufferAttribute

View File

@ -85,14 +85,14 @@ open external class BufferGeometry {
fun clearGroups() fun clearGroups()
fun addGroup(start: Int, count: Int, materialIndex: Int = definedExternally) fun addGroup(start: Int, count: Int, materialIndex: Int = definedExternally)
fun addAttribute(name: String, attribute: BufferAttribute) fun setAttribute(name: String, attribute: BufferAttribute)
fun getAttribute(name: String): BufferAttribute fun getAttribute(name: String): BufferAttribute
fun removeAttribute(name: String): BufferGeometry fun deleteAttribute(name: String): BufferGeometry
fun setIndex(index: BufferAttribute) fun setIndex(index: BufferAttribute)
fun setIndex(index: Array<Short>)
fun setDrawRange(start: Int, count: Int) fun setDrawRange(start: Int, count: Int)
fun fromGeometry(geometry: Geometry)
fun setFromObject(`object`: Object3D): BufferGeometry fun setFromObject(`object`: Object3D): BufferGeometry
fun updateFromObject(`object`: Object3D): BufferGeometry fun updateFromObject(`object`: Object3D): BufferGeometry
fun setFromPoints(points: Array<Vector3>): BufferGeometry fun setFromPoints(points: Array<Vector3>): BufferGeometry

View File

@ -1,48 +0,0 @@
/*
* The MIT License
*
* Copyright 2017-2018 Lars Ivar Hatledal
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
@file:JsModule("three")
@file:JsNonModule
package info.laht.threekt.core
import info.laht.threekt.math.Box3
import info.laht.threekt.math.Sphere
external class DirectGeometry {
var verticesNeedUpdate: Boolean
var normalsNeedUpdate: Boolean
var colorsNeedUpdate: Boolean
var uvsNeedUpdate: Boolean
var groupsNeedUpdate: Boolean
fun computeBoundingBox(): Box3
fun computeBoundingSphere(): Sphere
fun dispose()
fun fromGeometry(geometry: Geometry)
}

View File

@ -1,109 +0,0 @@
/*
* The MIT License
*
* Copyright 2017-2018 Lars Ivar Hatledal
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
@file:JsModule("three")
@file:JsNonModule
package info.laht.threekt.core
import info.laht.threekt.math.*
import info.laht.threekt.objects.Mesh
external interface MorphTarget {
val name: String
val vertices: Array<Vector3>
}
external interface MorphNormal {
val name: String
val normals: Array<Vector3>
}
open external class Geometry {
val id: Int
var vertices: Array<Vector3>
var colors: Array<Color>
var faces: Array<Face3>
var faceVertexUvs: Array<Array<Vector2>>
var morphTargets: Array<MorphTarget>
var morphNormals: Array<MorphNormal>
var skinWeights: Array<Vector4>
var skinIndices: Array<Vector4>
var lineDistances: List<Double>
var boundingBox: Box3?
var boundingSphere: Sphere?
// update flags
var elementsNeedUpdate: Boolean
var verticesNeedUpdate: Boolean
var uvsNeedUpdate: Boolean
var normalsNeedUpdate: Boolean
var colorsNeedUpdate: Boolean
var lineDistancesNeedUpdate: Boolean
var groupsNeedUpdate: Boolean
fun applyMatrix4(matrix: Matrix4): Geometry
fun rotateX(angle: Number): Geometry
fun rotateY(angle: Number): Geometry
fun rotateZ(angle: Number): Geometry
fun translate(x: Number, y: Number, z: Number): Geometry
fun scale(x: Number, y: Number, z: Number): Geometry
fun lookAt(vector: Vector3): Geometry
fun fromBufferGeometry(geometry: BufferGeometry): Geometry
fun addFace(a: Int, b: Int, c: Int, materialIndexOffset: Int = definedExternally)
fun center(): Vector3
fun normalize(): Geometry
fun computeFaceNormals()
fun computeVertexNormals(areaWeighted: Boolean = definedExternally)
fun computeFlatVertexNormals()
fun computeMorphNormals()
fun computeLineDistances()
fun computeBoundingBox()
fun computeBoundingSphere()
fun merge(geometry: Geometry, matrix: Matrix4 = definedExternally, materialIndexOffset: Int = definedExternally)
fun mergeMesh(mesh: Mesh)
fun mergeVertices()
fun setFromPoint(points: Array<Vector3>): Geometry
fun sortFacesByMaterialIndex()
fun toJSON(): Any
open fun clone(): Geometry
fun copy(geometry: Geometry): Geometry
fun dispose()
}

View File

@ -4,7 +4,6 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
external class BoxGeometry( external class BoxGeometry(
@ -14,14 +13,4 @@ external class BoxGeometry(
widthSegments: Int = definedExternally, widthSegments: Int = definedExternally,
heightSegments: Int = definedExternally, heightSegments: Int = definedExternally,
depthSegments: Int = definedExternally depthSegments: Int = definedExternally
) : Geometry
external class BoxBufferGeometry(
width: Number,
height: Number,
depth: Number,
widthSegments: Int = definedExternally,
heightSegments: Int = definedExternally,
depthSegments: Int = definedExternally
) : BufferGeometry ) : BufferGeometry

View File

@ -4,7 +4,7 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
external class ConeGeometry( external class ConeGeometry(
radius: Number = definedExternally, radius: Number = definedExternally,
@ -14,14 +14,4 @@ external class ConeGeometry(
openEnded: Boolean = definedExternally, openEnded: Boolean = definedExternally,
thetaStart: Boolean = definedExternally, thetaStart: Boolean = definedExternally,
thetaLength: Boolean = definedExternally thetaLength: Boolean = definedExternally
) : Geometry
external class ConeBufferGeometry(
radius: Number = definedExternally,
height: Number = definedExternally,
radialSegments: Int = definedExternally,
heightSegments: Int = definedExternally,
openEnded: Boolean = definedExternally,
thetaStart: Boolean = definedExternally,
thetaLength: Boolean = definedExternally
) : BufferGeometry ) : BufferGeometry

View File

@ -4,7 +4,6 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
external class CylinderGeometry( external class CylinderGeometry(
radiusTop: Number, radiusTop: Number,
@ -15,15 +14,4 @@ external class CylinderGeometry(
openEnded: Boolean = definedExternally, openEnded: Boolean = definedExternally,
thetaStart: Number = definedExternally, thetaStart: Number = definedExternally,
thetaLength: Number = definedExternally thetaLength: Number = definedExternally
) : Geometry
external class CylinderBufferGeometry(
radiusTop: Number,
radiusBottom: Number,
height: Number,
radialSegments: Int = definedExternally,
heightSegments: Int = definedExternally,
openEnded: Boolean = definedExternally,
thetaStart: Number = definedExternally,
thetaLength: Number = definedExternally
) : BufferGeometry ) : BufferGeometry

View File

@ -4,8 +4,5 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
external class EdgesGeometry(geometry: Geometry, thresholdAngle: Int = definedExternally) : BufferGeometry { public external class EdgesGeometry(geometry: BufferGeometry, thresholdAngle: Int = definedExternally) : BufferGeometry
constructor(geometry: BufferGeometry, thresholdAngle: Int = definedExternally)
}

View File

@ -11,7 +11,6 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
import info.laht.threekt.extras.core.Shape import info.laht.threekt.extras.core.Shape
import info.laht.threekt.math.Vector2 import info.laht.threekt.math.Vector2
@ -78,15 +77,3 @@ external open class ExtrudeBufferGeometry : BufferGeometry {
var WorldUVGenerator: UVGenerator var WorldUVGenerator: UVGenerator
} }
} }
external open class ExtrudeGeometry : Geometry {
constructor(shapes: Shape, options: ExtrudeGeometryOptions?)
constructor(shapes: Array<Shape>, options: ExtrudeGeometryOptions?)
open fun addShapeList(shapes: Array<Shape>, options: Any? = definedExternally)
open fun addShape(shape: Shape, options: Any? = definedExternally)
companion object {
var WorldUVGenerator: UVGenerator
}
}

View File

@ -4,7 +4,6 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
external class PlaneGeometry( external class PlaneGeometry(
@ -13,13 +12,4 @@ external class PlaneGeometry(
widthSegments: Int = definedExternally, widthSegments: Int = definedExternally,
heightSegments: Int = definedExternally heightSegments: Int = definedExternally
) : Geometry
external class PlaneBufferGeometry(
width: Number,
height: Number,
widthSegments: Int = definedExternally,
heightSegments: Int = definedExternally
) : BufferGeometry ) : BufferGeometry

View File

@ -4,7 +4,6 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
external class SphereGeometry( external class SphereGeometry(
radius: Number, radius: Number,
@ -14,14 +13,4 @@ external class SphereGeometry(
phiLength: Number = definedExternally, phiLength: Number = definedExternally,
thetaStart: Number = definedExternally, thetaStart: Number = definedExternally,
thetaLength: Number = definedExternally thetaLength: Number = definedExternally
) : Geometry
external class SphereBufferGeometry(
radius: Number,
widthSegments: Int = definedExternally,
heightSegments: Int = definedExternally,
phiStart: Number = definedExternally,
phiLength: Number = definedExternally,
thetaStart: Number = definedExternally,
thetaLength: Number = definedExternally
) : BufferGeometry ) : BufferGeometry

View File

@ -34,10 +34,7 @@ external interface TextGeometryParameters {
set(value) = definedExternally set(value) = definedExternally
} }
external class TextBufferGeometry(text: String, parameters: TextGeometryParameters? = definedExternally) : ExtrudeBufferGeometry { external class TextBufferGeometry(text: String, parameters: TextGeometryParameters? = definedExternally) :
val parameters: TextGeometryParameters ExtrudeBufferGeometry {
}
external class TextGeometry(text: String, parameters: TextGeometryParameters? = definedExternally) : ExtrudeGeometry {
val parameters: TextGeometryParameters val parameters: TextGeometryParameters
} }

View File

@ -4,7 +4,7 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
external class TorusGeometry( external class TorusGeometry(
radius: Number = definedExternally, radius: Number = definedExternally,
@ -12,12 +12,4 @@ external class TorusGeometry(
radialSegments: Int = definedExternally, radialSegments: Int = definedExternally,
tubularSegments: Int = definedExternally, tubularSegments: Int = definedExternally,
arc: Number = definedExternally arc: Number = definedExternally
) : Geometry
external class TorusBufferGeometry(
radius: Number = definedExternally,
tube: Number = definedExternally,
radialSegments: Int = definedExternally,
tubularSegments: Int = definedExternally,
arc: Number = definedExternally
) : BufferGeometry ) : BufferGeometry

View File

@ -1,10 +1,10 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
import info.laht.threekt.extras.core.Curve import info.laht.threekt.extras.core.Curve
import info.laht.threekt.math.Vector3 import info.laht.threekt.math.Vector3
/** /**
* Creates a tube that extrudes along a 3d curve. * Creates a tube that extrudes along a 3d curve.
*/ */
@ -16,25 +16,6 @@ external class TubeGeometry(
radiusSegments: Int = definedExternally, radiusSegments: Int = definedExternally,
closed: Boolean = definedExternally closed: Boolean = definedExternally
) : Geometry {
var tangents: Array<Vector3>
var normals: Array<Vector3>
var binormals: Array<Vector3>
}
/**
* Creates a tube that extrudes along a 3d curve.
*/
external class TubeBufferGeometry(
path: Curve<Vector3>,
tubularSegments: Int = definedExternally,
radius: Number = definedExternally,
radiusSegments: Int = definedExternally,
closed: Boolean = definedExternally
) : BufferGeometry { ) : BufferGeometry {
val parameters: dynamic val parameters: dynamic

View File

@ -4,14 +4,8 @@
package info.laht.threekt.geometries package info.laht.threekt.geometries
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
/** /**
* This can be used as a helper object to view a Geometry object as a wireframe. * This can be used as a helper object to view a Geometry object as a wireframe.
*/ */
external class WireframeGeometry : BufferGeometry { external class WireframeGeometry(geometry: BufferGeometry) : BufferGeometry
constructor(geometry: Geometry)
constructor(geometry: BufferGeometry)
}

View File

@ -28,12 +28,10 @@
package info.laht.threekt.objects package info.laht.threekt.objects
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Geometry
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
import info.laht.threekt.materials.Material import info.laht.threekt.materials.Material
open external class LineSegments(geometry: BufferGeometry, material: Material) : Object3D { open external class LineSegments(geometry: BufferGeometry, material: Material) : Object3D {
constructor(geometry: Geometry, material: Material)
var geometry: BufferGeometry var geometry: BufferGeometry
var material: Material var material: Material

View File

@ -27,14 +27,14 @@
package info.laht.threekt.objects package info.laht.threekt.objects
import info.laht.threekt.core.* import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Intersect
import info.laht.threekt.core.Object3D
import info.laht.threekt.core.Raycaster
import info.laht.threekt.materials.Material import info.laht.threekt.materials.Material
open external class Mesh : Object3D { open external class Mesh(geometry: BufferGeometry?, material: Material?) : Object3D {
constructor(geometry: Geometry?, material: Material?)
constructor(geometry: BufferGeometry?, material: Material?)
var geometry: dynamic var geometry: dynamic
var material: Material var material: Material

View File

@ -30,9 +30,6 @@ public abstract class MeshThreeFactory<in T : Solid>(
override fun invoke(three: ThreePlugin, obj: T): Mesh { override fun invoke(three: ThreePlugin, obj: T): Mesh {
val geometry = buildGeometry(obj) val geometry = buildGeometry(obj)
//JS sometimes tries to pass Geometry as BufferGeometry
@Suppress("USELESS_IS_CHECK") if (geometry !is BufferGeometry) error("BufferGeometry expected")
//val meshMeta: Meta = obj.properties[Material3D.MATERIAL_KEY]?.node ?: Meta.empty //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 {

View File

@ -1,12 +1,12 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import info.laht.threekt.geometries.BoxBufferGeometry import info.laht.threekt.geometries.BoxGeometry
import space.kscience.visionforge.solid.Box import space.kscience.visionforge.solid.Box
import space.kscience.visionforge.solid.detail import space.kscience.visionforge.solid.detail
public object ThreeBoxFactory : MeshThreeFactory<Box>(Box::class) { public object ThreeBoxFactory : MeshThreeFactory<Box>(Box::class) {
override fun buildGeometry(obj: Box): BoxBufferGeometry = override fun buildGeometry(obj: Box): BoxGeometry =
obj.detail?.let { detail -> obj.detail?.let { detail ->
BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize, detail, detail, detail) BoxGeometry(obj.xSize, obj.ySize, obj.zSize, detail, detail, detail)
} ?: BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize) } ?: BoxGeometry(obj.xSize, obj.ySize, obj.zSize)
} }

View File

@ -2,7 +2,7 @@ package space.kscience.visionforge.solid.three
import info.laht.threekt.DoubleSide import info.laht.threekt.DoubleSide
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
import info.laht.threekt.geometries.PlaneBufferGeometry import info.laht.threekt.geometries.PlaneGeometry
import info.laht.threekt.materials.MeshBasicMaterial import info.laht.threekt.materials.MeshBasicMaterial
import info.laht.threekt.objects.Mesh import info.laht.threekt.objects.Mesh
import info.laht.threekt.textures.Texture import info.laht.threekt.textures.Texture
@ -46,7 +46,7 @@ public object ThreeCanvasLabelFactory : ThreeFactory<SolidLabel> {
} }
val mesh = Mesh( val mesh = Mesh(
PlaneBufferGeometry(canvas.width, canvas.height), PlaneGeometry(canvas.width, canvas.height),
material material
) )

View File

@ -2,6 +2,7 @@ package space.kscience.visionforge.solid.three
import CSG import CSG
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.math.Matrix4
import info.laht.threekt.objects.Mesh import info.laht.threekt.objects.Mesh
import space.kscience.visionforge.solid.Composite import space.kscience.visionforge.solid.Composite
import space.kscience.visionforge.solid.CompositeType import space.kscience.visionforge.solid.CompositeType
@ -23,7 +24,7 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : MeshThreeFac
CompositeType.INTERSECT -> firstCSG.intersect(secondCSG) CompositeType.INTERSECT -> firstCSG.intersect(secondCSG)
CompositeType.SUBTRACT -> firstCSG.subtract(secondCSG) CompositeType.SUBTRACT -> firstCSG.subtract(secondCSG)
} }
return resultCSG.toGeometry().toBufferGeometry() return resultCSG.toGeometry(Matrix4())
} }
} }

View File

@ -1,7 +1,7 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.geometries.CylinderBufferGeometry import info.laht.threekt.geometries.CylinderGeometry
import space.kscience.visionforge.solid.ConeSegment import space.kscience.visionforge.solid.ConeSegment
import space.kscience.visionforge.solid.detail import space.kscience.visionforge.solid.detail
import kotlin.math.PI import kotlin.math.PI
@ -11,7 +11,7 @@ public object ThreeConeFactory : MeshThreeFactory<ConeSegment>(ConeSegment::clas
override fun buildGeometry(obj: ConeSegment): BufferGeometry { override fun buildGeometry(obj: ConeSegment): BufferGeometry {
val cylinder = obj.detail?.let { val cylinder = obj.detail?.let {
val segments = it.toDouble().pow(0.5).toInt() val segments = it.toDouble().pow(0.5).toInt()
CylinderBufferGeometry( CylinderGeometry(
radiusTop = obj.topRadius, radiusTop = obj.topRadius,
radiusBottom = obj.bottomRadius, radiusBottom = obj.bottomRadius,
height = obj.height, height = obj.height,
@ -21,7 +21,7 @@ public object ThreeConeFactory : MeshThreeFactory<ConeSegment>(ConeSegment::clas
thetaStart = obj.startAngle, thetaStart = obj.startAngle,
thetaLength = obj.angle thetaLength = obj.angle
) )
} ?: CylinderBufferGeometry( } ?: CylinderGeometry(
radiusTop = obj.topRadius, radiusTop = obj.topRadius,
radiusBottom = obj.bottomRadius, radiusBottom = obj.bottomRadius,
height = obj.height, height = obj.height,

View File

@ -63,9 +63,7 @@ public fun Object3D.updateProperty(source: Vision, propertyName: Name) {
* Generic factory for elements which provide inside geometry builder * Generic factory for elements which provide inside geometry builder
*/ */
public object ThreeShapeFactory : MeshThreeFactory<GeometrySolid>(GeometrySolid::class) { public object ThreeShapeFactory : MeshThreeFactory<GeometrySolid>(GeometrySolid::class) {
override fun buildGeometry(obj: GeometrySolid): BufferGeometry { override fun buildGeometry(obj: GeometrySolid): BufferGeometry = ThreeGeometryBuilder().apply {
return obj.run { obj.toGeometry(this)
ThreeGeometryBuilder().apply { toGeometry(this) }.build() }.build()
}
}
} }

View File

@ -1,52 +1,61 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Face3 import info.laht.threekt.core.Float32BufferAttribute
import info.laht.threekt.core.Geometry
import info.laht.threekt.math.Vector3 import info.laht.threekt.math.Vector3
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.int
import space.kscience.visionforge.solid.GeometryBuilder import space.kscience.visionforge.solid.GeometryBuilder
import space.kscience.visionforge.solid.Point3D import space.kscience.visionforge.solid.Point3D
import space.kscience.visionforge.solid.cross
import space.kscience.visionforge.solid.minus
internal fun Point3D.toVector() = Vector3(x, y, z) internal fun Point3D.toVector() = Vector3(x, y, z)
internal fun <T> MutableList<T>.add(f1: T, f2: T, f3: T) {
add(f1)
add(f2)
add(f3)
}
/** /**
* An implementation of geometry builder for Three.js [BufferGeometry] * An implementation of geometry builder for Three.js [BufferGeometry]
*/ */
public class ThreeGeometryBuilder : GeometryBuilder<BufferGeometry> { public class ThreeGeometryBuilder : GeometryBuilder<BufferGeometry> {
private val vertices = ArrayList<Vector3>() private val indices = ArrayList<Short>()
private val faces = ArrayList<Face3>() private val positions = ArrayList<Float>()
private val normals = ArrayList<Float>()
private val colors = ArrayList<Float>()
private val vertexCache = HashMap<Point3D, Int>() private val vertexCache = HashMap<Point3D, Short>()
private var counter: Short = -1
private fun append(vertex: Point3D): Int { private fun indexOf(vertex: Point3D, normal: Point3D): Short = vertexCache.getOrPut(vertex) {
val index = vertexCache[vertex] ?: -1//vertices.indexOf(vertex) //add vertex and update cache if needed
return if (index > 0) { positions.add(vertex.x, vertex.y, vertex.z)
index normals.add(normal.x, vertex.y, vertex.z)
} else { colors.add(1f, 1f, 1f)
vertices.add(vertex.toVector()) counter++
vertexCache[vertex] = vertices.size - 1 counter
vertices.size - 1
}
} }
override fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D?, meta: Meta) { override fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D?, meta: Meta) {
val face = Face3(append(vertex1), append(vertex2), append(vertex3), normal?.toVector() ?: Vector3(0, 0, 0)) val actualNormal: Point3D = normal ?: (vertex3 - vertex2) cross (vertex1 - vertex2)
meta["materialIndex"].int?.let { face.materialIndex = it } indices.add(
meta["color"]?.getColor()?.let { face.color = it } indexOf(vertex1, actualNormal),
faces.add(face) indexOf(vertex2, actualNormal),
indexOf(vertex3, actualNormal)
)
} }
override fun build(): BufferGeometry { override fun build(): BufferGeometry = BufferGeometry().apply {
return Geometry().apply { //setIndex(Int16BufferAttribute(indices.toShortArray(), 1))
vertices = this@ThreeGeometryBuilder.vertices.toTypedArray() setIndex(indices.toTypedArray())
faces = this@ThreeGeometryBuilder.faces.toTypedArray() setAttribute("position", Float32BufferAttribute(positions.toFloatArray(), 3))
computeBoundingSphere() setAttribute("normal", Float32BufferAttribute(normals.toFloatArray(), 3))
computeFaceNormals() //setAttribute("color", Float32BufferAttribute(colors.toFloatArray(), 3))
}.toBufferGeometry()
computeBoundingSphere()
} }
} }

View File

@ -1,6 +1,6 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import info.laht.threekt.core.Geometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
import info.laht.threekt.math.Color import info.laht.threekt.math.Color
import info.laht.threekt.objects.LineSegments import info.laht.threekt.objects.LineSegments
@ -16,8 +16,8 @@ public object ThreeLineFactory : ThreeFactory<PolyLine> {
override val type: KClass<PolyLine> get() = PolyLine::class override val type: KClass<PolyLine> get() = PolyLine::class
override fun invoke(three: ThreePlugin, obj: PolyLine): Object3D { override fun invoke(three: ThreePlugin, obj: PolyLine): Object3D {
val geometry = Geometry().apply { val geometry = BufferGeometry().apply {
vertices = Array(obj.points.size) { obj.points[it].toVector() } setFromPoints(Array(obj.points.size) { obj.points[it].toVector() })
} }
val material = ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.EDGES_MATERIAL_KEY).node, true) val material = ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.EDGES_MATERIAL_KEY).node, true)

View File

@ -1,14 +1,14 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.geometries.SphereBufferGeometry import info.laht.threekt.geometries.SphereGeometry
import space.kscience.visionforge.solid.Sphere import space.kscience.visionforge.solid.Sphere
import space.kscience.visionforge.solid.detail import space.kscience.visionforge.solid.detail
public object ThreeSphereFactory : MeshThreeFactory<Sphere>(Sphere::class) { public object ThreeSphereFactory : MeshThreeFactory<Sphere>(Sphere::class) {
override fun buildGeometry(obj: Sphere): BufferGeometry { override fun buildGeometry(obj: Sphere): BufferGeometry {
return obj.detail?.let {detail -> return obj.detail?.let {detail ->
SphereBufferGeometry( SphereGeometry(
radius = obj.radius, radius = obj.radius,
phiStart = obj.phiStart, phiStart = obj.phiStart,
phiLength = obj.phi, phiLength = obj.phi,
@ -17,7 +17,7 @@ public object ThreeSphereFactory : MeshThreeFactory<Sphere>(Sphere::class) {
widthSegments = detail, widthSegments = detail,
heightSegments = detail heightSegments = detail
) )
}?: SphereBufferGeometry( }?: SphereGeometry(
radius = obj.radius, radius = obj.radius,
phiStart = obj.phiStart, phiStart = obj.phiStart,
phiLength = obj.phi, phiLength = obj.phi,

View File

@ -1,28 +1,34 @@
@file:Suppress("INTERFACE_WITH_SUPERCLASS", @file:Suppress(
"INTERFACE_WITH_SUPERCLASS",
"OVERRIDING_FINAL_MEMBER", "OVERRIDING_FINAL_MEMBER",
"RETURN_TYPE_MISMATCH_ON_OVERRIDE", "RETURN_TYPE_MISMATCH_ON_OVERRIDE",
"CONFLICTING_OVERLOADS", "CONFLICTING_OVERLOADS",
"EXTERNAL_DELEGATION") "EXTERNAL_DELEGATION"
)
@file:JsModule("three-csg-ts") @file:JsModule("three-csg-ts")
@file:JsNonModule @file:JsNonModule
import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.math.Matrix4 import info.laht.threekt.math.Matrix4
import info.laht.threekt.math.Vector3 import info.laht.threekt.math.Vector3
import info.laht.threekt.objects.Mesh import info.laht.threekt.objects.Mesh
external open class CSG { external class CSG {
open fun clone(): CSG fun clone(): CSG
open fun toPolygons(): Array<Polygon> fun toPolygons(): Array<Polygon>
open fun union(csg: CSG): CSG fun toGeometry(toMatrix: Matrix4): BufferGeometry
open fun subtract(csg: CSG): CSG fun union(csg: CSG): CSG
open fun intersect(csg: CSG): CSG fun subtract(csg: CSG): CSG
open fun inverse(): CSG fun intersect(csg: CSG): CSG
fun inverse(): CSG
companion object { companion object {
fun fromPolygons(polygons: Array<Polygon>): CSG fun fromPolygons(polygons: Array<Polygon>): CSG
fun fromGeometry(geom: Any): CSG fun fromGeometry(geom: BufferGeometry, objectIndex: dynamic = definedExternally): CSG
fun fromMesh(mesh: Mesh): CSG fun fromMesh(mesh: Mesh, objectIndex: dynamic = definedExternally): CSG
fun toGeometry(csg: CSG, toMatrix: Matrix4): BufferGeometry
fun toMesh(csg: CSG, toMatrix: Matrix4): Mesh fun toMesh(csg: CSG, toMatrix: Matrix4): Mesh
fun iEval(tokens: Mesh, index: Number? = definedExternally) fun iEval(tokens: Mesh, index: Number? = definedExternally)
fun eval(tokens: Mesh, doRemove: Boolean): Mesh fun eval(tokens: Mesh, doRemove: Boolean): Mesh
@ -35,15 +41,15 @@ external open class CSG {
} }
} }
external open class Vector(x: Number, y: Number, z: Number) : Vector3 { external class Vector(x: Number, y: Number, z: Number) : Vector3 {
open fun negated(): Vector fun negated(): Vector
open fun plus(a: Vector): Vector fun plus(a: Vector): Vector
open fun minus(a: Vector): Vector fun minus(a: Vector): Vector
open fun times(a: Number): Vector fun times(a: Number): Vector
open fun dividedBy(a: Number): Vector fun dividedBy(a: Number): Vector
open fun lerp(a: Vector, t: Number): Any fun lerp(a: Vector, t: Number): Any
open fun unit(): Vector fun unit(): Vector
open fun cross(a: Vector): Any fun cross(a: Vector): Any
} }
external interface IVector { external interface IVector {
@ -52,21 +58,21 @@ external interface IVector {
var z: Number var z: Number
} }
external open class Vertex(pos: IVector, normal: IVector, uv: IVector? = definedExternally) { external class Vertex(pos: IVector, normal: IVector, uv: IVector? = definedExternally) {
open var pos: Vector var pos: Vector
open var normal: Vector var normal: Vector
open var uv: Vector var uv: Vector
open fun clone(): Vertex fun clone(): Vertex
open fun flip() fun flip()
open fun interpolate(other: Vertex, t: Number): Vertex fun interpolate(other: Vertex, t: Number): Vertex
} }
external open class Plane(normal: Vector, w: Number) { external class Plane(normal: Vector, w: Number) {
open var normal: Vector var normal: Vector
open var w: Number var w: Number
open fun clone(): Plane fun clone(): Plane
open fun flip() fun flip()
open fun splitPolygon( fun splitPolygon(
polygon: Polygon, polygon: Polygon,
coplanarFront: Array<Polygon>, coplanarFront: Array<Polygon>,
coplanarBack: Array<Polygon>, coplanarBack: Array<Polygon>,
@ -80,10 +86,10 @@ external open class Plane(normal: Vector, w: Number) {
} }
} }
external open class Polygon(vertices: Array<Vertex>, shared: Any? = definedExternally) { external class Polygon(vertices: Array<Vertex>, shared: Any? = definedExternally) {
open var plane: Plane var plane: Plane
open var vertices: Array<Vertex> var vertices: Array<Vertex>
open var shared: Any var shared: Any
open fun clone(): Polygon fun clone(): Polygon
open fun flip() fun flip()
} }

View File

@ -1,7 +1,7 @@
package space.kscience.visionforge.solid.three package space.kscience.visionforge.solid.three
import CSG import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.* import info.laht.threekt.core.Layers
import info.laht.threekt.external.controls.OrbitControls import info.laht.threekt.external.controls.OrbitControls
import info.laht.threekt.materials.Material import info.laht.threekt.materials.Material
import info.laht.threekt.math.Euler import info.laht.threekt.math.Euler
@ -19,53 +19,13 @@ public val Solid.euler: Euler get() = Euler(rotationX, rotationY, rotationZ, rot
public val MetaItem.vector: Vector3 get() = Vector3(node["x"].float ?: 0f, node["y"].float ?: 0f, node["z"].float ?: 0f) public val MetaItem.vector: Vector3 get() = Vector3(node["x"].float ?: 0f, node["y"].float ?: 0f, node["z"].float ?: 0f)
public fun Geometry.toBufferGeometry(): BufferGeometry = BufferGeometry().apply { fromGeometry(this@toBufferGeometry) }
internal fun Double.toRadians() = this * PI / 180 internal fun Double.toRadians() = this * PI / 180
public fun CSG.toGeometry(): Geometry {
val geom = Geometry()
val vertices = ArrayList<Vector3>()
val faces = ArrayList<Face3>()
for (polygon in toPolygons()) {
val v0 = vertices.size
val pvs = polygon.vertices
for (pv in pvs) {
vertices.add(Vector3().copy(pv.pos))
}
for (j in 3..polygon.vertices.size) {
val fc = Face3(v0, v0 + j - 2, v0 + j - 1, Vector3())
fc.vertexNormals = arrayOf(
Vector3().copy(pvs[0].normal),
Vector3().copy(pvs[j - 2].normal),
Vector3().copy(pvs[j - 1].normal)
)
fc.normal = Vector3().copy(polygon.plane.normal)
faces.add(fc)
}
}
geom.vertices = vertices.toTypedArray()
geom.faces = faces.toTypedArray()
// val inv: Matrix4 = Matrix4().apply { getInverse(toMatrix) }
// geom.applyMatrix(toMatrix)
geom.verticesNeedUpdate = true
geom.elementsNeedUpdate = true
geom.normalsNeedUpdate = true
geom.computeBoundingSphere()
geom.computeBoundingBox()
return geom
}
internal fun Any.dispose() { internal fun Any.dispose() {
when (this) { when (this) {
is Geometry -> dispose()
is BufferGeometry -> dispose() is BufferGeometry -> dispose()
is DirectGeometry -> dispose()
is Material -> dispose() is Material -> dispose()
is Mesh -> { is Mesh -> {
geometry.dispose() geometry.dispose()