KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/LayeredRenderTree.kt

87 lines
3.3 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ru.dbotthepony.kstarbound.client.render
import ru.dbotthepony.kstarbound.math.FloatMatrix
import ru.dbotthepony.kstarbound.math.Matrix4f
import ru.dbotthepony.kstarbound.math.Matrix4fStack
/**
* Интерфейс для отрисовки комплексных объектов, в которых множество слоёв, который
* определяет лишь один метод: [renderLayer]
*
* Используется вместе с другими [ILayeredRenderer], где необходимо отрисовывать комплексную сцену,
* реализуя ручную сортировку геометрии.
*/
interface ILayeredRenderer {
/**
* Главный метод отрисовки данной стопки слоёв. Вызов данного метода может что-либо
* отрисовать, а может вообще ничего не отрисовать.
*
* zLevel всегда положителен, и указывает на то, какой слой (или все слои за) надо отрисовать,
* т.е. при вызове этого метода отрисовываются все слои, у которых z позиция >= [zPos]
*
* Возвращается zNew следующего слоя (такой, что [zPos] > zNew).
*
* Если следующего слоя нет, вернуть -1, и данный объект
* будет считаться отрисованным.
*/
fun renderLayerFromStack(zPos: Int, transform: Matrix4fStack): Int
/**
* Возвращает наибольшее zPos в данной стопке.
*
* Если стопка пуста, то необходимо вернуть -1.
*
* В зависимости от сцены, которую необходимо отрисовать,
* [renderLayerFromStack] может быть вызван сразу с этим же значением,
* если этот объект имеет самый дальний слой
*/
fun bottomMostZLevel(): Int
/**
* Говорит о том, что вот-вот будет начата отрисовка в render pipeline
* и будут вызываться [renderLayerFromStack]. В данном методе должна построиться
* и отсортироваться стопка слоёв
*/
fun prepareForLayeredRender()
}
fun renderLayeredList(transform: Matrix4fStack, potentialRenderers: List<ILayeredRenderer>): Int {
val renderers = ArrayList<ILayeredRenderer>(potentialRenderers.size)
var bottomMost = -1
for (render in potentialRenderers) {
render.prepareForLayeredRender()
val zLevel = render.bottomMostZLevel()
if (zLevel >= 0) {
bottomMost = bottomMost.coerceAtLeast(zLevel)
renderers.add(render)
}
}
var lastBottom = bottomMost
var renderCalls = 0
while (lastBottom > 0 && renderers.isNotEmpty()) {
var newBottom = lastBottom
for (i in renderers.size - 1 downTo 0) {
val renderer = renderers[i]
val newLevel = renderer.renderLayerFromStack(lastBottom, transform)
renderCalls++
if (newLevel <= -1) {
renderers.removeAt(i)
} else {
newBottom = newBottom.coerceAtMost(newLevel)
}
}
lastBottom = newBottom
}
return renderCalls
}