rendering: bugfix and code quality improvements

This commit is contained in:
Lukas 2021-03-01 21:53:34 +01:00
parent 66c918d20e
commit 07654ca1ab
4 changed files with 81 additions and 62 deletions

View File

@ -18,7 +18,6 @@ import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import glm_.glm
import glm_.vec2.Vec2
import glm_.vec3.Vec3
open class BlockModelElement(data: JsonObject) {
@ -34,7 +33,6 @@ open class BlockModelElement(data: JsonObject) {
VecUtil.jsonToVec3(it)
} ?: Vec3(BLOCK_RESOLUTION)
positions = arrayOf(
Vec3(from),
Vec3(to.x, from.y, from.z),
@ -52,12 +50,14 @@ open class BlockModelElement(data: JsonObject) {
val rescale = it["rescale"]?.asBoolean ?: false
rotatePositions(positions, axis, angle, VecUtil.jsonToVec3(it["origin"].asJsonArray), rescale)
}
data["faces"]?.asJsonObject?.let {
for ((directionName, json) in it.entrySet()) {
val direction = Directions.valueOf(directionName.toUpperCase())
faces[direction] = BlockModelFace(json.asJsonObject, from, to, direction)
}
}
for ((i, position) in positions.withIndex()) {
positions[i] = transformPosition(position)
}
@ -76,48 +76,6 @@ open class BlockModelElement(data: JsonObject) {
intArrayOf(5, 1, 3, 7)
)
private val POSITION_1 = Vec3(-0.5f, -0.5f, -0.5f) // Vec3(0, 0, 0)
private val POSITION_2 = Vec3(+0.5f, -0.5f, -0.5f) // Vec3(BLOCK_RESOLUTION, 0, 0)
private val POSITION_3 = Vec3(-0.5f, -0.5f, +0.5f) // Vec3(0, 0, BLOCK_RESOLUTION)
private val POSITION_4 = Vec3(+0.5f, -0.5f, +0.5f) // Vec3(BLOCK_RESOLUTION, 0, BLOCK_RESOLUTION)
private val POSITION_5 = Vec3(-0.5f, +0.5f, -0.5f) // Vec3(0, BLOCK_RESOLUTION, 0)
private val POSITION_6 = Vec3(+0.5f, +0.5f, +0.5f) // Vec3(BLOCK_RESOLUTION, BLOCK_RESOLUTION, 0)
private val POSITION_7 = Vec3(-0.5f, +0.5f, +0.5f) // Vec3(0, BLOCK_RESOLUTION, BLOCK_RESOLUTION)
private val POSITION_8 = Vec3(+0.5f, +0.5f, +0.5f) // Vec3(BLOCK_RESOLUTION, BLOCK_RESOLUTION, BLOCK_RESOLUTION)
val FULL_TEST_POSITIONS = arrayOf(
setOf(POSITION_1, POSITION_2, POSITION_3, POSITION_4),
setOf(POSITION_5, POSITION_6, POSITION_7, POSITION_8),
setOf(POSITION_3, POSITION_4, POSITION_7, POSITION_8),
setOf(POSITION_1, POSITION_2, POSITION_5, POSITION_6),
setOf(POSITION_2, POSITION_4, POSITION_6, POSITION_8),
setOf(POSITION_1, POSITION_3, POSITION_5, POSITION_7)
)
fun getRotatedValues(x: Float, y: Float, sin: Double, cos: Double): Vec2 {
return Vec2((x * cos - y * sin).toFloat(), (x * sin + y * cos).toFloat())
}
fun rotateVector(original: Vec3, angle: Double, axis: Axes): Vec3 {
if (angle == 0.0) {
return original
}
return when (axis) {
Axes.X -> {
val rotatedValues = getRotatedValues(original.y, original.z, glm.sin(angle), glm.cos(angle))
Vec3(original.x, rotatedValues)
}
Axes.Y -> {
val rotatedValues = getRotatedValues(original.x, original.z, glm.sin(angle), glm.cos(angle))
Vec3(rotatedValues.x, original.y, rotatedValues.y)
}
Axes.Z -> {
val rotatedValues = getRotatedValues(original.x, original.y, glm.sin(angle), glm.cos(angle))
Vec3(rotatedValues.x, rotatedValues.y, original.z)
}
}
}
fun rotatePositions(positions: Array<Vec3>, axis: Axes, angle: Double, origin: Vec3, rescale: Boolean) {
// TODO: optimize for 90deg, 180deg, 270deg rotations
if (angle == 0.0) {
@ -125,7 +83,7 @@ open class BlockModelElement(data: JsonObject) {
}
for ((i, position) in positions.withIndex()) {
var transformedPosition = position - origin
transformedPosition = rotateVector(transformedPosition, angle, axis)
transformedPosition = VecUtil.rotateVector(transformedPosition, angle, axis)
if (rescale) {
transformedPosition = transformedPosition / glm.cos(angle)
}

View File

@ -15,18 +15,21 @@ package de.bixilon.minosoft.gui.rendering.chunk.models.loading
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import glm_.Java.Companion.glm
import glm_.vec2.Vec2
import glm_.vec3.Vec3
import java.util.*
class BlockModelFace(data: JsonObject, from: Vec3, to: Vec3, direction: Directions) {
val textureName: String = data.get("texture").asString.removePrefix("#")
class BlockModelFace {
val textureName: String
val cullFace: Directions?
val tint: Boolean = data.has("tintindex")
private var positions: MutableList<Vec2>
val tint: Boolean
private val positions: MutableList<Vec2>
init {
constructor(data: JsonObject, from: Vec3, to: Vec3, direction: Directions) {
tint = data.has("tintindex")
textureName = data.get("texture").asString.removePrefix("#")
var textureStart = Vec2(0, 0)
var textureEnd = Vec2(16, 16)
when (direction) {
@ -64,6 +67,16 @@ class BlockModelFace(data: JsonObject, from: Vec3, to: Vec3, direction: Directio
Collections.rotate(positions, rotation)
}
constructor(parent: BlockModelFace) {
textureName = parent.textureName
cullFace = parent.cullFace
tint = parent.tint
positions = mutableListOf()
for (position in parent.positions) {
positions.add(Vec2(position))
}
}
fun getTexturePositionArray(direction: Directions): Array<Vec2?> {
val template = textureTemplate[direction.ordinal]
val result = arrayOfNulls<Vec2>(template.size)
@ -79,9 +92,9 @@ class BlockModelFace(data: JsonObject, from: Vec3, to: Vec3, direction: Directio
}
val sin = glm.sin(angle)
val cos = glm.cos(angle)
for (i in positions.indices) {
val offset = positions[i] - Vec2(0.5f, 0.5f)
positions[i] = BlockModelElement.getRotatedValues(offset.x, offset.y, sin, cos) + Vec2(0.5f, 0.5f)
for ((i, position) in positions.withIndex()) {
val offset = position - TEXTURE_MIDDLE
positions[i] = VecUtil.getRotatedValues(offset.x, offset.y, sin, cos) + TEXTURE_MIDDLE
}
}
@ -102,5 +115,7 @@ class BlockModelFace(data: JsonObject, from: Vec3, to: Vec3, direction: Directio
arrayOf(2, 3, 0, 1),
arrayOf(1, 0, 3, 2),
)
val TEXTURE_MIDDLE = Vec2(0.5, 0.5)
}
}

View File

@ -26,28 +26,29 @@ import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace
import de.bixilon.minosoft.gui.rendering.textures.Texture
import de.bixilon.minosoft.gui.rendering.textures.TextureArray
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import glm_.Java.Companion.glm
import glm_.mat4x4.Mat4
import glm_.vec2.Vec2
import glm_.vec3.Vec3
import glm_.vec4.Vec4
class ElementRenderer(element: BlockModelElement, val rotation: Vec3, uvLock: Boolean, rescale: Boolean) {
class ElementRenderer(parent: BlockModelElement, val rotation: Vec3, uvLock: Boolean, rescale: Boolean) {
private val fullFaceDirections: MutableSet<Directions> = mutableSetOf()
private val faces: MutableMap<Directions, BlockModelFace> = element.faces.toMutableMap()
private var positions: Array<Vec3> = element.positions.clone()
private val faces: MutableMap<Directions, BlockModelFace> = mutableMapOf()
private var positions: Array<Vec3> = parent.positions.clone()
private val directionMapping: HashBiMap<Directions, Directions> = HashBiMap.create()
init {
rotatePositionsAxes(positions, rotation, rescale)
// TODO : uvLock
for (direction in Directions.DIRECTIONS) {
if (positions.containsAllVectors(BlockModelElement.FULL_TEST_POSITIONS[direction.ordinal], 0.0001f)) { // TODO: check if texture is transparent ==> && ! texture.isTransparent
if (positions.containsAllVectors(FULL_TEST_POSITIONS[direction.ordinal], 0.0001f)) { // TODO: check if texture is transparent ==> && ! texture.isTransparent
fullFaceDirections.add(direction)
}
directionMapping[direction] = getRotatedDirection(rotation, direction)
for (face in faces.values) {
face.rotate(rotation.y.toDouble())
parent.faces[direction]?.let {
faces[direction] = BlockModelFace(it)
}
}
}
@ -144,9 +145,9 @@ class ElementRenderer(element: BlockModelElement, val rotation: Vec3, uvLock: Bo
if (rotation == EMPTY_VECTOR) {
return direction
}
var rotatedDirectionVector = BlockModelElement.rotateVector(direction.directionVector, rotation.z.toDouble(), Axes.Z)
rotatedDirectionVector = BlockModelElement.rotateVector(rotatedDirectionVector, rotation.y.toDouble(), Axes.Y)
return Directions.byDirection(BlockModelElement.rotateVector(rotatedDirectionVector, rotation.x.toDouble(), Axes.X))
var rotatedDirectionVector = VecUtil.rotateVector(direction.directionVector, rotation.x.toDouble(), Axes.X)
rotatedDirectionVector = VecUtil.rotateVector(rotatedDirectionVector, rotation.y.toDouble(), Axes.Y)
return Directions.byDirection(VecUtil.rotateVector(rotatedDirectionVector, rotation.z.toDouble(), Axes.Z))
}
fun rotatePositionsAxes(positions: Array<Vec3>, angles: Vec3, rescale: Boolean) {
@ -157,6 +158,24 @@ class ElementRenderer(element: BlockModelElement, val rotation: Vec3, uvLock: Bo
BlockModelElement.rotatePositions(positions, Axes.Y, angles.y.toDouble(), EMPTY_VECTOR, rescale)
BlockModelElement.rotatePositions(positions, Axes.Z, angles.z.toDouble(), EMPTY_VECTOR, rescale)
}
private val POSITION_1 = Vec3(-0.5f, -0.5f, -0.5f)
private val POSITION_2 = Vec3(+0.5f, -0.5f, -0.5f)
private val POSITION_3 = Vec3(-0.5f, -0.5f, +0.5f)
private val POSITION_4 = Vec3(+0.5f, -0.5f, +0.5f)
private val POSITION_5 = Vec3(-0.5f, +0.5f, -0.5f)
private val POSITION_6 = Vec3(+0.5f, +0.5f, +0.5f)
private val POSITION_7 = Vec3(-0.5f, +0.5f, +0.5f)
private val POSITION_8 = Vec3(+0.5f, +0.5f, +0.5f)
val FULL_TEST_POSITIONS = arrayOf(
setOf(POSITION_1, POSITION_2, POSITION_3, POSITION_4),
setOf(POSITION_5, POSITION_6, POSITION_7, POSITION_8),
setOf(POSITION_3, POSITION_4, POSITION_7, POSITION_8),
setOf(POSITION_1, POSITION_2, POSITION_5, POSITION_6),
setOf(POSITION_2, POSITION_4, POSITION_6, POSITION_8),
setOf(POSITION_1, POSITION_3, POSITION_5, POSITION_7)
)
}
}

View File

@ -16,6 +16,9 @@ package de.bixilon.minosoft.gui.rendering.util
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.Axes
import glm_.glm
import glm_.vec2.Vec2
import glm_.vec3.Vec3
object VecUtil {
@ -27,4 +30,28 @@ object VecUtil {
else -> throw IllegalArgumentException("Not a Vec3!")
}
}
fun getRotatedValues(x: Float, y: Float, sin: Double, cos: Double): Vec2 {
return Vec2((x * cos - y * sin).toFloat(), (x * sin + y * cos).toFloat())
}
fun rotateVector(original: Vec3, angle: Double, axis: Axes): Vec3 {
if (angle == 0.0) {
return original
}
return when (axis) {
Axes.X -> {
val rotatedValues = getRotatedValues(original.y, original.z, glm.sin(angle), glm.cos(angle))
Vec3(original.x, rotatedValues)
}
Axes.Y -> {
val rotatedValues = getRotatedValues(original.x, original.z, glm.sin(angle), glm.cos(angle))
Vec3(rotatedValues.x, original.y, rotatedValues.y)
}
Axes.Z -> {
val rotatedValues = getRotatedValues(original.x, original.y, glm.sin(angle), glm.cos(angle))
Vec3(rotatedValues.x, rotatedValues.y, original.z)
}
}
}
}