87 lines
3.3 KiB
Kotlin
87 lines
3.3 KiB
Kotlin
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
|
||
}
|