Skip to content

Commit a74b7a8

Browse files
committed
Trying to make Scenery more "kotlinesque", starting by refactoring the first "Basic" test:
- added some fake constructors call for initializing the object directly after the instantiation - added an `inline reified` counterpart for `Image.fromResource` - added an `Image::toTexture` function - added the operator overloading `plusAssign` for adding element(s) to the scene - minors
1 parent c47e15f commit a74b7a8

File tree

7 files changed

+81
-33
lines changed

7 files changed

+81
-33
lines changed

src/main/kotlin/graphics/scenery/Box.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import org.joml.Vector3f
77
import java.lang.IllegalArgumentException
88
import kotlin.jvm.JvmOverloads
99

10+
inline fun Box(sizes: Vector3f = Vector3f(1.0f, 1.0f, 1.0f), insideNormals: Boolean = false, block: Box.() -> Unit): Box = Box(sizes, insideNormals).apply(block)
11+
1012
/**
1113
* Constructs a Box [Node] with the dimensions given in [sizes]
1214
*

src/main/kotlin/graphics/scenery/DetachedHeadCamera.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import kotlin.math.PI
1313
import kotlin.math.atan
1414
import kotlin.reflect.KProperty
1515

16+
inline fun DetachedHeadCamera(block: DetachedHeadCamera.() -> Unit): DetachedHeadCamera = DetachedHeadCamera().apply(block)
17+
1618
/**
1719
* Detached Head Camera is a Camera subclass that tracks the head orientation
1820
* in addition to general orientation - useful for HMDs

src/main/kotlin/graphics/scenery/Node.kt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import java.util.concurrent.CopyOnWriteArrayList
2121
import java.util.concurrent.locks.ReentrantLock
2222
import java.util.function.Consumer
2323
import kotlin.collections.ArrayList
24+
import kotlin.collections.Collection
2425

2526
interface Node : Networkable {
2627
var name: String
@@ -137,6 +138,23 @@ interface Node : Networkable {
137138
/** Unique ID of the Node */
138139
fun getUuid(): UUID
139140

