Атлас спрайтов теперь более менее рабочий
This commit is contained in:
parent
8ef4ab0eb1
commit
7697efeb50
@ -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.GLStateTracker
|
||||||
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
|
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
|
||||||
import ru.dbotthepony.kstarbound.client.gl.vertex.quadRotatedZ
|
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.kstarbound.world.entities.ItemEntity
|
||||||
import ru.dbotthepony.kvector.matrix.Matrix4fStack
|
import ru.dbotthepony.kvector.matrix.Matrix4fStack
|
||||||
|
|
||||||
class ItemRenderer(state: GLStateTracker, entity: ItemEntity, chunk: ClientChunk?) : EntityRenderer(state, entity, chunk) {
|
class ItemRenderer(state: GLStateTracker, entity: ItemEntity, chunk: ClientChunk?) : EntityRenderer(state, entity, chunk) {
|
||||||
private val def = entity.def
|
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) {
|
override fun render(stack: Matrix4fStack) {
|
||||||
if (textures.isEmpty())
|
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 width = (texture.width / PIXELS_IN_STARBOUND_UNITf) / 2f
|
||||||
val height = (texture.height / 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.upload()
|
||||||
builder.draw()
|
builder.draw()
|
||||||
|
@ -18,8 +18,13 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
* Атлас спрайтов, собранный вручную артистом
|
* Атлас спрайтов, собранный вручную артистом
|
||||||
*
|
*
|
||||||
* В файлах игры именуется frames
|
* В файлах игры именуется frames
|
||||||
|
*
|
||||||
|
* Несмотря на название, НЕ ЯВЛЯЕТСЯ изображением, а лишь метаданными для *множества* возможных изображений
|
||||||
*/
|
*/
|
||||||
class AtlasDefinition private constructor(
|
class AtlasDefinition private constructor(
|
||||||
|
/**
|
||||||
|
* Имя данного атласа (путь к файлу)
|
||||||
|
*/
|
||||||
val name: String,
|
val name: String,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,18 +69,57 @@ class AtlasDefinition private constructor(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Позиция и размеры данного спрайта, в пикселях
|
* Позиция и размеры данного спрайта, в пикселях
|
||||||
|
*
|
||||||
|
* Нулевой размер имеет особое значение - считается, что спрайт покрывает весь атлас
|
||||||
*/
|
*/
|
||||||
val position: Vector4i,
|
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 координаты данного спрайта на заданном полотне
|
* Вычисляет uv координаты данного спрайта на заданном полотне
|
||||||
|
*
|
||||||
|
* v вычисляется инвентированным, для учёта системы координат OpenGL
|
||||||
*/
|
*/
|
||||||
fun compute(width: Int, height: Int): UVCoordinates {
|
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(
|
return UVCoordinates(
|
||||||
u0 = position.x.toFloat() / width.toFloat(),
|
u0 = position.x.toFloat() / width.toFloat(),
|
||||||
v0 = position.y.toFloat() / height.toFloat(),
|
v1 = position.y.toFloat() / height.toFloat(),
|
||||||
u1 = position.z.toFloat() / width.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 {
|
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>()
|
private val cache = ConcurrentHashMap<String, AtlasDefinition>()
|
||||||
|
|
||||||
|
@ -5,4 +5,9 @@ data class UVCoordinates(
|
|||||||
override val v0: Float,
|
override val v0: Float,
|
||||||
override val u1: Float,
|
override val u1: Float,
|
||||||
override val v1: 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