diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 75a6258cb..4e9742ba6 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,8 +1,6 @@
-
-
@@ -10,6 +8,5 @@
-
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 2d9529908..ae8a33732 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,9 @@
+
+
+
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Terrarum.xml b/.idea/runConfigurations/Terrarum.xml
index 5cf10822e..6928af11a 100644
--- a/.idea/runConfigurations/Terrarum.xml
+++ b/.idea/runConfigurations/Terrarum.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/.idea/runConfigurations/Terrarum__no_DEV_MODE_.xml b/.idea/runConfigurations/Terrarum__no_DEV_MODE_.xml
index a41986fab..8e156951b 100644
--- a/.idea/runConfigurations/Terrarum__no_DEV_MODE_.xml
+++ b/.idea/runConfigurations/Terrarum__no_DEV_MODE_.xml
@@ -1,7 +1,6 @@
-
diff --git a/src/module-info.java b/src/module-info.java
index 1b02a65fe..ad93f8437 100644
--- a/src/module-info.java
+++ b/src/module-info.java
@@ -4,7 +4,6 @@ module Terrarum {
requires java.desktop;
requires java.logging;
requires jdk.unsupported; // sun.misc.Unsafe
- requires jdk.incubator.vector;
// kotlin
requires kotlin.stdlib;
diff --git a/src/net/torvald/gdx/graphics/Cvec.kt b/src/net/torvald/gdx/graphics/Cvec.kt
index 82ef99077..f71f4e567 100644
--- a/src/net/torvald/gdx/graphics/Cvec.kt
+++ b/src/net/torvald/gdx/graphics/Cvec.kt
@@ -18,16 +18,12 @@ package net.torvald.gdx.graphics
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.utils.NumberUtils
-import jdk.incubator.vector.FloatVector
-import jdk.incubator.vector.FloatVector.SPECIES_128
/**
* A Cvec is kind of a Vector4f made compatible with LibGdx's Color class, with the intention of actually utilising
* the JEP 338 VectorInstrinsics later, when the damned thing finally releases.
*
* Before then, the code will be identical to LibGdx's.
- *
- * THIS CLASS MUST NOT BE SERIALISED
*/
/** A color class, holding the r, g, b and alpha component as floats in the range [0,1]. All methods perform clamping on the
@@ -37,13 +33,11 @@ import jdk.incubator.vector.FloatVector.SPECIES_128
*/
class Cvec {
- var vec = FloatVector.broadcast(SPECIES_128, 0f); private set
-
/** the red, green, blue and alpha components */
- val r: Float; get() = vec.lane(0)
- val g: Float; get() = vec.lane(1)
- val b: Float; get() = vec.lane(2)
- val a: Float; get() = vec.lane(3)
+ var r: Float = 0f
+ var g: Float = 0f
+ var b: Float = 0f
+ var a: Float = 0f
/** Constructs a new Cvec with all components set to 0. */
constructor() {}
@@ -54,16 +48,11 @@ class Cvec {
rgba8888ToCvec(this, rgba8888)
}
- constructor(scalar: Float) {
- vec = FloatVector.broadcast(SPECIES_128, scalar)
- }
-
constructor(color: Color) {
- vec = FloatVector.fromArray(SPECIES_128, floatArrayOf(color.r, color.g, color.b, color.a), 0)
- }
-
- constructor(vec: FloatVector) {
- this.vec = vec
+ this.r = color.r
+ this.g = color.g
+ this.b = color.b
+ this.a = color.a
}
/** Constructor, sets the components of the color
@@ -74,7 +63,10 @@ class Cvec {
* @param a the alpha component
*/
constructor(r: Float, g: Float, b: Float, a: Float) {
- vec = FloatVector.fromArray(SPECIES_128, floatArrayOf(r, g, b, a), 0)
+ this.r = r
+ this.g = g
+ this.b = b
+ this.a = a
}
/** Constructs a new color using the given color
@@ -85,10 +77,10 @@ class Cvec {
set(color)
}
-// operator fun component1() = r
-// operator fun component2() = g
-// operator fun component3() = b
-// operator fun component4() = a
+ operator fun component1() = r
+ operator fun component2() = g
+ operator fun component3() = b
+ operator fun component4() = a
/**
* Get RGBA Element using index, of which:
@@ -97,24 +89,23 @@ class Cvec {
* - 2: B
* - 3: A
*/
- inline fun getElem(index: Int) = vec.lane(index)
+ fun getElem(index: Int) = when(index) {
+ 0 -> r
+ 1 -> g
+ 2 -> b
+ 3 -> a
+ else -> throw IndexOutOfBoundsException("Invalid index $index")
+ }
/** Sets this color to the given color.
*
* @param color the Cvec
*/
fun set(color: Cvec): Cvec {
- this.vec = color.vec
- return this
- }
-
- fun set(vec: FloatVector): Cvec {
- this.vec = vec
- return this
- }
-
- fun set(scalar: Float): Cvec {
- this.vec = FloatVector.broadcast(SPECIES_128, scalar)
+ this.r = color.r
+ this.g = color.g
+ this.b = color.b
+ this.a = color.a
return this
}
@@ -124,7 +115,10 @@ class Cvec {
* @return this color.
*/
fun mul(color: Cvec): Cvec {
- this.vec = this.vec.mul(color.vec)
+ this.r *= color.r
+ this.g *= color.g
+ this.b *= color.b
+ this.a *= color.a
return this
}
@@ -134,7 +128,10 @@ class Cvec {
* @return this color
*/
fun mul(value: Float): Cvec {
- this.vec = this.vec.mul(value)
+ this.r *= value
+ this.g *= value
+ this.b *= value
+ this.a *= value
return this
}
@@ -144,7 +141,10 @@ class Cvec {
* @return this color
*/
fun add(color: Cvec): Cvec {
- this.vec = this.vec.add(color.vec)
+ this.r += color.r
+ this.g += color.g
+ this.b += color.b
+ this.a += color.a
return this
}
@@ -154,12 +154,10 @@ class Cvec {
* @return this color
*/
fun sub(color: Cvec): Cvec {
- this.vec = this.vec.sub(color.vec)
- return this
- }
-
- fun max(color: Cvec): Cvec {
- this.vec = this.vec.max(color.vec)
+ this.r -= color.r
+ this.g -= color.g
+ this.b -= color.b
+ this.a -= color.a
return this
}
@@ -173,7 +171,10 @@ class Cvec {
* @return this Cvec for chaining
*/
operator fun set(r: Float, g: Float, b: Float, a: Float): Cvec {
- vec = FloatVector.fromArray(SPECIES_128, floatArrayOf(r, g, b, a), 0)
+ this.r = r
+ this.g = g
+ this.b = b
+ this.a = a
return this
}
@@ -187,6 +188,96 @@ class Cvec {
return this
}
+ /** Adds the given color component values to this Cvec's values.
+ *
+ * @param r Red component
+ * @param g Green component
+ * @param b Blue component
+ * @param a Alpha component
+ *
+ * @return this Cvec for chaining
+ */
+ fun add(r: Float, g: Float, b: Float, a: Float): Cvec {
+ this.r += r
+ this.g += g
+ this.b += b
+ this.a += a
+ return this
+ }
+
+ /** Subtracts the given values from this Cvec's component values.
+ *
+ * @param r Red component
+ * @param g Green component
+ * @param b Blue component
+ * @param a Alpha component
+ *
+ * @return this Cvec for chaining
+ */
+ fun sub(r: Float, g: Float, b: Float, a: Float): Cvec {
+ this.r -= r
+ this.g -= g
+ this.b -= b
+ this.a -= a
+ return this
+ }
+
+ /** Multiplies this Cvec's color components by the given ones.
+ *
+ * @param r Red component
+ * @param g Green component
+ * @param b Blue component
+ * @param a Alpha component
+ *
+ * @return this Cvec for chaining
+ */
+ fun mul(r: Float, g: Float, b: Float, a: Float): Cvec {
+ this.r *= r
+ this.g *= g
+ this.b *= b
+ this.a *= a
+ return this
+ }
+
+ /** Linearly interpolates between this color and the target color by t which is in the range [0,1]. The result is stored in
+ * this color.
+ * @param target The target color
+ * @param t The interpolation coefficient
+ * @return This color for chaining.
+ */
+ fun lerp(target: Cvec, t: Float): Cvec {
+ this.r += t * (target.r - this.r)
+ this.g += t * (target.g - this.g)
+ this.b += t * (target.b - this.b)
+ this.a += t * (target.a - this.a)
+ return this
+ }
+
+ /** Linearly interpolates between this color and the target color by t which is in the range [0,1]. The result is stored in
+ * this color.
+ * @param r The red component of the target color
+ * @param g The green component of the target color
+ * @param b The blue component of the target color
+ * @param a The alpha component of the target color
+ * @param t The interpolation coefficient
+ * @return This color for chaining.
+ */
+ fun lerp(r: Float, g: Float, b: Float, a: Float, t: Float): Cvec {
+ this.r += t * (r - this.r)
+ this.g += t * (g - this.g)
+ this.b += t * (b - this.b)
+ this.a += t * (a - this.a)
+ return this
+ }
+
+ /** Multiplies the RGB values by the alpha. */
+ fun premultiplyAlpha(): Cvec {
+ r *= a
+ g *= a
+ b *= a
+ return this
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || javaClass != other.javaClass) return false
@@ -226,8 +317,102 @@ class Cvec {
value = "0$value"
return value
}
+
+ /** Sets the RGB Cvec components using the specified Hue-Saturation-Value. Note that HSV components are voluntary not clamped
+ * to preserve high range color and can range beyond typical values.
+ * @param h The Hue in degree from 0 to 360
+ * @param s The Saturation from 0 to 1
+ * @param v The Value (brightness) from 0 to 1
+ * @return The modified Cvec for chaining.
+ */
+ fun fromHsv(h: Float, s: Float, v: Float): Cvec {
+ val x = (h / 60f + 6) % 6
+ val i = x.toInt()
+ val f = x - i
+ val p = v * (1 - s)
+ val q = v * (1 - s * f)
+ val t = v * (1 - s * (1 - f))
+ when (i) {
+ 0 -> {
+ r = v
+ g = t
+ b = p
+ }
+ 1 -> {
+ r = q
+ g = v
+ b = p
+ }
+ 2 -> {
+ r = p
+ g = v
+ b = t
+ }
+ 3 -> {
+ r = p
+ g = q
+ b = v
+ }
+ 4 -> {
+ r = t
+ g = p
+ b = v
+ }
+ else -> {
+ r = v
+ g = p
+ b = q
+ }
+ }
+
+ //return clamp();
+ return this
+ }
+
+ /** Sets RGB components using the specified Hue-Saturation-Value. This is a convenient method for
+ * [.fromHsv]. This is the inverse of [.toHsv].
+ * @param hsv The Hue, Saturation and Value components in that order.
+ * @return The modified Cvec for chaining.
+ */
+ fun fromHsv(hsv: FloatArray): Cvec {
+ return fromHsv(hsv[0], hsv[1], hsv[2])
+ }
+
fun toGdxColor() = Color(r, g, b, a)
+ /** Extract Hue-Saturation-Value. This is the inverse of [.fromHsv].
+ * @param hsv The HSV array to be modified.
+ * @return HSV components for chaining.
+ */
+ fun toHsv(hsv: FloatArray): FloatArray {
+ val max = Math.max(Math.max(r, g), b)
+ val min = Math.min(Math.min(r, g), b)
+ val range = max - min
+ if (range == 0f) {
+ hsv[0] = 0f
+ }
+ else if (max == r) {
+ hsv[0] = (60 * (g - b) / range + 360) % 360
+ }
+ else if (max == g) {
+ hsv[0] = 60 * (b - r) / range + 120
+ }
+ else {
+ hsv[0] = 60 * (r - g) / range + 240
+ }
+
+ if (max > 0) {
+ hsv[1] = 1 - min / max
+ }
+ else {
+ hsv[1] = 0f
+ }
+
+ hsv[2] = max
+
+ return hsv
+ }
+
/** @return a copy of this color
*/
fun cpy(): Cvec {
@@ -289,11 +474,10 @@ class Cvec {
* @param value An integer color value in RGBA8888 format.
*/
fun rgba8888ToCvec(color: Cvec, value: Int) {
- val r = (value and -0x1000000).ushr(24) / 255f
- val g = (value and 0x00ff0000).ushr(16) / 255f
- val b = (value and 0x0000ff00).ushr(8) / 255f
- val a = (value and 0x000000ff) / 255f
- color.vec = FloatVector.fromArray(SPECIES_128, floatArrayOf(r, g, b, a), 0)
+ color.r = (value and -0x1000000).ushr(24) / 255f
+ color.g = (value and 0x00ff0000).ushr(16) / 255f
+ color.b = (value and 0x0000ff00).ushr(8) / 255f
+ color.a = (value and 0x000000ff) / 255f
}
/** Sets the Cvec components using the specified integer value in the format ARGB8888. This is the inverse to the argb8888(a,
@@ -303,11 +487,10 @@ class Cvec {
* @param value An integer color value in ARGB8888 format.
*/
fun argb8888ToCvec(color: Cvec, value: Int) {
- val a = (value and -0x1000000).ushr(24) / 255f
- val r = (value and 0x00ff0000).ushr(16) / 255f
- val g = (value and 0x0000ff00).ushr(8) / 255f
- val b = (value and 0x000000ff) / 255f
- color.vec = FloatVector.fromArray(SPECIES_128, floatArrayOf(r, g, b, a), 0)
+ color.a = (value and -0x1000000).ushr(24) / 255f
+ color.r = (value and 0x00ff0000).ushr(16) / 255f
+ color.g = (value and 0x0000ff00).ushr(8) / 255f
+ color.b = (value and 0x000000ff) / 255f
}
/** Sets the Cvec components using the specified float value in the format ABGB8888.
@@ -315,11 +498,10 @@ class Cvec {
*/
fun abgr8888ToCvec(color: Cvec, value: Float) {
val c = NumberUtils.floatToIntColor(value)
- val a = (c and -0x1000000).ushr(24) / 255f
- val b = (c and 0x00ff0000).ushr(16) / 255f
- val g = (c and 0x0000ff00).ushr(8) / 255f
- val r = (c and 0x000000ff) / 255f
- color.vec = FloatVector.fromArray(SPECIES_128, floatArrayOf(r, g, b, a), 0)
+ color.a = (c and -0x1000000).ushr(24) / 255f
+ color.b = (c and 0x00ff0000).ushr(16) / 255f
+ color.g = (c and 0x0000ff00).ushr(8) / 255f
+ color.r = (c and 0x000000ff) / 255f
}
}
}
diff --git a/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt b/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt
index a695c784f..ca1c36f70 100644
--- a/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt
+++ b/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt
@@ -1,9 +1,6 @@
package net.torvald.gdx.graphics
-import jdk.incubator.vector.FloatVector
import net.torvald.unsafe.UnsafeHelper
-import java.nio.ByteBuffer
-import java.nio.ByteOrder
/**
* Basically just a FloatArray. You may need to re-write the entire code to actually store the Vectors,
@@ -21,9 +18,7 @@ internal class UnsafeCvecArray(val width: Int, val height: Int) {
private inline fun toAddr(x: Int, y: Int) = 4L * (y * width + x)
-// fun isDestroyed() = array.destroyed
-
- private val byteOrder = ByteOrder.nativeOrder()
+ fun isDestroyed() = array.destroyed
init {
zerofill()
@@ -34,65 +29,152 @@ internal class UnsafeCvecArray(val width: Int, val height: Int) {
fun getG(x: Int, y: Int) = array.getFloat(toAddr(x, y) + 1)
fun getB(x: Int, y: Int) = array.getFloat(toAddr(x, y) + 2)
fun getA(x: Int, y: Int) = array.getFloat(toAddr(x, y) + 3)
- inline fun getVec(x: Int, y: Int) = Cvec(getFloatVector(x, y))
- inline fun getFloatVector(x: Int, y: Int): FloatVector {
- val offset = toAddr(x, y)
- val array = floatArrayOf(
- array.getFloat(offset),
- array.getFloat(offset + 1),
- array.getFloat(offset + 2),
- array.getFloat(offset + 3)
- )
- return FloatVector.fromArray(FloatVector.SPECIES_128, array, 0)
- }
- // setters
- fun zerofill() {
- array.fillWith(0)
- }
-// fun setR(x: Int, y: Int, value: Float) { array.putFloat(toAddr(x, y), value) }
-// fun setG(x: Int, y: Int, value: Float) { array.putFloat(toAddr(x, y) + 1, value) }
-// fun setB(x: Int, y: Int, value: Float) { array.putFloat(toAddr(x, y) + 2, value) }
-// fun setA(x: Int, y: Int, value: Float) { array.putFloat(toAddr(x, y) + 3, value) }
- inline fun setVec(x: Int, y: Int, value: Cvec) {
- setFromFloatVector(x, y, value.vec)
- }
+ inline fun getVec(x: Int, y: Int) = Cvec(
+ array.getFloat(toAddr(x, y)),
+ array.getFloat(toAddr(x, y) + 1),
+ array.getFloat(toAddr(x, y) + 2),
+ array.getFloat(toAddr(x, y) + 3)
+ )
+ /**
+ * @param channel 0 for R, 1 for G, 2 for B, 3 for A
+ */
+ fun channelGet(x: Int, y: Int, channel: Int) = array.getFloat(toAddr(x, y) + channel)
- inline fun setFromFloatVector(x: Int, y: Int, value: FloatVector) {
- val offset = toAddr(x, y)
- value.toArray().forEachIndexed { index, fl ->
- array.setFloat(offset + index, fl)
- }
+ // setters
+ fun zerofill() = array.fillWith(0)
+ fun setR(x: Int, y: Int, value: Float) { array.setFloat(toAddr(x, y), value) }
+ fun setG(x: Int, y: Int, value: Float) { array.setFloat(toAddr(x, y) + 1, value) }
+ fun setB(x: Int, y: Int, value: Float) { array.setFloat(toAddr(x, y) + 2, value) }
+ fun setA(x: Int, y: Int, value: Float) { array.setFloat(toAddr(x, y) + 3, value) }
+ inline fun setVec(x: Int, y: Int, value: Cvec) {
+ array.setFloat(toAddr(x, y), value.r)
+ array.setFloat(toAddr(x, y) + 1, value.g)
+ array.setFloat(toAddr(x, y) + 2, value.b)
+ array.setFloat(toAddr(x, y) + 3, value.a)
+ }
+ inline fun setScalar(x: Int, y: Int, value: Float) {
+ array.setFloat(toAddr(x, y), value)
+ array.setFloat(toAddr(x, y) + 1, value)
+ array.setFloat(toAddr(x, y) + 2, value)
+ array.setFloat(toAddr(x, y) + 3, value)
+ }
+ /**
+ * @param channel 0 for R, 1 for G, 2 for B, 3 for A
+ */
+ fun channelSet(x: Int, y: Int, channel: Int, value: Float) {
+ array.setFloat(toAddr(x, y) + channel, value)
}
// operators
inline fun max(x: Int, y: Int, other: Cvec) {
- setFromFloatVector(x, y, getFloatVector(x, y).max(other.vec))
+ setR(x, y, maxOf(getR(x, y), other.r))
+ setG(x, y, maxOf(getG(x, y), other.g))
+ setB(x, y, maxOf(getB(x, y), other.b))
+ setA(x, y, maxOf(getA(x, y), other.a))
}
inline fun mul(x: Int, y: Int, scalar: Float) {
- setFromFloatVector(x, y, getFloatVector(x, y).mul(scalar))
+ setR(x, y, getR(x, y) * scalar)
+ setG(x, y, getG(x, y) * scalar)
+ setB(x, y, getB(x, y) * scalar)
+ setA(x, y, getA(x, y) * scalar)
}
- /*fun mulAndAssign(x: Int, y: Int, scalar: Float) {
+ fun mulAndAssign(x: Int, y: Int, scalar: Float) {
val addr = toAddr(x, y)
for (k in 0..3) {
- array.putFloat(addr + k, (array.getFloat(addr + k) * scalar))
+ array.setFloat(addr + k, (array.getFloat(addr + k) * scalar))
}
}
fun forAllMulAssign(scalar: Float) {
for (i in 0 until TOTAL_SIZE_IN_BYTES / 4) {
- array.putFloat(i, array.getFloat(i) * scalar)
+ array.setFloat(i, array.getFloat(i) * scalar)
}
}
fun forAllMulAssign(vector: Cvec) {
for (i in 0 until TOTAL_SIZE_IN_BYTES / 4 step 4) {
for (k in 0 until 4) {
- array.putFloat(i + 4*k, array.getFloat(i + k) * vector.getElem(k))
+ array.setFloat(i + 4*k, array.getFloat(i + k) * vector.getElem(k))
}
}
- }*/
+ }
fun destroy() = this.array.destroy()
}
+
+
+/**
+ * Safe (and slower) version of UnsafeCvecArray utilised to tackle down the SEGFAULT
+ */
+internal class TestCvecArr(val width: Int, val height: Int) {
+
+ val TOTAL_SIZE_IN_BYTES = 4 * width * height
+
+ val array = FloatArray(TOTAL_SIZE_IN_BYTES)
+
+ private inline fun toAddr(x: Int, y: Int) = 4 * (y * width + x)
+
+ init {
+ zerofill()
+ }
+
+ // getters
+ fun getR(x: Int, y: Int) = array.get(toAddr(x, y))
+ fun getG(x: Int, y: Int) = array.get(toAddr(x, y) + 1)
+ fun getB(x: Int, y: Int) = array.get(toAddr(x, y) + 2)
+ fun getA(x: Int, y: Int) = array.get(toAddr(x, y) + 3)
+ inline fun getVec(x: Int, y: Int) = Cvec(
+ array.get(toAddr(x, y)),
+ array.get(toAddr(x, y) + 1),
+ array.get(toAddr(x, y) + 2),
+ array.get(toAddr(x, y) + 3)
+ )
+ /**
+ * @param channel 0 for R, 1 for G, 2 for B, 3 for A
+ */
+ fun channelGet(x: Int, y: Int, channel: Int) = array.get(toAddr(x, y) + 1 * channel)
+
+ // setters
+ fun zerofill() = array.fill(0f)
+ fun setR(x: Int, y: Int, value: Float) { array.set(toAddr(x, y), value) }
+ fun setG(x: Int, y: Int, value: Float) { array.set(toAddr(x, y) + 1, value) }
+ fun setB(x: Int, y: Int, value: Float) { array.set(toAddr(x, y) + 2, value) }
+ fun setA(x: Int, y: Int, value: Float) { array.set(toAddr(x, y) + 3, value) }
+ inline fun setVec(x: Int, y: Int, value: Cvec) {
+ array.set(toAddr(x, y), value.r)
+ array.set(toAddr(x, y) + 1, value.g)
+ array.set(toAddr(x, y) + 2, value.b)
+ array.set(toAddr(x, y) + 3, value.a)
+ }
+ inline fun setScalar(x: Int, y: Int, value: Float) {
+ array.set(toAddr(x, y), value)
+ array.set(toAddr(x, y) + 1, value)
+ array.set(toAddr(x, y) + 2, value)
+ array.set(toAddr(x, y) + 3, value)
+ }
+ /**
+ * @param channel 0 for R, 1 for G, 2 for B, 3 for A
+ */
+ fun channelSet(x: Int, y: Int, channel: Int, value: Float) {
+ array.set(toAddr(x, y) + 1 * channel, value)
+ }
+
+ // operators
+ inline fun max(x: Int, y: Int, other: Cvec) {
+ setR(x, y, maxOf(getR(x, y), other.r))
+ setG(x, y, maxOf(getG(x, y), other.g))
+ setB(x, y, maxOf(getB(x, y), other.b))
+ setA(x, y, maxOf(getA(x, y), other.a))
+ }
+ inline fun mul(x: Int, y: Int, scalar: Float) {
+ setR(x, y, getR(x, y) * scalar)
+ setG(x, y, getG(x, y) * scalar)
+ setB(x, y, getB(x, y) * scalar)
+ setA(x, y, getA(x, y) * scalar)
+ }
+
+ fun destroy() = {}
+
+}
\ No newline at end of file
diff --git a/src/net/torvald/terrarum/blockproperties/BlockProp.kt b/src/net/torvald/terrarum/blockproperties/BlockProp.kt
index 358178ce0..39e3ac0a4 100644
--- a/src/net/torvald/terrarum/blockproperties/BlockProp.kt
+++ b/src/net/torvald/terrarum/blockproperties/BlockProp.kt
@@ -54,12 +54,12 @@ class BlockProp {
internal var baseLumColG = 0f // base value used to calculate dynamic luminosity
internal var baseLumColB = 0f // base value used to calculate dynamic luminosity
internal var baseLumColA = 0f // base value used to calculate dynamic luminosity
- internal val baseLumCol = Cvec(0f)
+ internal val baseLumCol = Cvec(0)
//var lumColR = 0f // memoised value of dynamic luminosity
//var lumColG = 0f // memoised value of dynamic luminosity
//var lumColB = 0f // memoised value of dynamic luminosity
//var lumColA = 0f // memoised value of dynamic luminosity
- internal val _lumCol = Cvec(0f)
+ internal val _lumCol = Cvec(0)
// X- and Y-value must be treated properly beforehand! (use GameWorld.coerceXY())
fun getLumCol(x: Int, y: Int) = if (dynamicLuminosityFunction == 0) {
baseLumCol
diff --git a/src/net/torvald/terrarum/blockproperties/BlockPropUtil.kt b/src/net/torvald/terrarum/blockproperties/BlockPropUtil.kt
index 134d47c93..60032b32c 100644
--- a/src/net/torvald/terrarum/blockproperties/BlockPropUtil.kt
+++ b/src/net/torvald/terrarum/blockproperties/BlockPropUtil.kt
@@ -137,6 +137,11 @@ object BlockPropUtil {
* @return processed colour
*/
private fun alterBrightnessUniform(data: Cvec, brighten: Float): Cvec {
- return Cvec(data.vec.add(brighten))
+ return Cvec(
+ data.r + brighten,
+ data.g + brighten,
+ data.b + brighten,
+ data.a + brighten
+ )
}
}
\ No newline at end of file
diff --git a/src/net/torvald/terrarum/weather/WeatherMixer.kt b/src/net/torvald/terrarum/weather/WeatherMixer.kt
index 789d2eef2..dbb570b09 100644
--- a/src/net/torvald/terrarum/weather/WeatherMixer.kt
+++ b/src/net/torvald/terrarum/weather/WeatherMixer.kt
@@ -48,7 +48,7 @@ internal object WeatherMixer : RNGConsumer {
lateinit var mixedWeather: BaseModularWeather
- val globalLightNow = Cvec(0f)
+ val globalLightNow = Cvec(0)
// Weather indices
const val WEATHER_GENERIC = "generic"
diff --git a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt
index a77150a16..67604e43d 100644
--- a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt
+++ b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt
@@ -3,8 +3,6 @@ package net.torvald.terrarum.worlddrawer
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
-import jdk.incubator.vector.FloatVector
-import jdk.incubator.vector.FloatVector.SPECIES_128
import net.torvald.gdx.graphics.Cvec
import net.torvald.gdx.graphics.UnsafeCvecArray
import net.torvald.terrarum.*
@@ -367,10 +365,10 @@ object LightmapRenderer {
for (x in lightBoxX.div(TILE_SIZE).floorInt()
..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) {
- val oldLight = lanternMap[LandUtil.getBlockAddr(world, x, y)] ?: Cvec(0f) // if two or more luminous actors share the same block, mix the light
+ val oldLight = lanternMap[LandUtil.getBlockAddr(world, x, y)] ?: Cvec(0) // if two or more luminous actors share the same block, mix the light
val actorLight = colour
- lanternMap[LandUtil.getBlockAddr(world, x, y)] = oldLight.max(actorLight)
+ lanternMap[LandUtil.getBlockAddr(world, x, y)] = oldLight.maxAndAssign(actorLight)
}
}
}
@@ -386,10 +384,10 @@ object LightmapRenderer {
for (x in lightBoxX.div(TILE_SIZE).floorInt()
..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) {
- val oldLight = shadowMap[LandUtil.getBlockAddr(world, x, y)] ?: Cvec(0f) // if two or more luminous actors share the same block, mix the light
+ val oldLight = shadowMap[LandUtil.getBlockAddr(world, x, y)] ?: Cvec(0) // if two or more luminous actors share the same block, mix the light
val actorLight = colour
- shadowMap[LandUtil.getBlockAddr(world, x, y)] = oldLight.max(actorLight)
+ shadowMap[LandUtil.getBlockAddr(world, x, y)] = oldLight.maxAndAssign(actorLight)
}
}
}
@@ -435,23 +433,20 @@ object LightmapRenderer {
}*/
// local variables that are made static
- private val sunLight = Cvec(0f)
+ private val sunLight = Cvec(0)
private var _thisTerrain = 0
private var _thisFluid = GameWorld.FluidInfo(Fluid.NULL, 0f)
private var _thisWall = 0
- private var _ambientAccumulator = Cvec(0f)
- private var _reflectanceAccumulator = Cvec(0f)
- private var _thisTileOpacity = Cvec(0f)
- private var _thisTileOpacity2 = Cvec(0f) // thisTileOpacity * sqrt(2)
- private var _fluidAmountToCol = Cvec(0f)
- private var _thisTileLuminosity = Cvec(0f)
+ private val _ambientAccumulator = Cvec(0)
+ private val _reflectanceAccumulator = Cvec(0)
+ private val _thisTileOpacity = Cvec(0)
+ private val _thisTileOpacity2 = Cvec(0) // thisTileOpacity * sqrt(2)
+ private val _fluidAmountToCol = Cvec(0)
+ private val _thisTileLuminosity = Cvec(0)
private var _thisTerrainProp: BlockProp = BlockProp()
private var _thisWallProp: BlockProp = BlockProp()
private var _thisFluidProp: BlockProp = BlockProp()
- private val VECTOR_ZERO = Cvec(0f)
- private val VECTOR_ONE = Cvec(1f)
-
private fun precalculate(rawx: Int, rawy: Int) {
val lx = rawx.convX(); val ly = rawy.convY()
val (worldX, worldY) = world.coerceXY(rawx, rawy)
@@ -496,8 +491,9 @@ object LightmapRenderer {
if (_thisFluid.type != Fluid.NULL) {
_fluidAmountToCol.set(_thisFluid.amount, _thisFluid.amount, _thisFluid.amount, _thisFluid.amount)
+
_thisTileLuminosity.set(_thisTerrainProp.getLumCol(worldX, worldY))
- _thisTileLuminosity.max(_thisFluidProp.getLumCol(worldX, worldY).cpy().mul(_fluidAmountToCol))
+ _thisTileLuminosity.maxAndAssign(_thisFluidProp.getLumCol(worldX, worldY).mul(_fluidAmountToCol))
_mapThisTileOpacity.setVec(lx, ly, _thisTerrainProp.opacity)
_mapThisTileOpacity.max(lx, ly, _thisFluidProp.opacity.mul(_fluidAmountToCol))
}
@@ -509,11 +505,10 @@ object LightmapRenderer {
// blend shade
_mapThisTileOpacity.max(lx, ly, shadowMap[LandUtil.getBlockAddr(world, worldX, worldY)] ?: colourNull)
-// _mapThisTileOpacity2.setR(lx, ly, _mapThisTileOpacity.getR(lx, ly) * 1.41421356f)
-// _mapThisTileOpacity2.setG(lx, ly, _mapThisTileOpacity.getG(lx, ly) * 1.41421356f)
-// _mapThisTileOpacity2.setB(lx, ly, _mapThisTileOpacity.getB(lx, ly) * 1.41421356f)
-// _mapThisTileOpacity2.setA(lx, ly, _mapThisTileOpacity.getA(lx, ly) * 1.41421356f)
- _mapThisTileOpacity2.setFromFloatVector(lx, ly, _mapThisTileOpacity.getFloatVector(lx, ly).mul(1.41421356f))
+ _mapThisTileOpacity2.setR(lx, ly, _mapThisTileOpacity.getR(lx, ly) * 1.41421356f)
+ _mapThisTileOpacity2.setG(lx, ly, _mapThisTileOpacity.getG(lx, ly) * 1.41421356f)
+ _mapThisTileOpacity2.setB(lx, ly, _mapThisTileOpacity.getB(lx, ly) * 1.41421356f)
+ _mapThisTileOpacity2.setA(lx, ly, _mapThisTileOpacity.getA(lx, ly) * 1.41421356f)
// open air || luminous tile backed by sunlight
@@ -523,7 +518,7 @@ object LightmapRenderer {
}
// blend lantern
- _mapLightLevelThis.max(lx, ly, _thisTileLuminosity.max(
+ _mapLightLevelThis.max(lx, ly, _thisTileLuminosity.maxAndAssign(
lanternMap[LandUtil.getBlockAddr(world, worldX, worldY)] ?: colourNull
))
}
@@ -539,16 +534,17 @@ object LightmapRenderer {
// }
// blend nearby 4 lights to get intensity
- _ambientAccumulator.set(0f)
- .max(lightmap.getVec(lx - 1, ly))
- .max(lightmap.getVec(lx + 1, ly))
- .max(lightmap.getVec(lx, ly - 1))
- .max(lightmap.getVec(lx, ly + 1))
+ _ambientAccumulator.set(0)
+ .maxAndAssign(lightmap.getVec(lx - 1, ly))
+ .maxAndAssign(lightmap.getVec(lx + 1, ly))
+ .maxAndAssign(lightmap.getVec(lx, ly - 1))
+ .maxAndAssign(lightmap.getVec(lx, ly + 1))
_thisTerrain = world.getTileFromTerrainRaw(worldX, worldY)
_thisTerrainProp = BlockCodex[world.tileNumberToNameMap[_thisTerrain.toLong()]]
_reflectanceAccumulator.set(App.tileMaker.terrainTileColourMap[_thisTerrainProp.id]!!)
+ _reflectanceAccumulator.a = 0f // temporarily disabled
_reflectanceAccumulator.mul(_thisTerrainProp.reflectance).mul(giScale)
_mapLightLevelThis.max(lx, ly, _reflectanceAccumulator)
@@ -561,34 +557,26 @@ object LightmapRenderer {
private fun _swipeTask(x: Int, y: Int, x2: Int, y2: Int, lightmap: UnsafeCvecArray) {
if (x2 < 0 || y2 < 0 || x2 >= LIGHTMAP_WIDTH || y2 >= LIGHTMAP_HEIGHT) return
-// _ambientAccumulator.r = _mapLightLevelThis.getR(x, y)
-// _ambientAccumulator.g = _mapLightLevelThis.getG(x, y)
-// _ambientAccumulator.b = _mapLightLevelThis.getB(x, y)
-// _ambientAccumulator.a = _mapLightLevelThis.getA(x, y)
-
- _ambientAccumulator = _mapLightLevelThis.getVec(x, y)
+ _ambientAccumulator.r = _mapLightLevelThis.getR(x, y)
+ _ambientAccumulator.g = _mapLightLevelThis.getG(x, y)
+ _ambientAccumulator.b = _mapLightLevelThis.getB(x, y)
+ _ambientAccumulator.a = _mapLightLevelThis.getA(x, y)
if (!swipeDiag) {
-// _thisTileOpacity.r = _mapThisTileOpacity.getR(x, y)
-// _thisTileOpacity.g = _mapThisTileOpacity.getG(x, y)
-// _thisTileOpacity.b = _mapThisTileOpacity.getB(x, y)
-// _thisTileOpacity.a = _mapThisTileOpacity.getA(x, y)
-// _ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity, lightmap))
- _thisTileOpacity = _mapThisTileOpacity.getVec(x, y)
- _ambientAccumulator = _ambientAccumulator.max(darkenColoured(x2, y2, _thisTileOpacity, lightmap))
+ _thisTileOpacity.r = _mapThisTileOpacity.getR(x, y)
+ _thisTileOpacity.g = _mapThisTileOpacity.getG(x, y)
+ _thisTileOpacity.b = _mapThisTileOpacity.getB(x, y)
+ _thisTileOpacity.a = _mapThisTileOpacity.getA(x, y)
+ _ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity, lightmap))
}
else {
-// _thisTileOpacity2.r = _mapThisTileOpacity2.getR(x, y)
-// _thisTileOpacity2.g = _mapThisTileOpacity2.getG(x, y)
-// _thisTileOpacity2.b = _mapThisTileOpacity2.getB(x, y)
-// _thisTileOpacity2.a = _mapThisTileOpacity2.getA(x, y)
-// _ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity2, lightmap))
- _thisTileOpacity2 = _mapThisTileOpacity2.getVec(x, y)
- _ambientAccumulator = _ambientAccumulator.max(darkenColoured(x2, y2, _thisTileOpacity2, lightmap))
+ _thisTileOpacity2.r = _mapThisTileOpacity2.getR(x, y)
+ _thisTileOpacity2.g = _mapThisTileOpacity2.getG(x, y)
+ _thisTileOpacity2.b = _mapThisTileOpacity2.getB(x, y)
+ _thisTileOpacity2.a = _mapThisTileOpacity2.getA(x, y)
+ _ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity2, lightmap))
}
-// _mapLightLevelThis.setVec(x, y, _ambientAccumulator)
-// lightmap.setVec(x, y, _ambientAccumulator)
_mapLightLevelThis.setVec(x, y, _ambientAccumulator)
lightmap.setVec(x, y, _ambientAccumulator)
}
@@ -623,9 +611,9 @@ object LightmapRenderer {
var lightBuffer: Pixmap = Pixmap(64, 64, Pixmap.Format.RGBA8888) // must not be too small
- private val colourNull = Cvec(0f)
+ private val colourNull = Cvec(0)
private val gdxColorNull = Color(0)
- val epsilon = FloatVector.broadcast(SPECIES_128, 1f / 1024f)
+ const val epsilon = 1f/1024f
private var _lightBufferAsTex: Texture = Texture(64, 64, Pixmap.Format.RGBA8888) // must not be too small
@@ -659,10 +647,10 @@ object LightmapRenderer {
val arrayX = x.convX()
val arrayY = y.convY()
- val red = lightmap.getR(arrayX, arrayY).let { if (it.isFinite()) it else 0f }
- val grn = lightmap.getG(arrayX, arrayY).let { if (it.isFinite()) it else 0f }
- val blu = lightmap.getB(arrayX, arrayY).let { if (it.isFinite()) it else 0f }
- val uvl = lightmap.getA(arrayX, arrayY).let { if (it.isFinite()) it else 0f }
+ val red = lightmap.getR(arrayX, arrayY)
+ val grn = lightmap.getG(arrayX, arrayY)
+ val blu = lightmap.getB(arrayX, arrayY)
+ val uvl = lightmap.getA(arrayX, arrayY)
val redw = (red.sqrt() - 1f) * (7f / 24f)
val grnw = (grn.sqrt() - 1f)
val bluw = (blu.sqrt() - 1f) * (7f / 72f)
@@ -678,21 +666,13 @@ object LightmapRenderer {
0
)
else
- /*lightBuffer.drawPixel(
+ lightBuffer.drawPixel(
x - this_x_start,
lightBuffer.height - 1 - y + this_y_start, // flip Y
(maxOf(red,grnw,bluw,uvlwr) * solidMultMagic).hdnorm().times(255f).roundToInt().shl(24) or
(maxOf(redw,grn,bluw,uvlwg) * solidMultMagic).hdnorm().times(255f).roundToInt().shl(16) or
(maxOf(redw,grnw,blu,uvlwb) * solidMultMagic).hdnorm().times(255f).roundToInt().shl(8) or
(maxOf(bluwv,uvl) * solidMultMagic).hdnorm().times(255f).roundToInt()
- )*/
- lightBuffer.drawPixel(
- x - this_x_start,
- lightBuffer.height - 1 - y + this_y_start, // flip Y
- (red * solidMultMagic).hdnorm().times(255f).roundToInt().shl(24) or
- (grn * solidMultMagic).hdnorm().times(255f).roundToInt().shl(16) or
- (blu * solidMultMagic).hdnorm().times(255f).roundToInt().shl(8) or
- (uvl * solidMultMagic).hdnorm().times(255f).roundToInt()
)
}
}
@@ -740,15 +720,25 @@ object LightmapRenderer {
if (x !in 0 until LIGHTMAP_WIDTH || y !in 0 until LIGHTMAP_HEIGHT) return colourNull
- /*return Cvec(
+ return Cvec(
lightmap.getR(x, y) * (1f - darken.r * lightScalingMagic),
lightmap.getG(x, y) * (1f - darken.g * lightScalingMagic),
lightmap.getB(x, y) * (1f - darken.b * lightScalingMagic),
lightmap.getA(x, y) * (1f - darken.a * lightScalingMagic)
- )*/
- return Cvec(lightmap.getFloatVector(x, y).mul(
- VECTOR_ONE.vec.sub(darken.vec.mul(lightScalingMagic))
- ))
+ )
+
+ }
+
+ /** infix is removed to clarify the association direction */
+ private fun Cvec.maxAndAssign(other: Cvec): Cvec {
+ // TODO investigate: if I use assignment instead of set(), it blackens like the vector branch. --Torvald, 2019-06-07
+ // that was because you forgot 'this.r/g/b/a = ' part, bitch. --Torvald, 2019-06-07
+ this.r = if (this.r > other.r) this.r else other.r
+ this.g = if (this.g > other.g) this.g else other.g
+ this.b = if (this.b > other.b) this.b else other.b
+ this.a = if (this.a > other.a) this.a else other.a
+
+ return this
}
private fun Float.inv() = 1f / this
@@ -821,7 +811,10 @@ object LightmapRenderer {
inline fun Float.hdnorm() = hdr(this.coerceIn(0f, 1f))
- private fun Cvec.nonZero() = epsilon.lt(this.vec.abs()).anyTrue()
+ private fun Cvec.nonZero() = this.r.abs() > epsilon ||
+ this.g.abs() > epsilon ||
+ this.b.abs() > epsilon ||
+ this.a.abs() > epsilon
val histogram: Histogram
get() {