wip skeletal drawing

This commit is contained in:
Moritz Zwerger 2023-10-16 17:08:17 +02:00
parent 3159f3dab5
commit 7f78cc1f86
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
15 changed files with 117 additions and 41 deletions

View File

@ -85,6 +85,6 @@ class SkeletalLoaderTest {
val baked = loader[dummyModel]!! 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())))))
} }
} }

View File

@ -13,11 +13,10 @@
package de.bixilon.minosoft.data.direction 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.kotlinglm.vec3.Vec3
import de.bixilon.kutil.array.ArrayUtil import de.bixilon.kutil.array.ArrayUtil
import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
object DirectionUtil { object DirectionUtil {
@ -39,14 +38,7 @@ object DirectionUtil {
return Directions.INDEXED[1][ArrayUtil.modifyArrayIndex(index.y + count, Directions.SIZE_SIDES)] return Directions.INDEXED[1][ArrayUtil.modifyArrayIndex(index.y + count, Directions.SIZE_SIDES)]
} }
fun rotateMatrix(direction: Directions): Mat4 { fun getRotation(direction: Directions): Vec3 {
return when (direction) { return Vec3.EMPTY // TODO
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))
}
} }
} }

View File

@ -12,7 +12,6 @@
*/ */
package de.bixilon.minosoft.data.direction package de.bixilon.minosoft.data.direction
import de.bixilon.kotlinglm.mat4x4.Mat4
import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kotlinglm.vec3.Vec3d
import de.bixilon.kotlinglm.vec3.Vec3i import de.bixilon.kotlinglm.vec3.Vec3i
@ -46,7 +45,7 @@ enum class Directions(
val vectord = Vec3d(vector) val vectord = Vec3d(vector)
val axis: Axes = unsafeNull() val axis: Axes = unsafeNull()
val rotatedMatrix: Mat4 = unsafeNull() val rotation: Vec3 = unsafeNull()
val inverted: Directions = unsafeNull() val inverted: Directions = unsafeNull()
private fun invert(): Directions { private fun invert(): Directions {
@ -170,14 +169,13 @@ enum class Directions(
return minDirection return minDirection
} }
init { init {
val rotationMatrix = Directions::rotatedMatrix.javaField!! val rotation = Directions::rotation.javaField!!
val inverted = Directions::inverted.javaField!! val inverted = Directions::inverted.javaField!!
val axis = Directions::axis.javaField!! val axis = Directions::axis.javaField!!
for (direction in VALUES) { for (direction in VALUES) {
inverted.forceSet(direction, direction.invert()) inverted.forceSet(direction, direction.invert())
rotationMatrix.forceSet(direction, DirectionUtil.rotateMatrix(direction)) rotation.forceSet(direction, DirectionUtil.getRotation(direction))
axis.forceSet(direction, Axes[direction]) axis.forceSet(direction, Axes[direction])
} }
NAME_MAP.unsafeCast<MutableMap<String, Directions>>()["bottom"] = DOWN NAME_MAP.unsafeCast<MutableMap<String, Directions>>()["bottom"] = DOWN

View File

@ -104,6 +104,7 @@ object RenderLoader {
Log.log(LogMessageType.RENDERING, LogLevels.VERBOSE) { "Baking models (after ${stopwatch.labTime()})..." } Log.log(LogMessageType.RENDERING, LogLevels.VERBOSE) { "Baking models (after ${stopwatch.labTime()})..." }
font.postInit(renderLatch) font.postInit(renderLatch)
models.bake(renderLatch) models.bake(renderLatch)
models.upload()
models.cleanup() models.cleanup()
Log.log(LogMessageType.RENDERING, LogLevels.VERBOSE) { "Post loading renderer (after ${stopwatch.labTime()})..." } Log.log(LogMessageType.RENDERING, LogLevels.VERBOSE) { "Post loading renderer (after ${stopwatch.labTime()})..." }

View File

@ -37,7 +37,7 @@ class DoubleChestRenderer(
light: Int, light: Int,
) : StorageBlockEntityRenderer<StorageBlockEntity>( ) : StorageBlockEntityRenderer<StorageBlockEntity>(
blockState, 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, light,
) { ) {

View File

@ -37,7 +37,7 @@ class SingleChestRenderer(
light: Int, light: Int,
) : StorageBlockEntityRenderer<StorageBlockEntity>( ) : StorageBlockEntityRenderer<StorageBlockEntity>(
blockState, 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, light,
) { ) {

View File

@ -60,6 +60,10 @@ class ModelLoader(
Log.log(LogMessageType.LOADING, LogLevels.VERBOSE) { "Baked models in ${time.formatNanos()}!" } Log.log(LogMessageType.LOADING, LogLevels.VERBOSE) { "Baked models in ${time.formatNanos()}!" }
} }
fun upload() {
skeletal.upload()
}
fun cleanup() { fun cleanup() {
block.cleanup() block.cleanup()
item.cleanup() item.cleanup()

View File

@ -46,6 +46,12 @@ class SkeletalLoader(private val loader: ModelLoader) {
} }
} }
fun upload() {
for ((name, baked) in this.baked) {
baked.load()
}
}
fun cleanup() { fun cleanup() {
this::registered.forceSet(null) this::registered.forceSet(null)
} }

View File

@ -46,20 +46,15 @@ class SkeletalManager(
fun draw(instance: SkeletalInstance, light: Int) { fun draw(instance: SkeletalInstance, light: Int) {
prepareDraw() prepareDraw()
shader.light = light shader.light = light
// val transforms = instance.calculateTransforms()
// var stride = 0 instance.transform.pack(uniformBuffer.buffer)
// for (transform in transforms) { uniformBuffer.upload(0 until instance.model.transformCount * MAT4_SIZE)
// for (float in transform.array) {
// uniformBuffer.buffer.put(stride++, float)
// }
// }
// uniformBuffer.upload(0 until (transforms.size * MAT4_SIZE))
instance.model.mesh.draw() instance.model.mesh.draw()
} }
private companion object { companion object {
private const val TRANSFORMS = 128 private const val TRANSFORMS = 128
private const val MAT4_SIZE = 4 * 4 const val MAT4_SIZE = 4 * 4
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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.shader.NativeShader
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager
class SkeletalShader( open class SkeletalShader(
override val native: NativeShader, override val native: NativeShader,
buffer: FloatUniformBuffer, buffer: FloatUniformBuffer,
) : Shader(), TextureShader, AnimatedShader, LightShader, ViewProjectionShader, FogShader { ) : Shader(), TextureShader, AnimatedShader, LightShader, ViewProjectionShader, FogShader {

View File

@ -13,7 +13,6 @@
package de.bixilon.minosoft.gui.rendering.skeletal.baked package de.bixilon.minosoft.gui.rendering.skeletal.baked
import de.bixilon.kotlinglm.mat4x4.Mat4
import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalMesh import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalMesh
@ -21,7 +20,8 @@ import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
data class BakedSkeletalModel( data class BakedSkeletalModel(
val mesh: SkeletalMesh, val mesh: SkeletalMesh,
val transforms: MutableMap<String, BakedSkeletalTransform>, val transform: BakedSkeletalTransform,
val transformCount: Int,
// TODO: animations // TODO: animations
) { ) {
private var state = SkeletalModelStates.DECLARED private var state = SkeletalModelStates.DECLARED
@ -39,7 +39,13 @@ data class BakedSkeletalModel(
state = SkeletalModelStates.UNLOADED 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
} }
} }

View File

@ -14,9 +14,21 @@
package de.bixilon.minosoft.gui.rendering.skeletal.baked package de.bixilon.minosoft.gui.rendering.skeletal.baked
import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.minosoft.gui.rendering.skeletal.instance.TransformInstance
data class BakedSkeletalTransform( data class BakedSkeletalTransform(
val id: Int, val id: Int,
val pivot: Vec3, val pivot: Vec3,
val children: Map<String, BakedSkeletalTransform>, val children: Map<String, BakedSkeletalTransform>,
) ) {
fun instance(): TransformInstance {
val children: MutableMap<String, TransformInstance> = mutableMapOf()
for ((name, child) in this.children) {
children[name] = child.instance()
}
return TransformInstance(id, pivot, children)
}
}

View File

@ -13,18 +13,42 @@
package de.bixilon.minosoft.gui.rendering.skeletal.instance 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.shader.Shader
import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel
class SkeletalInstance( class SkeletalInstance(
val context: RenderContext,
val model: BakedSkeletalModel, 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() TODO()
} }
fun draw(shader: Shader? = null) { fun update(position: Vec3, rotation: Vec3) {
TODO() 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)
} }
} }

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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<String, TransformInstance>,
) {
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)
}
}

View File

@ -64,8 +64,9 @@ data class SkeletalModel(
val transforms: MutableMap<String, BakedSkeletalTransform> = mutableMapOf() val transforms: MutableMap<String, BakedSkeletalTransform> = mutableMapOf()
val transformId = AtomicInteger(1)
for ((name, transform) in this.transforms) { for ((name, transform) in this.transforms) {
transforms[name] = transform.bake(AtomicInteger(1)) transforms[name] = transform.bake(transformId)
} }
val baseTransform = BakedSkeletalTransform(0, Vec3.EMPTY, transforms) val baseTransform = BakedSkeletalTransform(0, Vec3.EMPTY, transforms)
@ -73,6 +74,6 @@ data class SkeletalModel(
element.bake(mesh, textures, baseTransform) element.bake(mesh, textures, baseTransform)
} }
return BakedSkeletalModel(mesh, transforms) return BakedSkeletalModel(mesh, baseTransform, transformId.get())
} }
} }