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 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.direction.Directions
import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.RenderWindow 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.models.unbaked.UnbakedModel
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture 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.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.vec2.Vec2iUtil.toVec2iN
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotateAssign
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.util.KUtil.toBoolean import de.bixilon.minosoft.util.KUtil.toBoolean
import de.bixilon.minosoft.util.KUtil.toInt import de.bixilon.minosoft.util.KUtil.toInt
import de.bixilon.minosoft.util.KUtil.toResourceLocation import de.bixilon.minosoft.util.KUtil.toResourceLocation
import de.bixilon.minosoft.util.KUtil.unsafeCast import de.bixilon.minosoft.util.KUtil.unsafeCast
import glm_.func.rad import glm_.func.rad
import glm_.mat4x4.Mat4
import glm_.vec2.Vec2 import glm_.vec2.Vec2
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
import glm_.vec3.Vec3 import glm_.vec3.Vec3
import glm_.vec4.Vec4 import glm_.vec3.swizzle.xz
import glm_.vec4.swizzle.xyz import kotlin.collections.Map
import glm_.vec4.swizzle.xz 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( data class UnbakedBlockStateModel(
val model: UnbakedBlockModel, val model: UnbakedBlockModel,
@ -47,8 +60,10 @@ data class UnbakedBlockStateModel(
val uvLock: Boolean, val uvLock: Boolean,
val weight: Int, val weight: Int,
) : UnbakedModel { ) : UnbakedModel {
var baked: BakedBlockModel? = null
override fun bake(renderWindow: RenderWindow): BakedBlockModel { override fun bake(renderWindow: RenderWindow): BakedBlockModel {
baked?.let { return it }
val textureArray = renderWindow.textureManager.staticTextures val textureArray = renderWindow.textureManager.staticTextures
val resolvedTextures: MutableMap<String, AbstractTexture> = mutableMapOf() val resolvedTextures: MutableMap<String, AbstractTexture> = mutableMapOf()
@ -85,37 +100,41 @@ data class UnbakedBlockStateModel(
for (face in element.faces) { for (face in element.faces) {
val texture = resolvedTextures[face.texture.removePrefix("#")]!! // ToDo: Allow direct texture names? val texture = resolvedTextures[face.texture.removePrefix("#")]!! // ToDo: Allow direct texture names?
val positions = face.direction.getPositions(element.from, element.to) val positions = face.direction.getPositions(element.from, element.to)
val rotationMatrix = Mat4()
element.rotation?.let { 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 { rotation?.let {
rotationMatrix.rotateAssign(-rotation.y.rad, Vec3(0.0f, 1.0f, 0.0f)) val rad = it.rad
rotationMatrix.rotateAssign(-rotation.x.rad, Vec3(1.0f, 0.0f, 0.0f))
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) var texturePositions = arrayOf(
for ((index, position) in positions.withIndex()) {
positions[index] = (rotationMatrix * Vec4(position - 0.5f, 1.0f)).xyz + 0.5f
}
val texturePositions = arrayOf(
Vec2(face.uvEnd.x, face.uvStart.y), Vec2(face.uvEnd.x, face.uvStart.y),
face.uvStart, face.uvStart,
Vec2(face.uvStart.x, face.uvEnd.y), Vec2(face.uvStart.x, face.uvEnd.y),
face.uvEnd, 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) { if (this.uvLock && this.rotation != null && face.direction.axis != Axes.Z) {
val matrix = Mat4() var rad = this.rotation[face.direction.axis].rad
//matrix.rotateAssign(this.rotation.x.rad, Vec3(1,0,0)) if (direction.negative) {
val rotationVec3 = Vec3(this.rotation, 0.0f) rad = -rad
val angle = rotationVec3[face.direction.axis] }
matrix.rotateAssign(-angle.rad, direction.vectorf)
//matrix.rotateAssign(this.rotation.x.rad, Vec3(0,1,0))
for ((index, position) in texturePositions.withIndex()) { 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() finalFaces[index] = faceArray.toTypedArray()
} }
return BakedBlockStateModel(finalFaces.unsafeCast()) val baked = BakedBlockStateModel(finalFaces.unsafeCast())
this.baked = baked
return baked
} }
companion object { companion object {
@ -152,6 +173,5 @@ data class UnbakedBlockStateModel(
} }
fun <T> Array<T>.rotateLeft(n: Int) = drop(n) + take(n) 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 import glm_.vec3.Vec3
data class UnbakedElementRotation( data class UnbakedElementRotation(
val origin: Vec3?, val origin: Vec3,
val axis: Axes, val axis: Axes,
val angle: Float, val angle: Float,
val rescale: Boolean, val rescale: Boolean,
@ -29,7 +29,7 @@ data class UnbakedElementRotation(
operator fun invoke(data: Map<String, Any>): UnbakedElementRotation { operator fun invoke(data: Map<String, Any>): UnbakedElementRotation {
return 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()], axis = Axes[data["axis"].toString()],
angle = data["angle"].toFloat(), angle = data["angle"].toFloat(),
rescale = data["rescale"]?.toBoolean() ?: false, rescale = data["rescale"]?.toBoolean() ?: false,

View File

@ -13,7 +13,10 @@
package de.bixilon.minosoft.gui.rendering.util.vec.vec2 package de.bixilon.minosoft.gui.rendering.util.vec.vec2
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.util.KUtil.toInt import de.bixilon.minosoft.util.KUtil.toInt
import glm_.func.rad
import glm_.vec2.Vec2
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
object Vec2iUtil { object Vec2iUtil {
@ -57,6 +60,17 @@ object Vec2iUtil {
return this.x > other.x || this.y > other.y 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 { fun Any?.toVec2i(default: Vec2i? = null): Vec2i {
return toVec2iN() ?: default ?: throw IllegalArgumentException("Not a Vec2i: $this") 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) 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) val result = Vec2(x * cos - y * sin, x * sin + y * cos)
if (rescale) { if (rescale) {
return result / cos 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) { if (angle == 0.0f) {
return return
} }
when (axis) { when (axis) {
Axes.X -> this.yz = rotate(this.y, this.z, angle.sin, angle.cos, rescale) Axes.X -> this.yz = rotateAssign(this.y, this.z, angle.sin, angle.cos, rescale)
Axes.Y -> this.xz = rotate(this.x, 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 = rotate(this.x, this.y, 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 { operator fun <T : Number> Vec3t<T>.get(axis: Axes): T {
return when (axis) { return when (axis) {