141+
/**
142+
* Attaches a child node to this node.
143+
*
144+
* @param[child] The child to attach to this node.
145+
*/
146+
operator fun plusAssign(child: Node) = addChild(child)
147+
148+
/**
149+
* Attaches the given children nodes to this node.
150+
*
151+
* @param[children] The children to attach to this node.
152+
*/
153+
operator fun plusAssign(children: Collection<Node>) {
154+
for (child in children)
155+
addChild(child)
156+
}
157+
140158
/**
141159
* Attaches a child node to this node.
142160
*
@@ -184,12 +202,12 @@ interface Node : Networkable {
184202
*/
185203
fun generateBoundingBox(): OrientedBoundingBox? {
186204
val geometry = geometryOrNull()
187-
if(geometry == null) {
205+
return if(geometry == null) {
188206
logger.warn("$name: Assuming 3rd party BB generation")
189-
return boundingBox
207+
boundingBox
190208
} else {
191209
boundingBox = geometry.generateBoundingBox(children)
192-
return boundingBox
210+
boundingBox
193211
}
194212
}
195213

src/main/kotlin/graphics/scenery/PointLight.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import graphics.scenery.utils.extensions.xyz
66
import org.joml.Vector3f
77
import org.joml.Vector4f
88

9+
inline fun PointLight(radius: Float = 5.0f, block: PointLight.() -> Unit): PointLight = PointLight(radius).apply(block)
10+
911
/**
1012
* Point light class.
1113
*
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package graphics.scenery
2+
3+
inline operator fun <M : Mesh> M.invoke(init: M.() -> Unit): M {
4+
apply(init)
5+
return this
6+
}
7+

src/main/kotlin/graphics/scenery/utils/Image.kt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package graphics.scenery.utils
22

3+
import graphics.scenery.textures.Texture
34
import graphics.scenery.volumes.Colormap
5+
import net.imglib2.type.numeric.integer.UnsignedByteType
6+
import org.joml.Vector3i
47
import org.lwjgl.system.MemoryUtil
58
import java.awt.Color
69
import java.awt.color.ColorSpace
@@ -9,7 +12,6 @@ import java.awt.image.*
912
import java.io.BufferedInputStream
1013
import java.io.IOException
1114
import java.io.InputStream
12-
import java.lang.RuntimeException
1315
import java.nio.ByteBuffer
1416
import java.nio.ByteOrder
1517
import java.util.*
@@ -23,6 +25,17 @@ import javax.imageio.ImageIO
2325
*/
2426
open class Image(val contents: ByteBuffer, val width: Int, val height: Int, val depth: Int = 1) {
2527

28+
fun toTexture(
29+
repeatUVW: Triple<Texture.RepeatMode, Texture.RepeatMode, Texture.RepeatMode> = Texture.RepeatMode.Repeat.all(),
30+
borderColor: Texture.BorderColor = Texture.BorderColor.OpaqueBlack,
31+
normalized: Boolean = true,
32+
mipmap: Boolean = true,
33+
minFilter: Texture.FilteringMode = Texture.FilteringMode.Linear,
34+
maxFilter: Texture.FilteringMode = Texture.FilteringMode.Linear,
35+
usage: HashSet<Texture.UsageType> = hashSetOf(Texture.UsageType.Texture)
36+
): Texture {
37+
return Texture(Vector3i(width, height, depth),4, UnsignedByteType(), contents, repeatUVW, borderColor, normalized, mipmap, usageType = usage, minFilter = minFilter, maxFilter = maxFilter)
38+
}
2639
companion object {
2740
protected val logger by lazyLogger()
2841

@@ -98,6 +111,14 @@ open class Image(val contents: ByteBuffer, val width: Int, val height: Int, val
98111
return Image(imageData, bi.width, bi.height)
99112
}
100113

114+
/**
115+
* Creates an Image from a resource given in [path], with [baseClass] as basis for the search path.
116+
* [path] is expected to end in an extension (e.g., ".png"), such that the file type can be determined.
117+
*/
118+
inline fun <reified K> fromResource(path: String): Image {
119+
return fromStream(K::class.java.getResourceAsStream(path), path.substringAfterLast(".").lowercase())
120+
}
121+
101122
/**
102123
* Creates an Image from a resource given in [path], with [baseClass] as basis for the search path.
103124
* [path] is expected to end in an extension (e.g., ".png"), such that the file type can be determined.

src/test/kotlin/graphics/scenery/tests/examples/basic/ArcballExample.kt

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,60 +19,56 @@ class ArcballExample : SceneryBase("ArcballExample") {
1919
override fun init() {
2020
renderer = hub.add(Renderer.createRenderer(hub, applicationName, scene, 1024, 1024))
2121

22-
val cam: Camera = DetachedHeadCamera()
23-
with(cam) {
22+
val cam: Camera = DetachedHeadCamera {
2423
spatial {
2524
position = Vector3f(0.0f, 0.0f, 2.5f)
2625
}
2726
perspectiveCamera(70.0f, windowWidth, windowHeight)
2827

2928
targeted = true
3029
target = Vector3f(0.0f, 0.0f, 0.0f)
31-
32-
scene.addChild(this)
3330
}
31+
scene += cam
3432

35-
val camlight = PointLight(3.0f)
36-
camlight.intensity = 5.0f
37-
cam.addChild(camlight)
38-
39-
val box = Box(Vector3f(1.0f, 1.0f, 1.0f))
33+
val camlight = PointLight(3.0f) {
34+
intensity = 5.0f
35+
}
36+
cam += camlight
4037

41-
with(box) {
38+
val box = Box(Vector3f(1.0f, 1.0f, 1.0f)) {
4239
spatial {
4340
position = Vector3f(0.0f, 0.0f, 0.0f)
4441
}
4542
material {
4643
ambient = Vector3f(1.0f, 0.0f, 0.0f)
4744
diffuse = Vector3f(0.0f, 1.0f, 0.0f)
48-
textures["diffuse"] = Texture.fromImage(Image.fromResource("textures/helix.png", TexturedCubeExample::class.java))
45+
textures["diffuse"] = Image.fromResource<TexturedCubeExample>("textures/helix.png").toTexture()
4946
specular = Vector3f(1.0f, 1.0f, 1.0f)
5047
}
51-
52-
scene.addChild(this)
5348
}
49+
scene += box
5450

55-
val lights = (0..2).map {
56-
PointLight(radius = 15.0f)
57-
}.map { light ->
58-
light.spatial {
59-
position = Random.random3DVectorFromRange(-3.0f, 3.0f)
51+
val lights = List(3) {
52+
PointLight(radius = 15.0f) {
53+
spatial {
54+
position = Random.random3DVectorFromRange(-3.0f, 3.0f)
55+
}
56+
emissionColor = Random.random3DVectorFromRange(0.2f, 0.8f)
57+
intensity = Random.randomFromRange(0.1f, 0.8f)
6058
}
61-
light.emissionColor = Random.random3DVectorFromRange(0.2f, 0.8f)
62-
light.intensity = Random.randomFromRange(0.1f, 0.8f)
63-
light
6459
}
6560

66-
val floor = Box(Vector3f(500.0f, 0.05f, 500.0f))
67-
floor.spatial {
68-
position = Vector3f(0.0f, -1.0f, 0.0f)
69-
}
70-
floor.material {
71-
diffuse = Vector3f(1.0f, 1.0f, 1.0f)
61+
val floor = Box(Vector3f(500.0f, 0.05f, 500.0f)) {
62+
spatial {
63+
position = Vector3f(0.0f, -1.0f, 0.0f)
64+
}
65+
material {
66+
diffuse = Vector3f(1.0f, 1.0f, 1.0f)
67+
}
7268
}
73-
scene.addChild(floor)
69+
scene += floor
7470

75-
lights.forEach(scene::addChild)
71+
scene += lights
7672
}
7773

7874
override fun inputSetup() {

0 commit comments

Comments
 (0)