From 083ff2b466eee04b8473d22220d34fb86aa204b5 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sun, 1 Mar 2020 04:14:54 +0900 Subject: [PATCH] initial test, ~40% of the performance was achieved --- .idea/misc.xml | 2 +- src/net/torvald/gdx/graphics/Cvec.kt | 519 ++---------------- .../torvald/gdx/graphics/UnsafeCvecArray.kt | 48 +- src/net/torvald/terrarum/GdxColorMap.kt | 2 +- .../terrarum/blockproperties/BlockCodex.kt | 2 +- .../terrarum/blockproperties/BlockProp.kt | 12 +- .../terrarum/blockproperties/BlockPropUtil.kt | 13 +- .../gameactors/ActorHumanoid.kt | 8 +- .../gameactors/ProjectileSimple.kt | 2 +- .../modulebasegame/weather/WeatherMixer.kt | 6 +- .../terrarum/ui/BasicDebugInfoWindow.kt | 8 +- .../worlddrawer/LightmapRendererNew.kt | 237 ++------ 12 files changed, 151 insertions(+), 708 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index df5a15f37..19568e289 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -38,7 +38,7 @@ - + \ No newline at end of file diff --git a/src/net/torvald/gdx/graphics/Cvec.kt b/src/net/torvald/gdx/graphics/Cvec.kt index 0812895eb..6cbf36e3e 100644 --- a/src/net/torvald/gdx/graphics/Cvec.kt +++ b/src/net/torvald/gdx/graphics/Cvec.kt @@ -16,487 +16,80 @@ 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.VectorOperators +import kotlin.math.roundToInt /** * 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. * + * -XX:+UseVectorApiIntrinsics --add-modules=jdk.incubator.vector + * * Before then, the code will be identical to LibGdx's. */ +inline class Cvec constructor(val vec: FloatVector) { -/** A color class, holding the r, g, b and alpha component as floats in the range [0,1]. All methods perform clamping on the - * internal values after execution. - * - * @author mzechner - */ -class Cvec { + constructor(floatArray: FloatArray) : this(FloatVector.fromArray(SPECIES, floatArray, 0)) + constructor(r: Float, g: Float, b: Float, a: Float) : this(FloatVector.fromValues(SPECIES, r, g, b, a)) + constructor(scalar: Float) : this(FloatVector.fromValues(SPECIES, scalar, scalar, scalar, scalar)) + constructor() : this(FloatVector.zero(SPECIES)) + constructor(rgba8888: Int) : this(FloatVector.fromValues(SPECIES, + ((rgba8888 ushr 24) and 0xff) / 255f, + ((rgba8888 ushr 16) and 0xff) / 255f, + ((rgba8888 ushr 8) and 0xff) / 255f, + (rgba8888 and 0xff) / 255f + )) - /** the red, green, blue and alpha components */ - var r: Float = 0.toFloat() - var g: Float = 0.toFloat() - var b: Float = 0.toFloat() - var a: Float = 0.toFloat() - - /** Constructs a new Cvec with all components set to 0. */ - constructor() {} - - /** @see .rgba8888ToCvec - */ - constructor(rgba8888: Int) { - rgba8888ToCvec(this, rgba8888) + companion object { + private val EPSILON = 1f / 1024f + private val SPECIES = FloatVector.SPECIES_128 } - constructor(color: Color) { - this.r = color.r - this.g = color.g - this.b = color.b - this.a = color.a - } + //fun cpy(): Cvec = Cvec(this.vec) - /** Constructor, sets the components of the color - * - * @param r the red component - * @param g the green component - * @param b the blue component - * @param a the alpha component - */ - constructor(r: Float, g: Float, b: Float, a: Float) { - this.r = r - this.g = g - this.b = b - this.a = a - } + // not using shorthand names to prevent confusion with builtin functions - /** Constructs a new color using the given color - * - * @param color the color - */ - constructor(color: Cvec) { - set(color) + fun multiply(other: FloatVector) = Cvec(vec.mul(other)) + infix operator fun times(other: Cvec) = multiply(other.vec) + //infix operator fun times(scalar: Float) = Cvec(vec.mul(scalar)) + + fun subtract(other: FloatVector) = Cvec(vec.sub(other)) + infix operator fun minus(other: Cvec) = subtract(other.vec) + //infix operator fun minus(scalar: Float) = Cvec(vec.sub(scalar)) + + fun addition(other: FloatVector) = Cvec(vec.add(other)) + infix operator fun plus(other: Cvec) = addition(other.vec) + //infix operator fun plus(scalar: Float) = Cvec(vec.add(scalar)) + + fun maximum(other: FloatVector): Cvec = Cvec(vec.max(other)) + infix fun max(other: Cvec): Cvec = maximum(other.vec) + + fun lerp(target: Cvec, t: Float): Cvec { + return Cvec(t) * (target - this) } /** - * Get RGBA Element using index, of which: - * - 0: R - * - 1: G - * - 2: B - * - 3: A + * true if at least one element in the vector is not zero. */ - fun getElem(index: Int) = when(index) { - 0 -> r - 1 -> g - 2 -> b - 3 -> a - else -> throw IndexOutOfBoundsException("Invalid index $index") + fun nonZero(): Boolean = vec.reduceLanes(VectorOperators.MUL) != 0f //vec.toArray().fold(false) { acc, fl -> acc or (fl.absoluteValue >= EPSILON) } + + fun toRGBA8888(): Int { + var acc = 0 + for (i in 0..3) + acc += vec.lane(i).coerceIn(0f, 1f).times(255f).roundToInt().shl(8 * (3 - i)) + + return acc } - /** Sets this color to the given color. - * - * @param color the Cvec - */ - fun set(color: Cvec): Cvec { - this.r = color.r - this.g = color.g - this.b = color.b - this.a = color.a - return this - } + /*override fun equals(other: Any?): Boolean { + return this.vec.equal((other as Cvec).vec).allTrue() + }*/ - /** Multiplies the this color and the given color - * - * @param color the color - * @return this color. - */ - fun mul(color: Cvec): Cvec { - this.r *= color.r - this.g *= color.g - this.b *= color.b - this.a *= color.a - return this - } - - /** Multiplies all components of this Cvec with the given value. - * - * @param value the value - * @return this color - */ - fun mul(value: Float): Cvec { - this.r *= value - this.g *= value - this.b *= value - this.a *= value - return this - } - - /** Adds the given color to this color. - * - * @param color the color - * @return this color - */ - fun add(color: Cvec): Cvec { - this.r += color.r - this.g += color.g - this.b += color.b - this.a += color.a - return this - } - - /** Subtracts the given color from this color - * - * @param color the color - * @return this color - */ - fun sub(color: Cvec): Cvec { - this.r -= color.r - this.g -= color.g - this.b -= color.b - this.a -= color.a - return this - } - - /** Sets 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 - */ - operator fun set(r: Float, g: Float, b: Float, a: Float): Cvec { - this.r = r - this.g = g - this.b = b - this.a = a - return this - } - - /** Sets this color's component values through an integer representation. - * - * @return this Cvec for chaining - * @see .rgba8888ToCvec - */ - fun set(rgba: Int): Cvec { - rgba8888ToCvec(this, rgba) - 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(o: Any?): Boolean { - if (this === o) return true - if (o == null || javaClass != o.javaClass) return false - val color = o as Cvec? - return toIntBits() == color!!.toIntBits() - } - - override fun hashCode(): Int { - var result = if (r != +0.0f) NumberUtils.floatToIntBits(r) else 0 - result = 31 * result + if (g != +0.0f) NumberUtils.floatToIntBits(g) else 0 - result = 31 * result + if (b != +0.0f) NumberUtils.floatToIntBits(b) else 0 - result = 31 * result + if (a != +0.0f) NumberUtils.floatToIntBits(a) else 0 - return result - } - - /** Packs the color components into a 32-bit integer with the format ABGR and then converts it to a float. Alpha is compressed - * from 0-255 to 0-254 to avoid using float bits in the NaN range (see [NumberUtils.intToFloatColor]). - * @return the packed color as a 32-bit float - */ - fun toFloatBits(): Float { - val color = (255 * a).toInt() shl 24 or ((255 * b).toInt() shl 16) or ((255 * g).toInt() shl 8) or (255 * r).toInt() - return NumberUtils.intToFloatColor(color) - } - - /** Packs the color components into a 32-bit integer with the format ABGR. - * @return the packed color as a 32-bit int. - */ - fun toIntBits(): Int { - return (255 * a).toInt() shl 24 or ((255 * b).toInt() shl 16) or ((255 * g).toInt() shl 8) or (255 * r).toInt() - } - - /** Returns the color encoded as hex string with the format RRGGBBAA. */ - override fun toString(): String { - var value = Integer - .toHexString((255 * r).toInt() shl 24 or ((255 * g).toInt() shl 16) or ((255 * b).toInt() shl 8) or (255 * a).toInt()) - while (value.length < 8) - 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 { - return Cvec(this) - } - - companion object { - val WHITE = Cvec(1f, 1f, 1f, 1f) - - /** Returns a new color from a hex string with the format RRGGBBAA. - * @see .toString - */ - fun valueOf(hex: String): Cvec { - var hex = hex - hex = if (hex[0] == '#') hex.substring(1) else hex - val r = Integer.valueOf(hex.substring(0, 2), 16) - val g = Integer.valueOf(hex.substring(2, 4), 16) - val b = Integer.valueOf(hex.substring(4, 6), 16) - val a = if (hex.length != 8) 255 else Integer.valueOf(hex.substring(6, 8), 16) - return Cvec(r / 255f, g / 255f, b / 255f, a / 255f) - } - - /** Packs the color components into a 32-bit integer with the format ABGR. Note that no range checking is performed for higher - * performance. - * @param r the red component, 0 - 255 - * @param g the green component, 0 - 255 - * @param b the blue component, 0 - 255 - * @param a the alpha component, 0 - 255 - * @return the packed color as a 32-bit int - */ - fun toIntBits(r: Int, g: Int, b: Int, a: Int): Int { - return a shl 24 or (b shl 16) or (g shl 8) or r - } - - fun alpha(alpha: Float): Int { - return (alpha * 255.0f).toInt() - } - - fun rgba8888(r: Float, g: Float, b: Float, a: Float): Int { - return (r * 255).toInt() shl 24 or ((g * 255).toInt() shl 16) or ((b * 255).toInt() shl 8) or (a * 255).toInt() - } - - fun argb8888(a: Float, r: Float, g: Float, b: Float): Int { - return (a * 255).toInt() shl 24 or ((r * 255).toInt() shl 16) or ((g * 255).toInt() shl 8) or (b * 255).toInt() - } - - fun rgba8888(color: Cvec): Int { - return (color.r * 255).toInt() shl 24 or ((color.g * 255).toInt() shl 16) or ((color.b * 255).toInt() shl 8) or (color.a * 255).toInt() - } - - fun argb8888(color: Cvec): Int { - return (color.a * 255).toInt() shl 24 or ((color.r * 255).toInt() shl 16) or ((color.g * 255).toInt() shl 8) or (color.b * 255).toInt() - } - - /** Sets the Cvec components using the specified integer value in the format RGBA8888. This is inverse to the rgba8888(r, g, - * b, a) method. - * - * @param color The Cvec to be modified. - * @param value An integer color value in RGBA8888 format. - */ - fun rgba8888ToCvec(color: Cvec, value: Int) { - 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, - * r, g, b) method - * - * @param color The Cvec to be modified. - * @param value An integer color value in ARGB8888 format. - */ - fun argb8888ToCvec(color: Cvec, value: Int) { - 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. - * @param color The Cvec to be modified. - */ - fun abgr8888ToCvec(color: Cvec, value: Float) { - val c = NumberUtils.floatToIntColor(value) - 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 - } - } + fun toGdxColor() = com.badlogic.gdx.graphics.Color( + vec.lane(0), + vec.lane(1), + vec.lane(2), + vec.lane(3) + ) } diff --git a/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt b/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt index 2c15ccece..9c2ae471a 100644 --- a/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt +++ b/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt @@ -12,11 +12,13 @@ import net.torvald.UnsafeHelper */ internal class UnsafeCvecArray(val width: Int, val height: Int) { - val TOTAL_SIZE_IN_BYTES = 16L * width * height + val sizeof = 16L + + val TOTAL_SIZE_IN_BYTES = sizeof * width * height val array = UnsafeHelper.allocate(TOTAL_SIZE_IN_BYTES) - private inline fun toAddr(x: Int, y: Int) = 16L * (y * width + x) + private inline fun toAddr(x: Int, y: Int) = sizeof * (y * width + x) fun zerofill() = array.fillWith(0) @@ -24,35 +26,21 @@ internal class UnsafeCvecArray(val width: Int, val height: Int) { zerofill() } - fun getR(x: Int, y: Int) = array.getFloat(toAddr(x, y)) - fun getG(x: Int, y: Int) = array.getFloat(toAddr(x, y) + 4) - fun getB(x: Int, y: Int) = array.getFloat(toAddr(x, y) + 8) - fun getA(x: Int, y: Int) = array.getFloat(toAddr(x, y) + 12) - - 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) + 4, value) } - fun setB(x: Int, y: Int, value: Float) { array.setFloat(toAddr(x, y) + 8, value) } - fun setA(x: Int, y: Int, value: Float) { array.setFloat(toAddr(x, y) + 12, value) } - - fun addA(x: Int, y: Int, value: Float) { array.setFloat(toAddr(x, y) + 12, getA(x, y) + value) } - - /** - * @param channel 0 for R, 1 for G, 2 for B, 3 for A - */ - inline fun channelSet(x: Int, y: Int, channel: Int, value: Float) { - array.setFloat(toAddr(x, y) + 4L * channel, value) + fun getVec(x: Int, y: Int): Cvec { + val addr = toAddr(x, y) + return Cvec( + array.getFloat(addr), + array.getFloat(addr + 4), + array.getFloat(addr + 8), + array.getFloat(addr + 12) + ) } - - /** - * @param channel 0 for R, 1 for G, 2 for B, 3 for A - */ - inline fun channelGet(x: Int, y: Int, channel: Int) = array.getFloat(toAddr(x, y) + 4L * channel) - - 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)) + fun setVec(x: Int, y: Int, value: Cvec) { + val addr = toAddr(x, y) + array.setFloat(addr, value.vec.lane(0)) + array.setFloat(addr + 4, value.vec.lane(1)) + array.setFloat(addr + 8, value.vec.lane(2)) + array.setFloat(addr + 12, value.vec.lane(3)) } fun destroy() = this.array.destroy() diff --git a/src/net/torvald/terrarum/GdxColorMap.kt b/src/net/torvald/terrarum/GdxColorMap.kt index a46a67de7..341163adf 100644 --- a/src/net/torvald/terrarum/GdxColorMap.kt +++ b/src/net/torvald/terrarum/GdxColorMap.kt @@ -75,7 +75,7 @@ class GdxColorMap { fun getRaw(x: Int, y: Int): RGBA8888 = dataRaw[y * width + x] fun getRaw(x: Int): RGBA8888 = if (is2D) throw UnsupportedOperationException("This is 2D color map") else dataRaw[x] - //fun getAsCvec(x: Int, y: Int): Cvec = dataCvec[y * width + x] + //fun getAsCvec(x: Int, y: Int): Cvec = dataCvec[y * width + x] // for some reason it just returns zero override fun toString(): String { val sb = StringBuilder() diff --git a/src/net/torvald/terrarum/blockproperties/BlockCodex.kt b/src/net/torvald/terrarum/blockproperties/BlockCodex.kt index c3244c980..51544623e 100644 --- a/src/net/torvald/terrarum/blockproperties/BlockCodex.kt +++ b/src/net/torvald/terrarum/blockproperties/BlockCodex.kt @@ -147,7 +147,7 @@ object BlockCodex { prop.baseLumColG = floatVal(record, "lumg") / LightmapRenderer.MUL_FLOAT prop.baseLumColB = floatVal(record, "lumb") / LightmapRenderer.MUL_FLOAT prop.baseLumColA = floatVal(record, "lumuv") / LightmapRenderer.MUL_FLOAT - prop.baseLumCol.set(prop.baseLumColR, prop.baseLumColG, prop.baseLumColB, prop.baseLumColA) + prop.baseLumCol = Cvec(prop.baseLumColR, prop.baseLumColG, prop.baseLumColB, prop.baseLumColA) prop.friction = intVal(record, "fr") prop.viscosity = intVal(record, "vscs") diff --git a/src/net/torvald/terrarum/blockproperties/BlockProp.kt b/src/net/torvald/terrarum/blockproperties/BlockProp.kt index 4b2de07f0..befbb48db 100644 --- a/src/net/torvald/terrarum/blockproperties/BlockProp.kt +++ b/src/net/torvald/terrarum/blockproperties/BlockProp.kt @@ -20,7 +20,7 @@ class BlockProp { var shadeColB = 0f var shadeColA = 0f - lateinit var opacity: Cvec + var opacity: Cvec = Cvec(0f) fun getOpacity(channel: Int) = when (channel) { 0 -> shadeColR @@ -51,12 +51,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(0) + internal var baseLumCol = Cvec(0f) //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(0) + internal var _lumCol = Cvec(0f) // X- and Y-value must be treated properly beforehand! (use GameWorld.coerceXY()) fun getLumCol(x: Int, y: Int) = if (dynamicLuminosityFunction == 0) { baseLumCol @@ -65,12 +65,6 @@ class BlockProp { BlockCodex[BlockCodex.dynamicToVirtualMap[id]!! - offset]._lumCol } - fun getLumCol(x: Int, y: Int, channel: Int): Float = if (dynamicLuminosityFunction == 0) { - baseLumCol.getElem(channel) - } else { - val offset = XXHash32.hash(((x and 0xFFFF).shl(16) or (y and 0xFFFF)).toLittle(), 10000).fmod(BlockCodex.DYNAMIC_RANDOM_CASES) - BlockCodex[BlockCodex.dynamicToVirtualMap[id]!! - offset]._lumCol.getElem(channel) - } /** * @param luminosity diff --git a/src/net/torvald/terrarum/blockproperties/BlockPropUtil.kt b/src/net/torvald/terrarum/blockproperties/BlockPropUtil.kt index 5ec5626fb..401a8fee8 100644 --- a/src/net/torvald/terrarum/blockproperties/BlockPropUtil.kt +++ b/src/net/torvald/terrarum/blockproperties/BlockPropUtil.kt @@ -95,7 +95,7 @@ object BlockPropUtil { prop.rngBase2 = getNewRandom() } - prop._lumCol.set(getDynamicLumFunc(prop)) + prop._lumCol = getDynamicLumFunc(prop) //prop.lumColR = prop.lumCol.r //prop.lumColG = prop.lumCol.g //prop.lumColB = prop.lumCol.b @@ -111,8 +111,8 @@ object BlockPropUtil { private fun getDynamicLumFunc(prop: BlockProp): Cvec { return when (prop.dynamicLuminosityFunction) { 1 -> getTorchFlicker(prop) - 2 -> (Terrarum.ingame!!.world).globalLight.cpy().mul(LightmapRenderer.DIV_FLOAT) // current global light - 3 -> WeatherMixer.getGlobalLightOfTime(Terrarum.ingame!!.world, WorldTime.DAY_LENGTH / 2).cpy().mul(LightmapRenderer.DIV_FLOAT) // daylight at noon + 2 -> (Terrarum.ingame!!.world).globalLight * LightmapRenderer.DIV_FLOAT_VEC // current global light + 3 -> WeatherMixer.getGlobalLightOfTime(Terrarum.ingame!!.world, WorldTime.DAY_LENGTH / 2) * LightmapRenderer.DIV_FLOAT_VEC // daylight at noon 4 -> getSlowBreath(prop) 5 -> getPulsate(prop) else -> prop.baseLumCol @@ -141,11 +141,6 @@ object BlockPropUtil { * @return processed colour */ private fun alterBrightnessUniform(data: Cvec, brighten: Float): Cvec { - return Cvec( - data.r + brighten, - data.g + brighten, - data.b + brighten, - data.a + brighten - ) + return data + Cvec(brighten) } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt index da0d6d70b..8cbe103ec 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt @@ -74,10 +74,10 @@ open class ActorHumanoid( (actorValue.getAsFloat(AVKey.LUMA) ?: 0f) / LightmapRenderer.MUL_FLOAT ) set(value) { - actorValue[AVKey.LUMR] = value.r * LightmapRenderer.MUL_FLOAT - actorValue[AVKey.LUMG] = value.g * LightmapRenderer.MUL_FLOAT - actorValue[AVKey.LUMB] = value.b * LightmapRenderer.MUL_FLOAT - actorValue[AVKey.LUMA] = value.a * LightmapRenderer.MUL_FLOAT + actorValue[AVKey.LUMR] = value.vec.lane(0) * LightmapRenderer.MUL_FLOAT + actorValue[AVKey.LUMG] = value.vec.lane(1) * LightmapRenderer.MUL_FLOAT + actorValue[AVKey.LUMB] = value.vec.lane(2) * LightmapRenderer.MUL_FLOAT + actorValue[AVKey.LUMA] = value.vec.lane(3) * LightmapRenderer.MUL_FLOAT } /** diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/ProjectileSimple.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/ProjectileSimple.kt index c4425de6e..bd8f44b47 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/ProjectileSimple.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/ProjectileSimple.kt @@ -33,7 +33,7 @@ open class ProjectileSimple( override var color: Cvec - get() = (bulletDatabase[type][OFFSET_LUMINOSITY] as Cvec).cpy() + get() = (bulletDatabase[type][OFFSET_LUMINOSITY] as Cvec) set(value) { } /** diff --git a/src/net/torvald/terrarum/modulebasegame/weather/WeatherMixer.kt b/src/net/torvald/terrarum/modulebasegame/weather/WeatherMixer.kt index 5b6362b44..2890c5850 100644 --- a/src/net/torvald/terrarum/modulebasegame/weather/WeatherMixer.kt +++ b/src/net/torvald/terrarum/modulebasegame/weather/WeatherMixer.kt @@ -48,7 +48,7 @@ internal object WeatherMixer : RNGConsumer { lateinit var mixedWeather: BaseModularWeather - val globalLightNow = Cvec(0) + var globalLightNow = Cvec(0f) // Weather indices const val WEATHER_GENERIC = "generic" @@ -133,7 +133,7 @@ internal object WeatherMixer : RNGConsumer { // calculate global light val globalLight = getGradientColour(world, skyboxColourMap, 2, timeNow) - globalLightNow.set(globalLight) + globalLightNow = globalLight /* (copied from the shader source) @@ -250,7 +250,7 @@ internal object WeatherMixer : RNGConsumer { " | ${colourThis.toStringRGB()} -[${scale.times(100).toInt()}%]-> ${colourNext.toStringRGB()}" + " | * `$r`$g`$b`")*/ - return Cvec(newCol) + return Cvec(newCol.r, newCol.g, newCol.b, newCol.a) } fun getWeatherList(classification: String) = weatherList[classification]!! diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 392c543d6..0a8cd0364 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -146,10 +146,10 @@ class BasicDebugInfoWindow : UICanvas() { val mtX = mouseTileX.toString() val mtY = mouseTileY.toString() val valRaw = LightmapRenderer.getLight(mouseTileX, mouseTileY) - val rawR = valRaw?.r?.times(100f)?.round()?.div(100f) - val rawG = valRaw?.g?.times(100f)?.round()?.div(100f) - val rawB = valRaw?.b?.times(100f)?.round()?.div(100f) - val rawA = valRaw?.a?.times(100f)?.round()?.div(100f) + val rawR = valRaw?.vec?.lane(0)?.times(100f)?.round()?.div(100f) + val rawG = valRaw?.vec?.lane(1)?.times(100f)?.round()?.div(100f) + val rawB = valRaw?.vec?.lane(2)?.times(100f)?.round()?.div(100f) + val rawA = valRaw?.vec?.lane(3)?.times(100f)?.round()?.div(100f) lightVal = if (valRaw == null) "$EMDASH" else "$rawR $rawG $rawB $rawA" diff --git a/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt b/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt index 434e0d9b0..7a47ac1ef 100644 --- a/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt +++ b/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt @@ -122,7 +122,9 @@ object LightmapRenderer { const val CHANNEL_MAX_FLOAT = CHANNEL_MAX.toFloat() const val COLOUR_RANGE_SIZE = MUL * MUL_2 const val MUL_FLOAT = MUL / 256f + val MUL_FLOAT_VEC = Cvec(MUL_FLOAT) const val DIV_FLOAT = 256f / MUL + val DIV_FLOAT_VEC = Cvec(DIV_FLOAT) internal var for_x_start = 0 internal var for_y_start = 0 @@ -159,12 +161,7 @@ object LightmapRenderer { val x = x.convX() val y = y.convY() - return Cvec( - lightmap.getR(x, y) * MUL_FLOAT, - lightmap.getG(x, y) * MUL_FLOAT, - lightmap.getB(x, y) * MUL_FLOAT, - lightmap.getA(x, y) * MUL_FLOAT - ) + return lightmap.getVec(x, y) * MUL_FLOAT_VEC } } @@ -221,7 +218,7 @@ object LightmapRenderer { */ // set sunlight - sunLight.set(world.globalLight); sunLight.mul(DIV_FLOAT) + sunLight = world.globalLight * DIV_FLOAT_VEC // set no-op mask from solidity of the block AppLoader.measureDebugTime("Renderer.LightNoOpMask") { @@ -506,7 +503,7 @@ object LightmapRenderer { * * @return true if skip */ - private fun radiate(channel: Int, wx: Int, wy: Int, lightsource: Cvec, distSqr: Int): Boolean { + /*private fun radiate(channel: Int, wx: Int, wy: Int, lightsource: Cvec, distSqr: Int): Boolean { val lx = wx.convX(); val ly = wy.convY() if (lx !in 0 until LIGHTMAP_WIDTH || ly !in 0 until LIGHTMAP_HEIGHT) @@ -537,28 +534,25 @@ object LightmapRenderer { if (inNoopMask(worldX, worldY)) return false // just quick snippets to make test work - lightLevelThis.set(colourNull) - thisTileOpacity.set(BlockCodex[world.getTileFromTerrain(worldX, worldY)].opacity) + thisTileOpacity = BlockCodex[world.getTileFromTerrain(worldX, worldY)].opacity val x = worldX.convX() val y = worldY.convY() - /* + *///lightLevelThis.maxAndAssign(darkenColoured(x - 1, y - 1, thisTileOpacity2)) - /* + *///lightLevelThis.maxAndAssign(darkenColoured(x + 1, y - 1, thisTileOpacity2)) - /* + *///lightLevelThis.maxAndAssign(darkenColoured(x - 1, y + 1, thisTileOpacity2)) - /* + *///lightLevelThis.maxAndAssign(darkenColoured(x + 1, y + 1, thisTileOpacity2)) - /* * */lightLevelThis.maxAndAssign(darkenColoured(x, y - 1, thisTileOpacity)) - /* * */lightLevelThis.maxAndAssign(darkenColoured(x, y + 1, thisTileOpacity)) - /* * */lightLevelThis.maxAndAssign(darkenColoured(x - 1, y, thisTileOpacity)) - /* * */lightLevelThis.maxAndAssign(darkenColoured(x + 1, y, thisTileOpacity)) + lightLevelThis = lightLevelThis max + /* + *///darkenColoured(x - 1, y - 1, thisTileOpacity2) max + /* + *///darkenColoured(x + 1, y - 1, thisTileOpacity2) max + /* + *///darkenColoured(x - 1, y + 1, thisTileOpacity2) max + /* + *///darkenColoured(x + 1, y + 1, thisTileOpacity2) max + /* * */darkenColoured(x, y - 1, thisTileOpacity) max + /* * */darkenColoured(x, y + 1, thisTileOpacity) max + /* * */darkenColoured(x - 1, y, thisTileOpacity) max + /* * */darkenColoured(x + 1, y, thisTileOpacity) - lightmap.setR(x, y, lightLevelThis.r) - lightmap.setG(x, y, lightLevelThis.g) - lightmap.setB(x, y, lightLevelThis.b) - lightmap.setA(x, y, lightLevelThis.a) + lightmap.setVec(x, y, lightLevelThis) return false - } + }*/ // TODO re-init at every resize @@ -677,12 +671,12 @@ object LightmapRenderer { private val ambientAccumulator = Cvec(0f,0f,0f,0f) - private val lightLevelThis = Cvec(0) - private val fluidAmountToCol = Cvec(0) - private val thisTileLuminosity = Cvec(0) - private val thisTileOpacity = Cvec(0) - private val thisTileOpacity2 = Cvec(0) // thisTileOpacity * sqrt(2) - private val sunLight = Cvec(0) + private var lightLevelThis = Cvec(0f) + private var fluidAmountToCol = Cvec(0f) + private var thisTileLuminosity = Cvec(0f) + private var thisTileOpacity = Cvec(0f) + private var thisTileOpacity2 = Cvec(0f) // thisTileOpacity * sqrt(2) + private var sunLight = Cvec(0f) private var thisFluid = GameWorld.FluidInfo(Fluid.NULL, 0f) private var thisTerrain = 0 private var thisWall = 0 @@ -694,6 +688,8 @@ object LightmapRenderer { private var thisTileOpacityCh = 0f private var thisTileOpacity2Ch = 0f + private val SQRT2_VEC = Cvec(1.41421356f) + /** * This function will alter following variables: * - lightLevelThis @@ -708,7 +704,7 @@ object LightmapRenderer { private fun getLightsAndShades(x: Int, y: Int) { val (x, y) = world.coerceXY(x, y) - lightLevelThis.set(colourNull) + lightLevelThis = colourNull thisTerrain = world.getTileFromTerrainRaw(x, y) thisFluid = world.getFluid(x, y) thisWall = world.getTileFromWallRaw(x, y) @@ -736,84 +732,29 @@ object LightmapRenderer { } if (thisFluid.type != Fluid.NULL) { - fluidAmountToCol.set(thisFluid.amount, thisFluid.amount, thisFluid.amount, thisFluid.amount) + fluidAmountToCol = Cvec(thisFluid.amount) - thisTileLuminosity.set(BlockCodex[thisTerrain].getLumCol(x, y)) - thisTileLuminosity.maxAndAssign(BlockCodex[thisFluid.type].getLumCol(x, y).mul(fluidAmountToCol)) // already been div by four - thisTileOpacity.set(BlockCodex[thisTerrain].opacity) - thisTileOpacity.maxAndAssign(BlockCodex[thisFluid.type].opacity.mul(fluidAmountToCol)) // already been div by four + thisTileLuminosity = BlockCodex[thisTerrain].getLumCol(x, y) max + (BlockCodex[thisFluid.type].getLumCol(x, y) * fluidAmountToCol) // already been div by four + thisTileOpacity = BlockCodex[thisTerrain].opacity max + (BlockCodex[thisFluid.type].opacity * fluidAmountToCol) // already been div by four } else { - thisTileLuminosity.set(BlockCodex[thisTerrain].getLumCol(x, y)) - thisTileOpacity.set(BlockCodex[thisTerrain].opacity) + thisTileLuminosity = BlockCodex[thisTerrain].getLumCol(x, y) + thisTileOpacity = BlockCodex[thisTerrain].opacity } - thisTileOpacity2.set(thisTileOpacity); thisTileOpacity2.mul(1.41421356f) + thisTileOpacity2 = thisTileOpacity * SQRT2_VEC //sunLight.set(world.globalLight); sunLight.mul(DIV_FLOAT) // moved to fireRecalculateEvent() // open air || luminous tile backed by sunlight if ((thisTerrain == AIR && thisWall == AIR) || (thisTileLuminosity.nonZero() && thisWall == AIR)) { - lightLevelThis.set(sunLight) + lightLevelThis = sunLight } // blend lantern - lightLevelThis.maxAndAssign(thisTileLuminosity).maxAndAssign(lanternMap[LandUtil.getBlockAddr(world, x, y)] ?: colourNull) - } - - private fun getLightsAndShadesCh(x: Int, y: Int, channel: Int) { - lightLevelThisCh = 0f - thisTerrain = world.getTileFromTerrain(x, y) ?: Block.STONE - thisFluid = world.getFluid(x, y) - thisWall = world.getTileFromWall(x, y) ?: Block.STONE - - // regarding the issue #26 - try { - val fuck = BlockCodex[thisTerrain].getLumCol(x, y) - } - catch (e: NullPointerException) { - System.err.println("## NPE -- x: $x, y: $y, value: $thisTerrain") - e.printStackTrace() - // create shitty minidump - System.err.println("MINIMINIDUMP START") - for (xx in x - 16 until x + 16) { - val raw = world.getTileFromTerrain(xx, y) - val lsb = raw.and(0xff).toString(16).padStart(2, '0') - val msb = raw.ushr(8).and(0xff).toString(16).padStart(2, '0') - System.err.print(lsb) - System.err.print(msb) - System.err.print(" ") - } - System.err.println("\nMINIMINIDUMP END") - - exitProcess(1) - } - - if (thisFluid.type != Fluid.NULL) { - fluidAmountToColCh = thisFluid.amount - - thisTileLuminosityCh = BlockCodex[thisTerrain].getLumCol(x, y, channel) - thisTileLuminosityCh = maxOf(BlockCodex[thisFluid.type].getLumCol(x, y, channel) * fluidAmountToColCh, thisTileLuminosityCh) // already been div by four - thisTileOpacityCh = BlockCodex[thisTerrain].getOpacity(channel) - thisTileOpacityCh = maxOf(BlockCodex[thisFluid.type].getOpacity(channel) * fluidAmountToColCh, thisTileOpacityCh) // already been div by four - } - else { - thisTileLuminosityCh = BlockCodex[thisTerrain].getLumCol(x, y, channel) - thisTileOpacityCh = BlockCodex[thisTerrain].getOpacity(channel) - } - - thisTileOpacity2Ch = thisTileOpacityCh * 1.41421356f - //sunLight.set(world.globalLight); sunLight.mul(DIV_FLOAT) // moved to fireRecalculateEvent() - - - // open air || luminous tile backed by sunlight - if ((thisTerrain == AIR && thisWall == AIR) || (thisTileLuminosityCh > epsilon && thisWall == AIR)) { - lightLevelThisCh = sunLight.getElem(channel) - } - - // blend lantern - lightLevelThisCh = maxOf(thisTileLuminosityCh, lightLevelThisCh) - lightLevelThisCh = maxOf(lanternMap[LandUtil.getBlockAddr(world, x, y)]?.getElem(channel) ?: 0f, lightLevelThisCh) + lightLevelThis = lightLevelThis max thisTileLuminosity max (lanternMap[LandUtil.getBlockAddr(world, x, y)] ?: colourNull) } private val inNoopMaskp = Point2i(0,0) @@ -888,70 +829,35 @@ object LightmapRenderer { // will "overwrite" what's there in the lightmap if it's the first pass // takes about 2 ms on 6700K - /* + */lightLevelThis.maxAndAssign(darkenColoured(x - 1, y - 1, thisTileOpacity2)) - /* + */lightLevelThis.maxAndAssign(darkenColoured(x + 1, y - 1, thisTileOpacity2)) - /* + */lightLevelThis.maxAndAssign(darkenColoured(x - 1, y + 1, thisTileOpacity2)) - /* + */lightLevelThis.maxAndAssign(darkenColoured(x + 1, y + 1, thisTileOpacity2)) - /* * */lightLevelThis.maxAndAssign(darkenColoured(x, y - 1, thisTileOpacity)) - /* * */lightLevelThis.maxAndAssign(darkenColoured(x, y + 1, thisTileOpacity)) - /* * */lightLevelThis.maxAndAssign(darkenColoured(x - 1, y, thisTileOpacity)) - /* * */lightLevelThis.maxAndAssign(darkenColoured(x + 1, y, thisTileOpacity)) + lightLevelThis = lightLevelThis max + /* + */darkenColoured(x - 1, y - 1, thisTileOpacity2) max + /* + */darkenColoured(x + 1, y - 1, thisTileOpacity2) max + /* + */darkenColoured(x - 1, y + 1, thisTileOpacity2) max + /* + */darkenColoured(x + 1, y + 1, thisTileOpacity2) max + /* * */darkenColoured(x, y - 1, thisTileOpacity) max + /* * */darkenColoured(x, y + 1, thisTileOpacity) max + /* * */darkenColoured(x - 1, y, thisTileOpacity) max + /* * */darkenColoured(x + 1, y, thisTileOpacity) //return lightLevelThis.cpy() // it HAS to be a cpy(), otherwise all cells gets the same instance //setLightOf(lightmap, x, y, lightLevelThis.cpy()) - lightmap.setR(x, y, lightLevelThis.r) - lightmap.setG(x, y, lightLevelThis.g) - lightmap.setB(x, y, lightLevelThis.b) - lightmap.setA(x, y, lightLevelThis.a) + lightmap.setVec(x, y, lightLevelThis) } - // per-channel version is slower... - private fun calculateAndAssignCh(lightmap: UnsafeCvecArray, worldX: Int, worldY: Int, channel: Int) { - - if (inNoopMask(worldX, worldY)) return - - // O(9n) == O(n) where n is a size of the map - - getLightsAndShadesCh(worldX, worldY, channel) - - val x = worldX.convX() - val y = worldY.convY() - - // calculate ambient - /* + * + 0 4 1 - * * @ * 6 @ 7 - * + * + 2 5 3 - * sample ambient for eight points and apply attenuation for those - * maxblend eight values and use it - */ - - // will "overwrite" what's there in the lightmap if it's the first pass - // takes about 2 ms on 6700K - /* + *///lightLevelThis.maxAndAssign(darkenColoured(x - 1, y - 1, thisTileOpacity2)) - /* + *///lightLevelThis.maxAndAssign(darkenColoured(x + 1, y - 1, thisTileOpacity2)) - /* + *///lightLevelThis.maxAndAssign(darkenColoured(x - 1, y + 1, thisTileOpacity2)) - /* + *///lightLevelThis.maxAndAssign(darkenColoured(x + 1, y + 1, thisTileOpacity2)) - - lightLevelThisCh = maxOf(darken(x, y - 1, thisTileOpacityCh, channel), lightLevelThisCh) - lightLevelThisCh = maxOf(darken(x, y + 1, thisTileOpacityCh, channel), lightLevelThisCh) - lightLevelThisCh = maxOf(darken(x - 1, y, thisTileOpacityCh, channel), lightLevelThisCh) - lightLevelThisCh = maxOf(darken(x + 1, y, thisTileOpacityCh, channel), lightLevelThisCh) - - lightmap.channelSet(x, y, channel, lightLevelThisCh) - } - - private fun isSolid(x: Int, y: Int): Float? { // ...so that they wouldn't appear too dark + private val SOLIDMULTMAGIC_FALSE = Cvec(1f) + private val SOLIDMULTMAGIC_TRUE = Cvec(1.2f) + private fun isSolid(x: Int, y: Int): Cvec? { // ...so that they wouldn't appear too dark if (!inBounds(x, y)) return null // brighten if solid - return if (BlockCodex[world.getTileFromTerrain(x, y)].isSolid) 1.2f else 1f + return if (BlockCodex[world.getTileFromTerrain(x, y)].isSolid) SOLIDMULTMAGIC_TRUE else SOLIDMULTMAGIC_FALSE } var lightBuffer: Pixmap = Pixmap(1, 1, Pixmap.Format.RGBA8888) - private val colourNull = Cvec(0) + private val colourNull = Cvec(0f) private val gdxColorNull = Color(0) private const val epsilon = 1f/1024f @@ -990,12 +896,7 @@ object LightmapRenderer { val color = if (solidMultMagic == null) gdxColorNull else - Color( - lightmap.getR(arrayX, arrayY) * solidMultMagic, - lightmap.getG(arrayX, arrayY) * solidMultMagic, - lightmap.getB(arrayX, arrayY) * solidMultMagic, - lightmap.getA(arrayX, arrayY) * solidMultMagic - ).normaliseToHDR() + lightmap.getVec(arrayX, arrayY).times(solidMultMagic).toGdxColor().normaliseToHDR() lightBuffer.setColor(color) @@ -1028,7 +929,8 @@ object LightmapRenderer { lightmap.destroy() } - private const val lightScalingMagic = 8f + private val lightScalingMagic = Cvec(8f) + private val CVEC_ONE = Cvec(1f) /** * Subtract each channel's RGB value. @@ -1050,30 +952,7 @@ object LightmapRenderer { if (x !in 0 until LIGHTMAP_WIDTH || y !in 0 until LIGHTMAP_HEIGHT) return colourNull - 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) - ) - - } - - private fun darken(x: Int, y: Int, darken: Float, channel: Int): Float { - if (x !in 0 until LIGHTMAP_WIDTH || y !in 0 until LIGHTMAP_HEIGHT) return 0f - return lightmap.channelGet(x, y, channel) * (1f - darken * 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 + return lightmap.getVec(x, y) * (CVEC_ONE - darken * lightScalingMagic) } private fun Float.inv() = 1f / this @@ -1142,11 +1021,6 @@ object LightmapRenderer { hdr(this.a.coerceIn(0f, 1f)) ) - private fun Cvec.nonZero() = this.r.abs() > epsilon || - this.g.abs() > epsilon || - this.b.abs() > epsilon || - this.a.abs() > epsilon - val histogram: Histogram get() { val reds = IntArray(MUL) // reds[intensity] ← counts @@ -1226,6 +1100,5 @@ object LightmapRenderer { } } -fun Cvec.toRGBA() = (255 * r).toInt() shl 24 or ((255 * g).toInt() shl 16) or ((255 * b).toInt() shl 8) or (255 * a).toInt() fun Color.toRGBA() = (255 * r).toInt() shl 24 or ((255 * g).toInt() shl 16) or ((255 * b).toInt() shl 8) or (255 * a).toInt()