From 7f78cc1f86970f6c1723ff77015bbf05a574a61a Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Mon, 16 Oct 2023 17:08:17 +0200 Subject: [PATCH] wip skeletal drawing --- .../models/loader/SkeletalLoaderTest.kt | 2 +- .../minosoft/data/direction/DirectionUtil.kt | 14 ++----- .../minosoft/data/direction/Directions.kt | 8 ++-- .../minosoft/gui/rendering/RenderLoader.kt | 1 + .../renderer/storage/DoubleChestRenderer.kt | 2 +- .../renderer/storage/SingleChestRenderer.kt | 2 +- .../rendering/models/loader/ModelLoader.kt | 4 ++ .../rendering/models/loader/SkeletalLoader.kt | 6 +++ .../gui/rendering/skeletal/SkeletalManager.kt | 15 +++----- .../gui/rendering/skeletal/SkeletalShader.kt | 4 +- .../skeletal/baked/BakedSkeletalModel.kt | 14 +++++-- .../skeletal/baked/BakedSkeletalTransform.kt | 14 ++++++- .../skeletal/instance/SkeletalInstance.kt | 30 +++++++++++++-- .../skeletal/instance/TransformInstance.kt | 37 +++++++++++++++++++ .../rendering/skeletal/model/SkeletalModel.kt | 5 ++- 15 files changed, 117 insertions(+), 41 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/TransformInstance.kt diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/loader/SkeletalLoaderTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/loader/SkeletalLoaderTest.kt index 9be3553e1..dde3834b8 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/loader/SkeletalLoaderTest.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/loader/SkeletalLoaderTest.kt @@ -85,6 +85,6 @@ class SkeletalLoaderTest { val baked = loader[dummyModel]!! - assertEquals(baked.transforms, mapOf("body" to BakedSkeletalTransform(1, Vec3(0.0, 0.5, 0.0), mapOf("head" to BakedSkeletalTransform(2, Vec3(0.0, 1.0, 0.0), emptyMap()))))) + assertEquals(baked.transform.children, mapOf("body" to BakedSkeletalTransform(1, Vec3(0.0, 0.5, 0.0), mapOf("head" to BakedSkeletalTransform(2, Vec3(0.0, 1.0, 0.0), emptyMap()))))) } } diff --git a/src/main/java/de/bixilon/minosoft/data/direction/DirectionUtil.kt b/src/main/java/de/bixilon/minosoft/data/direction/DirectionUtil.kt index 653a6810a..5428ee219 100644 --- a/src/main/java/de/bixilon/minosoft/data/direction/DirectionUtil.kt +++ b/src/main/java/de/bixilon/minosoft/data/direction/DirectionUtil.kt @@ -13,11 +13,10 @@ package de.bixilon.minosoft.data.direction -import de.bixilon.kotlinglm.func.rad -import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.kutil.array.ArrayUtil import de.bixilon.minosoft.data.Axes +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY object DirectionUtil { @@ -39,14 +38,7 @@ object DirectionUtil { return Directions.INDEXED[1][ArrayUtil.modifyArrayIndex(index.y + count, Directions.SIZE_SIDES)] } - fun rotateMatrix(direction: Directions): Mat4 { - return when (direction) { - Directions.DOWN -> Mat4().translateAssign(Vec3(0.5f)).rotateAssign(180.0f.rad, Vec3(1, 0, 0)).translateAssign(Vec3(-0.5f)) - Directions.UP -> Mat4().translateAssign(Vec3(0.5f)).rotateAssign((-180.0f).rad, Vec3(1, 0, 0)).translateAssign(Vec3(-0.5f)) // ToDo - Directions.NORTH -> Mat4() - Directions.SOUTH -> Mat4().translateAssign(Vec3(0.5f)).rotateAssign(180.0f.rad, Vec3(0, 1, 0)).translateAssign(Vec3(-0.5f)) - Directions.WEST -> Mat4().translateAssign(Vec3(0.5f)).rotateAssign((-270.0f).rad, Vec3(0, 1, 0)).translateAssign(Vec3(-0.5f)) - Directions.EAST -> Mat4().translateAssign(Vec3(0.5f)).rotateAssign((-90.0f).rad, Vec3(0, 1, 0)).translateAssign(Vec3(-0.5f)) - } + fun getRotation(direction: Directions): Vec3 { + return Vec3.EMPTY // TODO } } diff --git a/src/main/java/de/bixilon/minosoft/data/direction/Directions.kt b/src/main/java/de/bixilon/minosoft/data/direction/Directions.kt index 84fa76506..69fba0185 100644 --- a/src/main/java/de/bixilon/minosoft/data/direction/Directions.kt +++ b/src/main/java/de/bixilon/minosoft/data/direction/Directions.kt @@ -12,7 +12,6 @@ */ package de.bixilon.minosoft.data.direction -import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kotlinglm.vec3.Vec3i @@ -46,7 +45,7 @@ enum class Directions( val vectord = Vec3d(vector) val axis: Axes = unsafeNull() - val rotatedMatrix: Mat4 = unsafeNull() + val rotation: Vec3 = unsafeNull() val inverted: Directions = unsafeNull() private fun invert(): Directions { @@ -170,14 +169,13 @@ enum class Directions( return minDirection } - init { - val rotationMatrix = Directions::rotatedMatrix.javaField!! + val rotation = Directions::rotation.javaField!! val inverted = Directions::inverted.javaField!! val axis = Directions::axis.javaField!! for (direction in VALUES) { inverted.forceSet(direction, direction.invert()) - rotationMatrix.forceSet(direction, DirectionUtil.rotateMatrix(direction)) + rotation.forceSet(direction, DirectionUtil.getRotation(direction)) axis.forceSet(direction, Axes[direction]) } NAME_MAP.unsafeCast>()["bottom"] = DOWN diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderLoader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderLoader.kt index 0a4b33cbc..4c7be4933 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderLoader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderLoader.kt @@ -104,6 +104,7 @@ object RenderLoader { Log.log(LogMessageType.RENDERING, LogLevels.VERBOSE) { "Baking models (after ${stopwatch.labTime()})..." } font.postInit(renderLatch) models.bake(renderLatch) + models.upload() models.cleanup() Log.log(LogMessageType.RENDERING, LogLevels.VERBOSE) { "Post loading renderer (after ${stopwatch.labTime()})..." } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/entities/renderer/storage/DoubleChestRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/entities/renderer/storage/DoubleChestRenderer.kt index 202178e86..3ad2348e1 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/entities/renderer/storage/DoubleChestRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/entities/renderer/storage/DoubleChestRenderer.kt @@ -37,7 +37,7 @@ class DoubleChestRenderer( light: Int, ) : StorageBlockEntityRenderer( blockState, - model.createInstance(context, (blockPosition - context.camera.offset.offset).toVec3, (blockState.getFacing()).rotatedMatrix), + model.createInstance(context, (blockPosition - context.camera.offset.offset).toVec3, (blockState.getFacing()).rotation), light, ) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/entities/renderer/storage/SingleChestRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/entities/renderer/storage/SingleChestRenderer.kt index 3828fecfd..04ed72233 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/entities/renderer/storage/SingleChestRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/entities/renderer/storage/SingleChestRenderer.kt @@ -37,7 +37,7 @@ class SingleChestRenderer( light: Int, ) : StorageBlockEntityRenderer( blockState, - model.createInstance(context, (blockPosition - context.camera.offset.offset).toVec3, blockState.getFacing().rotatedMatrix), + model.createInstance(context, (blockPosition - context.camera.offset.offset).toVec3, blockState.getFacing().rotation), light, ) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/loader/ModelLoader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/loader/ModelLoader.kt index 1378f20db..f3304468f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/loader/ModelLoader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/loader/ModelLoader.kt @@ -60,6 +60,10 @@ class ModelLoader( Log.log(LogMessageType.LOADING, LogLevels.VERBOSE) { "Baked models in ${time.formatNanos()}!" } } + fun upload() { + skeletal.upload() + } + fun cleanup() { block.cleanup() item.cleanup() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/loader/SkeletalLoader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/loader/SkeletalLoader.kt index bb2ebcd1e..ffc131d32 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/loader/SkeletalLoader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/loader/SkeletalLoader.kt @@ -46,6 +46,12 @@ class SkeletalLoader(private val loader: ModelLoader) { } } + fun upload() { + for ((name, baked) in this.baked) { + baked.load() + } + } + fun cleanup() { this::registered.forceSet(null) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/SkeletalManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/SkeletalManager.kt index b3548bdfe..73ff8f94a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/SkeletalManager.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/SkeletalManager.kt @@ -46,20 +46,15 @@ class SkeletalManager( fun draw(instance: SkeletalInstance, light: Int) { prepareDraw() shader.light = light - // val transforms = instance.calculateTransforms() - // var stride = 0 - // for (transform in transforms) { - // for (float in transform.array) { - // uniformBuffer.buffer.put(stride++, float) - // } - // } - // uniformBuffer.upload(0 until (transforms.size * MAT4_SIZE)) + + instance.transform.pack(uniformBuffer.buffer) + uniformBuffer.upload(0 until instance.model.transformCount * MAT4_SIZE) instance.model.mesh.draw() } - private companion object { + companion object { private const val TRANSFORMS = 128 - private const val MAT4_SIZE = 4 * 4 + const val MAT4_SIZE = 4 * 4 } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/SkeletalShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/SkeletalShader.kt index 1882f1298..4363fdd67 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/SkeletalShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/SkeletalShader.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2023 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -23,7 +23,7 @@ import de.bixilon.minosoft.gui.rendering.system.base.buffer.uniform.FloatUniform import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager -class SkeletalShader( +open class SkeletalShader( override val native: NativeShader, buffer: FloatUniformBuffer, ) : Shader(), TextureShader, AnimatedShader, LightShader, ViewProjectionShader, FogShader { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalModel.kt index e8d52af2c..3edad62af 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalModel.kt @@ -13,7 +13,6 @@ package de.bixilon.minosoft.gui.rendering.skeletal.baked -import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalMesh @@ -21,7 +20,8 @@ import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance data class BakedSkeletalModel( val mesh: SkeletalMesh, - val transforms: MutableMap, + val transform: BakedSkeletalTransform, + val transformCount: Int, // TODO: animations ) { private var state = SkeletalModelStates.DECLARED @@ -39,7 +39,13 @@ data class BakedSkeletalModel( state = SkeletalModelStates.UNLOADED } - fun createInstance(context: RenderContext, position: Vec3, transform: Mat4 = Mat4()): SkeletalInstance { - TODO() + + fun createInstance(context: RenderContext, position: Vec3, rotation: Vec3): SkeletalInstance { + val transforms = this.transform.instance() + + val instance = SkeletalInstance(context, this, transforms) + instance.update(position, rotation) + + return instance } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalTransform.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalTransform.kt index 3d7862f2d..edf3b4679 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalTransform.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/baked/BakedSkeletalTransform.kt @@ -14,9 +14,21 @@ package de.bixilon.minosoft.gui.rendering.skeletal.baked import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.minosoft.gui.rendering.skeletal.instance.TransformInstance data class BakedSkeletalTransform( val id: Int, val pivot: Vec3, val children: Map, -) +) { + + fun instance(): TransformInstance { + val children: MutableMap = mutableMapOf() + + for ((name, child) in this.children) { + children[name] = child.instance() + } + + return TransformInstance(id, pivot, children) + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt index 2adc82848..26e8967ba 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt @@ -13,18 +13,42 @@ package de.bixilon.minosoft.gui.rendering.skeletal.instance +import de.bixilon.kotlinglm.mat4x4.Mat4 +import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel class SkeletalInstance( + val context: RenderContext, val model: BakedSkeletalModel, + val transform: TransformInstance, ) { + var light = 0xFF - fun draw(light: Int = 0xFF) { + fun draw() { + context.skeletal.draw(this, light) + } + + fun draw(light: Int) { + this.light = light + context.skeletal.draw(this, light) + } + + fun draw(shader: Shader) { TODO() } - fun draw(shader: Shader? = null) { - TODO() + fun update(position: Vec3, rotation: Vec3) { + val matrix = Mat4() + .translateAssign(Vec3(position - context.camera.offset.offset)) + // .rotateAssign((EntityRotation.HALF_CIRCLE_DEGREE - yaw).rad, Y_ROTATION_VECTOR) + + transform.value = matrix + } + + + companion object { + private val Y_ROTATION_VECTOR = Vec3(0, 1, 0) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/TransformInstance.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/TransformInstance.kt new file mode 100644 index 000000000..7c1e5e0f7 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/TransformInstance.kt @@ -0,0 +1,37 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.skeletal.instance + +import de.bixilon.kotlinglm.mat4x4.Mat4 +import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalManager +import java.nio.FloatBuffer + +class TransformInstance( + val id: Int, + val pivot: Vec3, + val children: Map, +) { + var value = Mat4() + + fun pack(buffer: FloatBuffer) { + pack(buffer, value) + } + + private fun pack(buffer: FloatBuffer, parent: Mat4) { + val value = parent * value + val offset = this.id * SkeletalManager.MAT4_SIZE + buffer.put(value.array, offset, SkeletalManager.MAT4_SIZE) + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/SkeletalModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/SkeletalModel.kt index 06afbf4f0..07970486b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/SkeletalModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/SkeletalModel.kt @@ -64,8 +64,9 @@ data class SkeletalModel( val transforms: MutableMap = mutableMapOf() + val transformId = AtomicInteger(1) for ((name, transform) in this.transforms) { - transforms[name] = transform.bake(AtomicInteger(1)) + transforms[name] = transform.bake(transformId) } val baseTransform = BakedSkeletalTransform(0, Vec3.EMPTY, transforms) @@ -73,6 +74,6 @@ data class SkeletalModel( element.bake(mesh, textures, baseTransform) } - return BakedSkeletalModel(mesh, transforms) + return BakedSkeletalModel(mesh, baseTransform, transformId.get()) } }