skeletal rotation

This commit is contained in:
Moritz Zwerger 2023-10-15 21:50:35 +02:00
parent 0dbdb6121e
commit 745143fab7
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
6 changed files with 73 additions and 20 deletions

View File

@ -3,7 +3,11 @@
"body": {
"from": [-8, 0, -8],
"to": [8, 16, 8],
"rotation": [-180, 0, 270],
"rotation": {
"value": [-180, 0, 270],
"origin": [0, 8, 0],
"rescale": false
},
"texture": "minosoft:dummy_texture",
"transform": "body",
"faces": {
@ -17,7 +21,7 @@
"children": {
"head1": {
"transform": "head",
"origin": [0, 5, 0],
"offset": [0, 5, 0],
"from": [-5, 0, -5],
"to": [5, 10, 5],
"faces": {
@ -30,7 +34,7 @@
},
"head2": {
"transform": "head",
"origin": [0, 6, 0],
"offset": [0, 6, 0],
"from": [-5, 0, -5],
"to": [5, 10, 5],
"faces": {

View File

@ -14,33 +14,34 @@
package de.bixilon.minosoft.gui.rendering.skeletal.baked
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.kutil.collections.CollectionUtil.extend
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalVertexConsumer
import de.bixilon.minosoft.gui.rendering.skeletal.model.elements.SkeletalElement
import de.bixilon.minosoft.gui.rendering.skeletal.model.elements.SkeletalRotation
import de.bixilon.minosoft.gui.rendering.skeletal.model.textures.SkeletalTextureInstance
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
data class SkeletalBakeContext(
val offset: Vec3 = Vec3.EMPTY,
val rotation: Vec3 = Vec3.EMPTY,
val inflate: Float = 0.0f,
val transparency: Boolean = true,
val texture: ResourceLocation? = null,
val transform: BakedSkeletalTransform? = null,
val transform: BakedSkeletalTransform,
val rotations: List<SkeletalRotation> = emptyList(),
val transforms: Map<String, BakedSkeletalTransform>,
val textures: Map<ResourceLocation, SkeletalTextureInstance>,
val consumer: SkeletalVertexConsumer,
) {
fun copy(element: SkeletalElement): SkeletalBakeContext {
val offset = this.offset + element.origin
val rotation = this.rotation + element.rotation
val offset = this.offset + (element.offset / 16.0f)
val inflate = this.inflate + element.inflate
val transparency = this.transparency && element.transparency
val texture = element.texture ?: texture
val transform = element.transform?.let { transforms[element.transform] } ?: transform
val rotations = if (element.rotation != null) this.rotations.extend(element.rotation) else this.rotations
val transform = element.transform?.let { transform.children[element.transform] ?: throw IllegalArgumentException("Can not find transform ${element.transform}") } ?: transform
return copy(offset = offset, rotation = rotation, inflate = inflate, transparency = transparency, texture = texture, transform = transform)
return copy(offset = offset, inflate = inflate, transparency = transparency, texture = texture, transform = transform, rotations = rotations)
}
}

View File

@ -13,6 +13,7 @@
package de.bixilon.minosoft.gui.rendering.skeletal.model
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.skeletal.SkeletalMesh
@ -25,6 +26,7 @@ import de.bixilon.minosoft.gui.rendering.skeletal.model.textures.SkeletalTexture
import de.bixilon.minosoft.gui.rendering.skeletal.model.transforms.SkeletalTransform
import de.bixilon.minosoft.gui.rendering.system.base.texture.shader.ShaderTexture
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
import java.util.concurrent.atomic.AtomicInteger
data class SkeletalModel(
@ -58,9 +60,10 @@ data class SkeletalModel(
for ((name, transform) in this.transforms) {
transforms[name] = transform.bake(AtomicInteger(1))
}
val baseTransform = BakedSkeletalTransform(0, Vec3.EMPTY, transforms)
for ((name, element) in elements) {
element.bake(mesh, textures, transforms)
element.bake(mesh, textures, baseTransform)
}
return BakedSkeletalModel(mesh, transforms)

View File

@ -25,8 +25,8 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
data class SkeletalElement(
val from: Vec3,
val to: Vec3,
val origin: Vec3 = (from - to) / 2.0f,
val rotation: Vec3 = Vec3.EMPTY,
val offset: Vec3 = Vec3.EMPTY,
val rotation: SkeletalRotation? = null,
val inflate: Float = 0.0f,
val transparency: Boolean = true,
val enabled: Boolean = true,
@ -36,10 +36,14 @@ data class SkeletalElement(
val children: Map<String, SkeletalElement>,
) {
fun bake(mesh: SkeletalMesh, textures: Map<ResourceLocation, SkeletalTextureInstance>, transforms: Map<String, BakedSkeletalTransform>) {
init {
this.rotation?.apply(from, to)
}
fun bake(mesh: SkeletalMesh, textures: Map<ResourceLocation, SkeletalTextureInstance>, transform: BakedSkeletalTransform) {
if (!enabled) return
val context = SkeletalBakeContext(transforms = transforms, textures = textures, consumer = mesh)
val context = SkeletalBakeContext(transform = transform, textures = textures, consumer = mesh)
return bake(context)
}
@ -47,8 +51,8 @@ data class SkeletalElement(
if (!enabled) return
val context = context.copy(this)
val transform = context.transform?.id ?: 0
val transform = context.transform.id
for ((direction, face) in faces) {
face.bake(context, direction, this, transform)

View File

@ -30,16 +30,17 @@ data class SkeletalFace(
) {
fun bake(context: SkeletalBakeContext, direction: Directions, element: SkeletalElement, transform: Int) {
val positions = direction.getPositions(context.offset + (element.from / 16.0f - context.inflate), context.offset + (element.to / 16.0f + context.inflate))
val positions = direction.getPositions(context.offset + element.from - context.inflate, context.offset + element.to + context.inflate)
val texture = context.textures[texture ?: context.texture ?: throw IllegalStateException("element has no texture set!")] ?: throw IllegalStateException("Texture not found!")
val texturePositions = ModelBakeUtil.getTextureCoordinates(uv.start / texture.properties.resolution, uv.end / texture.properties.resolution)
val origin = element.origin / 16.0f
element.rotation.let {
val rad = -GLM.radians(it)
for (rotation in context.rotations) {
val origin = rotation._origin / 16.0f
val rad = -GLM.radians(rotation.value)
for ((index, position) in positions.withIndex()) {
val out = Vec3(position)
out.rotateAssign(rad[0], Axes.X, origin, false)

View File

@ -0,0 +1,40 @@
/*
* 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.model.elements
import com.fasterxml.jackson.annotation.JsonIgnore
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.kutil.cast.CastUtil.unsafeNull
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
data class SkeletalRotation(
val value: Vec3,
val origin: Vec3? = null,
val rescale: Boolean = false,
) {
@JsonIgnore
var _origin: Vec3 = unsafeNull()
fun apply(from: Vec3, to: Vec3) {
this._origin = (to - from) / 2.0f
}
operator fun plus(other: SkeletalRotation): SkeletalRotation {
return SkeletalRotation(this.value + other.value, _origin)
}
companion object {
val EMPTY = SkeletalRotation(Vec3.EMPTY, Vec3.EMPTY, false)
}
}