remove rotation matrix, improve model baking speed

This commit is contained in:
Bixilon 2021-11-10 00:13:50 +01:00
parent 958df37f96
commit 81dd2f7535
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
4 changed files with 80 additions and 36 deletions

View File

@ -13,6 +13,7 @@
package de.bixilon.minosoft.gui.rendering.models.unbaked.block
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.RenderWindow
@ -24,22 +25,34 @@ import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedBlockModel
import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.get
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.rad
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.toVec2iN
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.get
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.set
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotateAssign
import de.bixilon.minosoft.util.KUtil.toBoolean
import de.bixilon.minosoft.util.KUtil.toInt
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import de.bixilon.minosoft.util.KUtil.unsafeCast
import glm_.func.rad
import glm_.mat4x4.Mat4
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
import glm_.vec3.Vec3
import glm_.vec4.Vec4
import glm_.vec4.swizzle.xyz
import glm_.vec4.swizzle.xz
import glm_.vec3.swizzle.xz
import kotlin.collections.Map
import kotlin.collections.MutableList
import kotlin.collections.MutableMap
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.drop
import kotlin.collections.iterator
import kotlin.collections.mutableListOf
import kotlin.collections.mutableMapOf
import kotlin.collections.plus
import kotlin.collections.plusAssign
import kotlin.collections.set
import kotlin.collections.take
import kotlin.collections.toTypedArray
import kotlin.collections.withIndex
data class UnbakedBlockStateModel(
val model: UnbakedBlockModel,
@ -47,8 +60,10 @@ data class UnbakedBlockStateModel(
val uvLock: Boolean,
val weight: Int,
) : UnbakedModel {
var baked: BakedBlockModel? = null
override fun bake(renderWindow: RenderWindow): BakedBlockModel {
baked?.let { return it }
val textureArray = renderWindow.textureManager.staticTextures
val resolvedTextures: MutableMap<String, AbstractTexture> = mutableMapOf()
@ -85,37 +100,41 @@ data class UnbakedBlockStateModel(
for (face in element.faces) {
val texture = resolvedTextures[face.texture.removePrefix("#")]!! // ToDo: Allow direct texture names?
val positions = face.direction.getPositions(element.from, element.to)
val rotationMatrix = Mat4()
element.rotation?.let {
rotationMatrix.rotateAssign(it.angle.rad, Vec3.EMPTY.apply { this[it.axis] = 1.0f })
val rad = it.angle.rad
for ((index, position) in positions.withIndex()) {
positions[index] = Vec3(position).apply { rotateAssign(rad, it.axis, it.origin, it.rescale) }
}
}
var direction = face.direction
rotation?.let {
rotationMatrix.rotateAssign(-rotation.y.rad, Vec3(0.0f, 1.0f, 0.0f))
rotationMatrix.rotateAssign(-rotation.x.rad, Vec3(1.0f, 0.0f, 0.0f))
val rad = it.rad
direction = Directions.byDirection(Vec3(face.direction.vectorf).apply { rotateAssign(rad) })
for ((index, position) in positions.withIndex()) {
positions[index] = Vec3(position).apply { rotateAssign(rad) }
}
}
val direction = Directions.byDirection((rotationMatrix * Vec4(face.direction.vectorf, 1.0f)).xyz)
for ((index, position) in positions.withIndex()) {
positions[index] = (rotationMatrix * Vec4(position - 0.5f, 1.0f)).xyz + 0.5f
}
val texturePositions = arrayOf(
var texturePositions = arrayOf(
Vec2(face.uvEnd.x, face.uvStart.y),
face.uvStart,
Vec2(face.uvStart.x, face.uvEnd.y),
face.uvEnd,
).rotateLeft((face.rotation % 360) / 90).toTypedArray()
)
if (face.rotation != 0) {
texturePositions = texturePositions.rotateLeft((face.rotation % 360) / 90).toTypedArray()
}
if (this.uvLock && this.rotation != null) {
val matrix = Mat4()
//matrix.rotateAssign(this.rotation.x.rad, Vec3(1,0,0))
val rotationVec3 = Vec3(this.rotation, 0.0f)
val angle = rotationVec3[face.direction.axis]
matrix.rotateAssign(-angle.rad, direction.vectorf)
//matrix.rotateAssign(this.rotation.x.rad, Vec3(0,1,0))
if (this.uvLock && this.rotation != null && face.direction.axis != Axes.Z) {
var rad = this.rotation[face.direction.axis].rad
if (direction.negative) {
rad = -rad
}
for ((index, position) in texturePositions.withIndex()) {
texturePositions[index] = (matrix * Vec4(position.x - 0.5f, 0.0f, position.y - 0.5f, 0.0f)).xz + 0.5f
texturePositions[index] = (Vec3(position.x - 0.5f, 0.0f, position.y - 0.5f).apply { rotateAssign(rad, direction.axis) }).xz + 0.5f
}
}
@ -138,7 +157,9 @@ data class UnbakedBlockStateModel(
finalFaces[index] = faceArray.toTypedArray()
}
return BakedBlockStateModel(finalFaces.unsafeCast())
val baked = BakedBlockStateModel(finalFaces.unsafeCast())
this.baked = baked
return baked
}
companion object {
@ -152,6 +173,5 @@ data class UnbakedBlockStateModel(
}
fun <T> Array<T>.rotateLeft(n: Int) = drop(n) + take(n)
fun <T> Array<T>.rotateRight(n: Int) = takeLast(n) + dropLast(n)
}
}

View File

@ -20,7 +20,7 @@ import de.bixilon.minosoft.util.KUtil.toFloat
import glm_.vec3.Vec3
data class UnbakedElementRotation(
val origin: Vec3?,
val origin: Vec3,
val axis: Axes,
val angle: Float,
val rescale: Boolean,
@ -29,7 +29,7 @@ data class UnbakedElementRotation(
operator fun invoke(data: Map<String, Any>): UnbakedElementRotation {
return UnbakedElementRotation(
origin = data["origin"]?.toVec3(),
origin = data["origin"]?.toVec3()?.apply { this /= UnbakedElement.BLOCK_RESOLUTION } ?: Vec3(0.5f), // default: center
axis = Axes[data["axis"].toString()],
angle = data["angle"].toFloat(),
rescale = data["rescale"]?.toBoolean() ?: false,

View File

@ -13,7 +13,10 @@
package de.bixilon.minosoft.gui.rendering.util.vec.vec2
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.util.KUtil.toInt
import glm_.func.rad
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
object Vec2iUtil {
@ -57,6 +60,17 @@ object Vec2iUtil {
return this.x > other.x || this.y > other.y
}
val Vec2i.rad: Vec2
get() = Vec2(x.rad, y.rad)
operator fun Vec2i.get(axis: Axes): Int {
return when (axis) {
Axes.X -> x
Axes.Y -> y
Axes.Z -> throw IllegalArgumentException("A Vec2i has no Z coordinate!")
}
}
fun Any?.toVec2i(default: Vec2i? = null): Vec2i {
return toVec2iN() ?: default ?: throw IllegalArgumentException("Not a Vec2i: $this")
}

View File

@ -39,7 +39,7 @@ object Vec3Util {
get() = Vec3(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE)
fun rotate(x: Float, y: Float, sin: Float, cos: Float, rescale: Boolean): Vec2 {
fun rotateAssign(x: Float, y: Float, sin: Float, cos: Float, rescale: Boolean): Vec2 {
val result = Vec2(x * cos - y * sin, x * sin + y * cos)
if (rescale) {
return result / cos
@ -48,17 +48,27 @@ object Vec3Util {
}
fun Vec3.rotate(angle: Float, axis: Axes, rescale: Boolean = false) {
fun Vec3.rotateAssign(angle: Float, axis: Axes, rescale: Boolean = false) {
if (angle == 0.0f) {
return
}
when (axis) {
Axes.X -> this.yz = rotate(this.y, this.z, angle.sin, angle.cos, rescale)
Axes.Y -> this.xz = rotate(this.x, this.z, angle.sin, angle.cos, rescale)
Axes.Z -> this.xy = rotate(this.x, this.y, angle.sin, angle.cos, rescale)
Axes.X -> this.yz = rotateAssign(this.y, this.z, angle.sin, angle.cos, rescale)
Axes.Y -> this.xz = rotateAssign(this.x, this.z, angle.sin, angle.cos, rescale)
Axes.Z -> this.xy = rotateAssign(this.x, this.y, angle.sin, angle.cos, rescale)
}
}
fun Vec3.rotateAssign(rotation: Vec2) {
rotateAssign(rotation.y, Axes.Y)
rotateAssign(rotation.x, Axes.X)
}
fun Vec3.rotateAssign(angle: Float, axis: Axes, origin: Vec3, rescale: Boolean) {
this -= origin
rotateAssign(angle, axis, rescale)
this += origin
}
operator fun <T : Number> Vec3t<T>.get(axis: Axes): T {
return when (axis) {