mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-16 00:26:07 +09:00
Revert "Light Calculation using JDK Incubator Vector": Vectorising
yields poorer performance
This reverts commit b47549d846.
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() = {}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user