Added manual tube. Fixed some bugs.
This commit is contained in:
parent
cf5a4fd7f6
commit
073ae8a353
@ -81,7 +81,11 @@ abstract class AbstractVisualObject(override val parent: VisualObject?) : Visual
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var _config: Config? = null
|
private var _config: Config? = null
|
||||||
override val config: Config get() = _config ?: Config().also { _config = it }
|
override val config: Config
|
||||||
|
get() = _config ?: Config().also { config ->
|
||||||
|
_config = config
|
||||||
|
config.onChange(this, ::propertyChanged)
|
||||||
|
}
|
||||||
|
|
||||||
override fun setProperty(name: Name, value: Any?) {
|
override fun setProperty(name: Name, value: Any?) {
|
||||||
config[name] = value
|
config[name] = value
|
||||||
@ -120,6 +124,13 @@ open class VisualGroup<T : VisualObject>(parent: VisualObject?) : AbstractVisual
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) {
|
||||||
|
super.propertyChanged(name, before, after)
|
||||||
|
forEach {
|
||||||
|
it.propertyChanged(name, before, after)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private data class Listener<T : VisualObject>(val owner: Any?, val callback: (Name?, T?) -> Unit)
|
private data class Listener<T : VisualObject>(val owner: Any?, val callback: (Name?, T?) -> Unit)
|
||||||
|
|
||||||
private val listeners = HashSet<Listener<T>>()
|
private val listeners = HashSet<Listener<T>>()
|
||||||
@ -164,10 +175,12 @@ open class VisualGroup<T : VisualObject>(parent: VisualObject?) : AbstractVisual
|
|||||||
* Get named child by name
|
* Get named child by name
|
||||||
*/
|
*/
|
||||||
operator fun get(name: Name): T? = namedChildren[name]
|
operator fun get(name: Name): T? = namedChildren[name]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get named child by string
|
* Get named child by string
|
||||||
*/
|
*/
|
||||||
operator fun get(key: String): T? = namedChildren[key]
|
operator fun get(key: String): T? = namedChildren[key]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an unnamed child
|
* Get an unnamed child
|
||||||
*/
|
*/
|
||||||
|
@ -33,7 +33,7 @@ class RendererDemoView : View() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var color by group.config.number(1530).int
|
var color by group.config.number(1530)
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
val random = Random(111)
|
val random = Random(111)
|
||||||
|
@ -45,10 +45,14 @@ private fun VisualGroup3D.addSolid(
|
|||||||
val aScale = solid.ascale()
|
val aScale = solid.ascale()
|
||||||
return when (solid) {
|
return when (solid) {
|
||||||
is GDMLBox -> box(solid.x * lScale, solid.y * lScale, solid.z * lScale, name)
|
is GDMLBox -> box(solid.x * lScale, solid.y * lScale, solid.z * lScale, name)
|
||||||
is GDMLTube -> cylinder(solid.rmax * lScale, solid.z * lScale, name) {
|
is GDMLTube -> tube(
|
||||||
startAngle = solid.startphi * aScale
|
solid.rmax * lScale,
|
||||||
angle = solid.deltaphi * aScale
|
solid.z * lScale,
|
||||||
}
|
solid.rmin * lScale,
|
||||||
|
solid.startphi * aScale,
|
||||||
|
solid.deltaphi * aScale,
|
||||||
|
name
|
||||||
|
)
|
||||||
is GDMLXtru -> extrude(name) {
|
is GDMLXtru -> extrude(name) {
|
||||||
shape {
|
shape {
|
||||||
solid.vertices.forEach {
|
solid.vertices.forEach {
|
||||||
@ -193,8 +197,7 @@ private fun volume(
|
|||||||
?: context.templates.addSolid(context, solid, solid.name) {
|
?: context.templates.addSolid(context, solid, solid.name) {
|
||||||
this.material = context.resolveColor(group, material, solid)
|
this.material = context.resolveColor(group, material, solid)
|
||||||
}
|
}
|
||||||
val wrapper = Proxy3D(this,cachedSolid)
|
proxy(cachedSolid, solid.name)
|
||||||
add(wrapper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
when (val vol = group.placement) {
|
when (val vol = group.placement) {
|
||||||
|
@ -90,11 +90,11 @@ private class GDMLDemoApp : ApplicationBase() {
|
|||||||
launch { message("Converting GDML into DF-VIS format") }
|
launch { message("Converting GDML into DF-VIS format") }
|
||||||
val visual = gdml.toVisual {
|
val visual = gdml.toVisual {
|
||||||
lUnit = LUnit.CM
|
lUnit = LUnit.CM
|
||||||
// acceptSolid = { solid ->
|
acceptSolid = { solid ->
|
||||||
// !solid.name.startsWith("ecal")
|
!solid.name.startsWith("ecal")
|
||||||
// && !solid.name.startsWith("V")
|
// && !solid.name.startsWith("V")
|
||||||
// && !solid.name.startsWith("U")
|
// && !solid.name.startsWith("U")
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
launch { message("Rendering") }
|
launch { message("Rendering") }
|
||||||
val output = three.output(canvas)
|
val output = three.output(canvas)
|
||||||
|
@ -31,7 +31,12 @@ private class ThreeDemoApp : ApplicationBase() {
|
|||||||
}
|
}
|
||||||
sphere(50.0) {
|
sphere(50.0) {
|
||||||
x = 110
|
x = 110
|
||||||
detail = 200
|
detail = 16
|
||||||
|
}
|
||||||
|
tube(50, height = 10, innerRadius = 25, angle = PI) {
|
||||||
|
y = 110
|
||||||
|
detail = 16
|
||||||
|
rotationX = PI/4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,12 +3,10 @@ package hep.dataforge.vis.spatial.three
|
|||||||
import hep.dataforge.vis.spatial.Box
|
import hep.dataforge.vis.spatial.Box
|
||||||
import hep.dataforge.vis.spatial.detail
|
import hep.dataforge.vis.spatial.detail
|
||||||
import info.laht.threekt.geometries.BoxBufferGeometry
|
import info.laht.threekt.geometries.BoxBufferGeometry
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
object ThreeBoxFactory : MeshThreeFactory<Box>(Box::class) {
|
object ThreeBoxFactory : MeshThreeFactory<Box>(Box::class) {
|
||||||
override fun buildGeometry(obj: Box) =
|
override fun buildGeometry(obj: Box) =
|
||||||
obj.detail?.let {
|
obj.detail?.let { detail ->
|
||||||
val segments = it.toDouble().pow(1.0 / 3.0).toInt()
|
BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize, detail, detail, detail)
|
||||||
BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize, segments, segments, segments)
|
|
||||||
} ?: BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
|
} ?: BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
|
||||||
}
|
}
|
@ -36,6 +36,7 @@ interface ThreeFactory<T : VisualObject3D> {
|
|||||||
* Update position, rotation and visibility
|
* Update position, rotation and visibility
|
||||||
*/
|
*/
|
||||||
internal fun Object3D.updatePosition(obj: VisualObject3D) {
|
internal fun Object3D.updatePosition(obj: VisualObject3D) {
|
||||||
|
visible = obj.visible ?: true
|
||||||
position.set(obj.x, obj.y, obj.z)
|
position.set(obj.x, obj.y, obj.z)
|
||||||
setRotationFromEuler(obj.euler)
|
setRotationFromEuler(obj.euler)
|
||||||
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
|
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
|
||||||
@ -125,7 +126,7 @@ abstract class MeshThreeFactory<T : VisualObject3D>(override val type: KClass<ou
|
|||||||
//update position of mesh using this object
|
//update position of mesh using this object
|
||||||
mesh.updatePosition(obj)
|
mesh.updatePosition(obj)
|
||||||
} else if (name == VisualObject3D.VISIBLE_KEY) {
|
} else if (name == VisualObject3D.VISIBLE_KEY) {
|
||||||
obj.visible = obj.visible ?: true
|
mesh.visible = obj.visible ?: true
|
||||||
} else {
|
} else {
|
||||||
//full update
|
//full update
|
||||||
mesh.geometry = geometryBuilder(obj)
|
mesh.geometry = geometryBuilder(obj)
|
||||||
|
@ -2,7 +2,6 @@ package hep.dataforge.vis.spatial.three
|
|||||||
|
|
||||||
import hep.dataforge.vis.spatial.Proxy3D
|
import hep.dataforge.vis.spatial.Proxy3D
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D
|
import hep.dataforge.vis.spatial.VisualObject3D
|
||||||
import info.laht.threekt.core.BufferGeometry
|
|
||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
|
|
||||||
@ -16,8 +15,8 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy3D> {
|
|||||||
three.buildObject3D(obj.template) as Mesh
|
three.buildObject3D(obj.template) as Mesh
|
||||||
}
|
}
|
||||||
|
|
||||||
val mesh = Mesh(templateMesh.geometry as BufferGeometry, templateMesh.material)
|
//val mesh = Mesh(templateMesh.geometry as BufferGeometry, templateMesh.material)
|
||||||
//val mesh = templateMesh.clone()
|
val mesh = templateMesh.clone()
|
||||||
|
|
||||||
mesh.updatePosition(obj)
|
mesh.updatePosition(obj)
|
||||||
return mesh
|
return mesh
|
||||||
|
@ -4,20 +4,18 @@ import hep.dataforge.vis.spatial.Sphere
|
|||||||
import hep.dataforge.vis.spatial.detail
|
import hep.dataforge.vis.spatial.detail
|
||||||
import info.laht.threekt.core.BufferGeometry
|
import info.laht.threekt.core.BufferGeometry
|
||||||
import info.laht.threekt.geometries.SphereBufferGeometry
|
import info.laht.threekt.geometries.SphereBufferGeometry
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
object ThreeSphereFactory : MeshThreeFactory<Sphere>(Sphere::class) {
|
object ThreeSphereFactory : MeshThreeFactory<Sphere>(Sphere::class) {
|
||||||
override fun buildGeometry(obj: Sphere): BufferGeometry {
|
override fun buildGeometry(obj: Sphere): BufferGeometry {
|
||||||
return obj.detail?.let {
|
return obj.detail?.let {detail ->
|
||||||
val segments = it.toDouble().pow(0.5).toInt()
|
|
||||||
SphereBufferGeometry(
|
SphereBufferGeometry(
|
||||||
radius = obj.radius,
|
radius = obj.radius,
|
||||||
phiStart = obj.phiStart,
|
phiStart = obj.phiStart,
|
||||||
phiLength = obj.phi,
|
phiLength = obj.phi,
|
||||||
thetaStart = obj.thetaStart,
|
thetaStart = obj.thetaStart,
|
||||||
thetaLength = obj.theta,
|
thetaLength = obj.theta,
|
||||||
widthSegments = segments,
|
widthSegments = detail,
|
||||||
heightSegments = segments
|
heightSegments = detail
|
||||||
)
|
)
|
||||||
}?: SphereBufferGeometry(
|
}?: SphereBufferGeometry(
|
||||||
radius = obj.radius,
|
radius = obj.radius,
|
||||||
|
@ -7,9 +7,9 @@ class Box(parent: VisualObject?, val xSize: Number, val ySize: Number, val zSize
|
|||||||
|
|
||||||
//TODO add helper for color configuration
|
//TODO add helper for color configuration
|
||||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
val dx = xSize.toDouble() / 2
|
val dx = xSize.toFloat() / 2
|
||||||
val dy = ySize.toDouble() / 2
|
val dy = ySize.toFloat() / 2
|
||||||
val dz = zSize.toDouble() / 2
|
val dz = zSize.toFloat() / 2
|
||||||
val node1 = Point3D(-dx, -dy, -dz)
|
val node1 = Point3D(-dx, -dy, -dz)
|
||||||
val node2 = Point3D(dx, -dy, -dz)
|
val node2 = Point3D(dx, -dy, -dz)
|
||||||
val node3 = Point3D(dx, dy, -dz)
|
val node3 = Point3D(dx, dy, -dz)
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.common.number
|
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cylinder or cut cone segment
|
* A cylinder or cut cone segment
|
||||||
*/
|
*/
|
||||||
class Cylinder(parent: VisualObject?, var radius: Number, var height: Number) : VisualLeaf3D(parent) {
|
class Cylinder(
|
||||||
var upperRadius by number(radius)
|
parent: VisualObject?,
|
||||||
var startAngle by number(0.0)
|
var radius: Number,
|
||||||
var angle by number(2 * PI)
|
var height: Number,
|
||||||
}
|
var upperRadius: Number = radius,
|
||||||
|
var startAngle: Number = 0f,
|
||||||
|
var angle: Number = 2 * PI
|
||||||
|
) : VisualLeaf3D(parent)
|
||||||
|
|
||||||
fun VisualGroup3D.cylinder(
|
fun VisualGroup3D.cylinder(
|
||||||
r: Number,
|
r: Number,
|
||||||
|
@ -46,19 +46,6 @@ class Extruded(parent: VisualObject?) : VisualLeaf3D(parent), Shape {
|
|||||||
//TODO send invalidation signal
|
//TODO send invalidation signal
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : Any> GeometryBuilder<T>.cap(shape: List<Point3D>) {
|
|
||||||
//FIXME won't work for non-convex shapes
|
|
||||||
val center = Point3D(
|
|
||||||
shape.map { it.x.toDouble() }.average(),
|
|
||||||
shape.map { it.y.toDouble() }.average(),
|
|
||||||
shape.map { it.z.toDouble() }.average()
|
|
||||||
)
|
|
||||||
for(i in 0 until (shape.size - 1)){
|
|
||||||
face(shape[i], shape[i+1], center, null)
|
|
||||||
}
|
|
||||||
face(shape.last(), shape.first(),center,null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
val shape: Shape2D = shape
|
val shape: Shape2D = shape
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ data class Point2D(val x: Number, val y: Number) : MetaRepr {
|
|||||||
"y" to y
|
"y" to y
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object{
|
companion object {
|
||||||
fun from(meta: Meta): Point2D{
|
fun from(meta: Meta): Point2D {
|
||||||
return Point2D(meta["x"].number ?: 0, meta["y"].number ?: 0)
|
return Point2D(meta["x"].number ?: 0, meta["y"].number ?: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,12 +22,12 @@ data class Point3D(val x: Number, val y: Number, val z: Number) : MetaRepr {
|
|||||||
"z" to z
|
"z" to z
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object{
|
companion object {
|
||||||
fun from(meta: Meta): Point3D{
|
fun from(meta: Meta): Point3D {
|
||||||
return Point3D(meta["x"].number ?: 0, meta["y"].number ?: 0, meta["y"].number ?: 0)
|
return Point3D(meta["x"].number ?: 0, meta["y"].number ?: 0, meta["y"].number ?: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
val zero = Point3D(0,0,0)
|
val zero = Point3D(0, 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ interface GeometryBuilder<T : Any> {
|
|||||||
* @param normal optional external normal to the face
|
* @param normal optional external normal to the face
|
||||||
* @param meta optional additional platform-specific parameters like color or texture index
|
* @param meta optional additional platform-specific parameters like color or texture index
|
||||||
*/
|
*/
|
||||||
fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D?, meta: Meta = EmptyMeta)
|
fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D? = null, meta: Meta = EmptyMeta)
|
||||||
|
|
||||||
fun build(): T
|
fun build(): T
|
||||||
}
|
}
|
||||||
@ -62,3 +62,16 @@ fun GeometryBuilder<*>.face4(
|
|||||||
interface Shape : VisualObject3D {
|
interface Shape : VisualObject3D {
|
||||||
fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>)
|
fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T : Any> GeometryBuilder<T>.cap(shape: List<Point3D>, normal: Point3D? = null) {
|
||||||
|
//FIXME won't work for non-convex shapes
|
||||||
|
val center = Point3D(
|
||||||
|
shape.map { it.x.toDouble() }.average(),
|
||||||
|
shape.map { it.y.toDouble() }.average(),
|
||||||
|
shape.map { it.z.toDouble() }.average()
|
||||||
|
)
|
||||||
|
for (i in 0 until (shape.size - 1)) {
|
||||||
|
face(shape[i], shape[i + 1], center, normal)
|
||||||
|
}
|
||||||
|
face(shape.last(), shape.first(), center, normal)
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
import kotlin.math.PI
|
||||||
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stright tube segment
|
||||||
|
*/
|
||||||
|
class Tube(
|
||||||
|
parent: VisualObject?,
|
||||||
|
var radius: Float,
|
||||||
|
var height: Float,
|
||||||
|
var innerRadius: Float = 0f,
|
||||||
|
var startAngle: Float = 0f,
|
||||||
|
var angle: Float = PI2
|
||||||
|
) : VisualLeaf3D(parent), Shape {
|
||||||
|
|
||||||
|
init {
|
||||||
|
require(radius > 0)
|
||||||
|
require(height > 0)
|
||||||
|
require(innerRadius >= 0)
|
||||||
|
require(startAngle >= 0)
|
||||||
|
require(angle in (0f..(PI2)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
|
val segments = detail ?: 8
|
||||||
|
require(segments >= 4) { "The number of segments in tube is too small" }
|
||||||
|
val angleStep = angle / (segments - 1)
|
||||||
|
|
||||||
|
fun shape(r: Float, z: Float): List<Point3D> {
|
||||||
|
return (0 until segments).map { i ->
|
||||||
|
Point3D(r * cos(startAngle + angleStep * i), r * sin(startAngle + angleStep * i), z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
geometryBuilder.apply {
|
||||||
|
|
||||||
|
//creating shape in x-y plane with z = 0
|
||||||
|
val bottomOuterPoints = shape(radius, 0f)
|
||||||
|
val upperOuterPoints = shape(radius, height)
|
||||||
|
//outer face
|
||||||
|
(1 until segments).forEach {
|
||||||
|
face4(bottomOuterPoints[it - 1], bottomOuterPoints[it], upperOuterPoints[it], upperOuterPoints[it - 1])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (angle == PI2) {
|
||||||
|
face4(bottomOuterPoints.last(), bottomOuterPoints[0], upperOuterPoints[0], upperOuterPoints.last())
|
||||||
|
}
|
||||||
|
if (innerRadius == 0f) {
|
||||||
|
val zeroBottom = Point3D(0f, 0f, 0f)
|
||||||
|
val zeroTop = Point3D(0f, 0f, height)
|
||||||
|
(1 until segments).forEach {
|
||||||
|
face(bottomOuterPoints[it - 1], zeroBottom, bottomOuterPoints[it])
|
||||||
|
face(upperOuterPoints[it - 1], upperOuterPoints[it], zeroTop)
|
||||||
|
}
|
||||||
|
if (angle == PI2) {
|
||||||
|
face(bottomOuterPoints.last(), zeroBottom, bottomOuterPoints[0])
|
||||||
|
face(upperOuterPoints.last(), upperOuterPoints[0], zeroTop)
|
||||||
|
} else {
|
||||||
|
face4(zeroTop, zeroBottom, bottomOuterPoints[0], upperOuterPoints[0])
|
||||||
|
face4(zeroTop, zeroBottom, bottomOuterPoints.last(), upperOuterPoints.last())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val bottomInnerPoints = shape(innerRadius, 0f)
|
||||||
|
val upperInnerPoints = shape(innerRadius, height)
|
||||||
|
//outer face
|
||||||
|
(1 until segments).forEach {
|
||||||
|
// inner surface
|
||||||
|
face4(
|
||||||
|
bottomInnerPoints[it],
|
||||||
|
bottomInnerPoints[it - 1],
|
||||||
|
upperInnerPoints[it - 1],
|
||||||
|
upperInnerPoints[it]
|
||||||
|
)
|
||||||
|
//bottom cup
|
||||||
|
face4(
|
||||||
|
bottomInnerPoints[it - 1],
|
||||||
|
bottomInnerPoints[it],
|
||||||
|
bottomOuterPoints[it],
|
||||||
|
bottomOuterPoints[it - 1]
|
||||||
|
)
|
||||||
|
//upper cup
|
||||||
|
face4(
|
||||||
|
upperInnerPoints[it],
|
||||||
|
upperInnerPoints[it - 1],
|
||||||
|
upperOuterPoints[it - 1],
|
||||||
|
upperOuterPoints[it]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (angle == PI2) {
|
||||||
|
face4(bottomInnerPoints[0], bottomInnerPoints.last(), upperInnerPoints.last(), upperInnerPoints[0])
|
||||||
|
face4(
|
||||||
|
bottomInnerPoints.last(),
|
||||||
|
bottomInnerPoints[0],
|
||||||
|
bottomOuterPoints[0],
|
||||||
|
bottomOuterPoints.last()
|
||||||
|
)
|
||||||
|
face4(upperInnerPoints[0], upperInnerPoints.last(), upperOuterPoints.last(), upperOuterPoints[0])
|
||||||
|
} else{
|
||||||
|
face4(bottomInnerPoints[0],bottomOuterPoints[0],upperOuterPoints[0],upperInnerPoints[0])
|
||||||
|
face4(bottomOuterPoints.last(),bottomInnerPoints.last(),upperInnerPoints.last(),upperOuterPoints.last())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun VisualGroup3D.tube(
|
||||||
|
r: Number,
|
||||||
|
height: Number,
|
||||||
|
innerRadius: Number = 0f,
|
||||||
|
startAngle: Number = 0f,
|
||||||
|
angle: Number = 2 * PI,
|
||||||
|
name: String? = null,
|
||||||
|
block: Tube.() -> Unit = {}
|
||||||
|
): Tube {
|
||||||
|
val tube = Tube(
|
||||||
|
this,
|
||||||
|
r.toFloat(),
|
||||||
|
height.toFloat(),
|
||||||
|
innerRadius.toFloat(),
|
||||||
|
startAngle.toFloat(),
|
||||||
|
angle.toFloat()
|
||||||
|
).apply(
|
||||||
|
block
|
||||||
|
)
|
||||||
|
return tube.also { set(name, it) }
|
||||||
|
}
|
@ -105,10 +105,10 @@ var VisualObject3D.rotationOrder: RotationOrder
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default
|
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default. Not inherited
|
||||||
*/
|
*/
|
||||||
var VisualObject3D.detail: Int?
|
var VisualObject3D.detail: Int?
|
||||||
get() = getProperty(DETAIL_KEY).int
|
get() = getProperty(DETAIL_KEY,false).int
|
||||||
set(value) = setProperty(DETAIL_KEY, value)
|
set(value) = setProperty(DETAIL_KEY, value)
|
||||||
|
|
||||||
var VisualObject3D.material: Meta?
|
var VisualObject3D.material: Meta?
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import kotlin.math.PI
|
||||||
|
|
||||||
object World {
|
object World {
|
||||||
const val CAMERA_INITIAL_DISTANCE = -500.0
|
const val CAMERA_INITIAL_DISTANCE = -500.0
|
||||||
const val CAMERA_INITIAL_X_ANGLE = -50.0
|
const val CAMERA_INITIAL_X_ANGLE = -50.0
|
||||||
@ -8,3 +10,5 @@ object World {
|
|||||||
const val CAMERA_NEAR_CLIP = 0.1
|
const val CAMERA_NEAR_CLIP = 0.1
|
||||||
const val CAMERA_FAR_CLIP = 10000.0
|
const val CAMERA_FAR_CLIP = 10000.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const val PI2: Float = 2 * PI.toFloat()
|
Loading…
Reference in New Issue
Block a user