Атлас спрайтов теперь более менее рабочий
This commit is contained in:
parent
8ef4ab0eb1
commit
7697efeb50
src/main/kotlin/ru/dbotthepony/kstarbound
@ -0,0 +1,58 @@
|
||||
package ru.dbotthepony.kstarbound.client.render
|
||||
|
||||
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
|
||||
import ru.dbotthepony.kstarbound.client.gl.GLTexture2D
|
||||
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
|
||||
import ru.dbotthepony.kstarbound.defs.animation.IUVCoordinates
|
||||
import ru.dbotthepony.kstarbound.defs.animation.SpriteReference
|
||||
|
||||
/**
|
||||
* Связка текстуры-атласа + координат спрайта на ней
|
||||
*/
|
||||
class BoundSprite(
|
||||
val reference: SpriteReference,
|
||||
val texture: GLTexture2D
|
||||
) : IUVCoordinates {
|
||||
inline val sprite get() = reference.sprite
|
||||
|
||||
/**
|
||||
* Настоящая ширина спрайта, в пикселях
|
||||
*/
|
||||
inline val width get() = reference.sprite.width(texture.width)
|
||||
|
||||
/**
|
||||
* Настоящая высота спрайта, в пикселях
|
||||
*/
|
||||
inline val height get() = reference.sprite.height(texture.height)
|
||||
|
||||
override val u0: Float
|
||||
override val v0: Float
|
||||
override val u1: Float
|
||||
override val v1: Float
|
||||
|
||||
init {
|
||||
val coords = reference.sprite.compute(texture)
|
||||
|
||||
this.u0 = coords.u0
|
||||
this.v0 = coords.v0
|
||||
this.u1 = coords.u1
|
||||
this.v1 = coords.v1
|
||||
}
|
||||
|
||||
fun bind() = texture.bind()
|
||||
val transformer = QuadTransformers.uv(u0, v0, u1, v1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Создаёт связку текстуры-атласа + координгат спрайта на ней
|
||||
*/
|
||||
fun SpriteReference.bind(texture: GLTexture2D): BoundSprite {
|
||||
return BoundSprite(this, texture)
|
||||
}
|
||||
|
||||
/**
|
||||
* Создаёт связку текстуры-атласа, которая загружается через [GLStateTracker.loadNamedTextureSafe] + координгат спрайта на ней
|
||||
*/
|
||||
fun SpriteReference.bind(state: GLStateTracker): BoundSprite {
|
||||
return BoundSprite(this, state.loadNamedTextureSafe(path))
|
||||
}
|
@ -5,12 +5,13 @@ import ru.dbotthepony.kstarbound.client.ClientChunk
|
||||
import ru.dbotthepony.kstarbound.client.gl.GLStateTracker
|
||||
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
|
||||
import ru.dbotthepony.kstarbound.client.gl.vertex.quadRotatedZ
|
||||
import ru.dbotthepony.kstarbound.client.render.bind
|
||||
import ru.dbotthepony.kstarbound.world.entities.ItemEntity
|
||||
import ru.dbotthepony.kvector.matrix.Matrix4fStack
|
||||
|
||||
class ItemRenderer(state: GLStateTracker, entity: ItemEntity, chunk: ClientChunk?) : EntityRenderer(state, entity, chunk) {
|
||||
private val def = entity.def
|
||||
private val textures = def.inventoryIcon?.stream()?.map { state.loadNamedTextureSafe(it.image.path) }?.toList() ?: listOf()
|
||||
private val textures = def.inventoryIcon?.stream()?.map { it.image.bind(state) }?.toList() ?: listOf()
|
||||
|
||||
override fun render(stack: Matrix4fStack) {
|
||||
if (textures.isEmpty())
|
||||
@ -31,7 +32,7 @@ class ItemRenderer(state: GLStateTracker, entity: ItemEntity, chunk: ClientChunk
|
||||
val width = (texture.width / PIXELS_IN_STARBOUND_UNITf) / 2f
|
||||
val height = (texture.height / PIXELS_IN_STARBOUND_UNITf) / 2f
|
||||
|
||||
builder.quadRotatedZ(-width, -height, width, height, 5f, 0f, 0f, entity.movement.angle, QuadTransformers.uv(0f, 1f, 1f, 0f))
|
||||
builder.quadRotatedZ(-width, -height, width, height, 5f, 0f, 0f, entity.movement.angle, texture.transformer)
|
||||
|
||||
builder.upload()
|
||||
builder.draw()
|
||||
|
@ -18,8 +18,13 @@ import java.util.concurrent.ConcurrentHashMap
|
||||
* Атлас спрайтов, собранный вручную артистом
|
||||
*
|
||||
* В файлах игры именуется frames
|
||||
*
|
||||
* Несмотря на название, НЕ ЯВЛЯЕТСЯ изображением, а лишь метаданными для *множества* возможных изображений
|
||||
*/
|
||||
class AtlasDefinition private constructor(
|
||||
/**
|
||||
* Имя данного атласа (путь к файлу)
|
||||
*/
|
||||
val name: String,
|
||||
|
||||
/**
|
||||
@ -64,18 +69,57 @@ class AtlasDefinition private constructor(
|
||||
|
||||
/**
|
||||
* Позиция и размеры данного спрайта, в пикселях
|
||||
*
|
||||
* Нулевой размер имеет особое значение - считается, что спрайт покрывает весь атлас
|
||||
*/
|
||||
val position: Vector4i,
|
||||
) {
|
||||
/**
|
||||
* Ширина, в пикселях
|
||||
*
|
||||
* Нулевой размер имеет особое значение - считается, что спрайт покрывает весь атлас
|
||||
*/
|
||||
val width = position.x - position.z
|
||||
|
||||
/**
|
||||
* Высота, в пикселях
|
||||
*
|
||||
* Нулевой размер имеет особое значение - считается, что спрайт покрывает весь атлас
|
||||
*/
|
||||
val height = position.y - position.w
|
||||
|
||||
fun width(atlasWidth: Int): Int {
|
||||
if (width == 0)
|
||||
return atlasWidth
|
||||
|
||||
return width
|
||||
}
|
||||
|
||||
fun height(atlasHeight: Int): Int {
|
||||
if (height == 0)
|
||||
return atlasHeight
|
||||
|
||||
return height
|
||||
}
|
||||
|
||||
/**
|
||||
* Вычисляет uv координаты данного спрайта на заданном полотне
|
||||
*
|
||||
* v вычисляется инвентированным, для учёта системы координат OpenGL
|
||||
*/
|
||||
fun compute(width: Int, height: Int): UVCoordinates {
|
||||
require(width > 0) { "Invalid width provided: $width" }
|
||||
require(height > 0) { "Invalid height provided: $height" }
|
||||
|
||||
if (this.width == 0 || this.height == 0) {
|
||||
return UVCoordinates.FULL_OPENGL
|
||||
}
|
||||
|
||||
return UVCoordinates(
|
||||
u0 = position.x.toFloat() / width.toFloat(),
|
||||
v0 = position.y.toFloat() / height.toFloat(),
|
||||
v1 = position.y.toFloat() / height.toFloat(),
|
||||
u1 = position.z.toFloat() / width.toFloat(),
|
||||
v1 = position.w.toFloat() / height.toFloat(),
|
||||
v0 = position.w.toFloat() / height.toFloat(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -99,7 +143,7 @@ class AtlasDefinition private constructor(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val EMPTY = AtlasDefinition("null", ImmutableMap.of("root", Sprite("root", Vector4i(0, 0, 1, 1))))
|
||||
val EMPTY = AtlasDefinition("null", ImmutableMap.of("root", Sprite("root", Vector4i(0, 0, 0, 0))))
|
||||
|
||||
private val cache = ConcurrentHashMap<String, AtlasDefinition>()
|
||||
|
||||
|
@ -5,4 +5,9 @@ data class UVCoordinates(
|
||||
override val v0: Float,
|
||||
override val u1: Float,
|
||||
override val v1: Float,
|
||||
) : IUVCoordinates
|
||||
) : IUVCoordinates {
|
||||
companion object {
|
||||
val FULL = UVCoordinates(0f, 0f, 1f, 1f)
|
||||
val FULL_OPENGL = UVCoordinates(0f, 1f, 1f, 0f)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user