Skip to content

Commit

Permalink
Chapter 14: Shapes may now have null materials which delegate to pare…
Browse files Browse the repository at this point in the history
…nts or the default material.
  • Loading branch information
sraaphorst committed Jan 21, 2023
1 parent fe13b76 commit 7ebc391
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/main/kotlin/apps/ch13_groups.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fun main() {
Cylinder(0, 0.5, true, t)
}

Group(gt, m, listOf(concentricCylinder1, concentricCylinder2, concentricCylinder3, concentricCylinder4))
Group(gt, m, children=listOf(concentricCylinder1, concentricCylinder2, concentricCylinder3, concentricCylinder4))
}

val decorativeCylinder1 = run {
Expand Down
5 changes: 3 additions & 2 deletions src/main/kotlin/shapes/Cone.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@ class Cone(minimum: Number = Double.NEGATIVE_INFINITY,
maximum: Number = Double.POSITIVE_INFINITY,
val closed: Boolean = false,
transformation: Matrix = Matrix.I,
material: Material = Material(),
material: Material? = null,
castsShadow: Boolean = true,
parent: Shape? = null):
Shape(transformation, material, castsShadow, parent) {

val minimum = minimum.toDouble()
val maximum = maximum.toDouble()

// Note due to Kotlin semantics, we have to use objMaterial here.
override fun withParent(parent: Shape?): Shape =
Cone(minimum, maximum, closed, transformation, material, castsShadow, parent)
Cone(minimum, maximum, closed, transformation, objMaterial, castsShadow, parent)

override fun withMaterial(material: Material): Shape =
Cone(minimum, maximum, closed, transformation, material, castsShadow, parent)
Expand Down
6 changes: 4 additions & 2 deletions src/main/kotlin/shapes/Cube.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import math.Intersection
import kotlin.math.absoluteValue

class Cube(transformation: Matrix = Matrix.I,
material: Material = Material(),
material: Material? = null,
castsShadow: Boolean = true,
parent: Shape? = null):
Shape(transformation, material, castsShadow, parent) {

// Note due to Kotlin semantics, we have to use objMaterial here.
override fun withParent(parent: Shape?): Shape =
Cube(transformation, material, castsShadow, parent)
Cube(transformation, objMaterial, castsShadow, parent)

override fun withMaterial(material: Material): Shape =
Cube(transformation, material, castsShadow, parent)
Expand Down
5 changes: 3 additions & 2 deletions src/main/kotlin/shapes/Cylinder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ class Cylinder(minimum: Number = Double.NEGATIVE_INFINITY,
maximum: Number = Double.POSITIVE_INFINITY,
val closed: Boolean = false,
transformation: Matrix = Matrix.I,
material: Material = Material(),
material: Material? = null,
castsShadow: Boolean = true,
parent: Shape? = null):
Shape(transformation, material, castsShadow, parent) {

val minimum = minimum.toDouble()
val maximum = maximum.toDouble()

// Note due to Kotlin semantics, we have to use objMaterial here.
override fun withParent(parent: Shape?): Shape =
Cylinder(minimum, maximum, closed, transformation, material, castsShadow, parent)
Cylinder(minimum, maximum, closed, transformation, objMaterial, castsShadow, parent)

override fun withMaterial(material: Material): Shape =
Cylinder(minimum, maximum, closed, transformation, material, castsShadow, parent)
Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/shapes/Group.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ import math.*
import math.BoundingBox.Companion.MaxPoint
import math.BoundingBox.Companion.MinPoint
import math.Intersection
import kotlin.math.PI

class Group(transformation: Matrix = Matrix.I,
material: Material = Material(),
material: Material? = null,
children: List<Shape> = emptyList(),
castsShadow: Boolean = true,
parent: Shape? = null):
Shape(transformation, material, castsShadow, parent) {

// Make copies of all the children to backreference this as their parent.
val children = children.map { it.withParent(this) }
val children = run { children.map { it.withParent(this) } }
val size = children.size
val isEmpty = children.isEmpty()
val isNotEmpty = children.isNotEmpty()
Expand All @@ -28,8 +27,9 @@ class Group(transformation: Matrix = Matrix.I,
operator fun contains(s: Shape): Boolean =
s in children

// Note due to Kotlin semantics, we have to use objMaterial here.
override fun withParent(parent: Shape?): Shape =
Group(transformation, material, children, castsShadow, parent)
Group(transformation, objMaterial, children, castsShadow, parent)

fun withTransformation(transformation: Matrix): Shape {
if (!transformation.isTransformation())
Expand All @@ -38,7 +38,7 @@ class Group(transformation: Matrix = Matrix.I,
return Group(transformation, material, children, castsShadow, parent)
}

fun forEach(f: (Shape) -> Unit): Unit {
fun forEach(f: (Shape) -> Unit) {
children.forEach(f)
}

Expand Down
6 changes: 4 additions & 2 deletions src/main/kotlin/shapes/Plane.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import math.*
import kotlin.math.absoluteValue

class Plane(transformation: Matrix = Matrix.I,
material: Material = Material(),
material: Material? = null,
castsShadow: Boolean = true,
parent: Shape? = null):
Shape(transformation, material, castsShadow, parent) {

// Note due to Kotlin semantics, we have to use objMaterial here.
override fun withParent(parent: Shape?): Shape =
Plane(transformation, material, castsShadow, parent)
Plane(transformation, objMaterial, castsShadow, parent)

override fun withMaterial(material: Material): Shape =
Plane(transformation, material, castsShadow, parent)
Expand Down
14 changes: 13 additions & 1 deletion src/main/kotlin/shapes/Shape.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import java.util.UUID
import kotlin.math.PI

abstract class Shape(val transformation: Matrix,
val material: Material,
material: Material? = null,
val castsShadow: Boolean,
val parent: Shape?,
private val id: UUID = UUID.randomUUID()) {
Expand All @@ -19,6 +19,14 @@ abstract class Shape(val transformation: Matrix,
"\tShape: ${javaClass.name}\nTransformation:\n${transformation.show()}")
}

// We need to store the parameter passed in for material here in order to propagate it correctly.
// We will access it below: if an object does not have a material, it will try to see if it has a parent
// with a material.
protected val objMaterial = material

val material: Material
get() = objMaterial ?: (parent?.objMaterial ?: DefaultMaterial)

// This method should only be invoked by Groups containing the object.
internal abstract fun withParent(parent: Shape? = null): Shape

Expand Down Expand Up @@ -71,4 +79,8 @@ abstract class Shape(val transformation: Matrix,
internal val parentBounds: BoundingBox by lazy {
bounds.transform(transformation)
}

companion object {
private val DefaultMaterial = Material()
}
}
6 changes: 4 additions & 2 deletions src/main/kotlin/shapes/Sphere.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import math.Intersection
import kotlin.math.sqrt

class Sphere(transformation: Matrix = Matrix.I,
material: Material = Material(),
material: Material? = null,
castsShadow: Boolean = true,
parent: Shape? = null):
Shape(transformation, material, castsShadow, parent) {

// Note due to Kotlin semantics, we have to use objMaterial here.
override fun withParent(parent: Shape?): Shape =
Sphere(transformation, material, castsShadow, parent)
Sphere(transformation, objMaterial, castsShadow, parent)

override fun withMaterial(material: Material): Shape =
Sphere(transformation, material, castsShadow, parent)
Expand Down

0 comments on commit 7ebc391

Please sign in to comment.