diff --git a/src/main/kotlin/solve/rendering/canvas/SceneCanvas.kt b/src/main/kotlin/solve/rendering/canvas/SceneCanvas.kt index cc916f2f..4bfb3062 100644 --- a/src/main/kotlin/solve/rendering/canvas/SceneCanvas.kt +++ b/src/main/kotlin/solve/rendering/canvas/SceneCanvas.kt @@ -47,6 +47,7 @@ class SceneCanvas : OpenGLCanvas() { this.scene = scene this.framesSize = Vector2i(scene.frameSize.width.toInt(), scene.frameSize.height.toInt()) canvasScene?.framesRenderer?.setNewSceneFrames(scene.frames, framesSize.toFloatVector()) + canvasScene?.landmarkRenderers?.forEach { it.setNewSceneFrames(scene.frames, framesSize.toFloatVector()) } isFirstFramesSelection = true needToReinitializeRenderers = true @@ -62,6 +63,7 @@ class SceneCanvas : OpenGLCanvas() { window.camera.position = leftUpperCornerCameraPosition canvasScene?.framesRenderer?.setFramesSelection(framesSelection) + canvasScene?.landmarkRenderers?.forEach { it.setFramesSelection(framesSelection) } canvasScene?.landmarkRenderers?.forEach { renderer -> val rendererLayerSettings = canvasScene?.landmarkLayerRendererLayers?.get(renderer)?.settings ?: return@forEach @@ -73,7 +75,7 @@ class SceneCanvas : OpenGLCanvas() { } fun setColumnsNumber(columnsNumber: Int) { - canvasScene?.framesRenderer?.setGridWidth(columnsNumber) + canvasScene?.framesRenderer?.setNewGridWidth(columnsNumber) canvasScene?.landmarkRenderers?.forEach { it.setNewGridWidth(columnsNumber) } this.columnsNumber = columnsNumber } diff --git a/src/main/kotlin/solve/rendering/engine/core/renderers/FramesRenderer.kt b/src/main/kotlin/solve/rendering/engine/core/renderers/FramesRenderer.kt index eddc3fbf..081e6102 100644 --- a/src/main/kotlin/solve/rendering/engine/core/renderers/FramesRenderer.kt +++ b/src/main/kotlin/solve/rendering/engine/core/renderers/FramesRenderer.kt @@ -45,19 +45,14 @@ class FramesRenderer( override val maxBatchSize = 1000 private var modelsCommonMatrix = Matrix4f().identity() - private var gridWidth = DefaultGridWidth - private var installedGridWidth = gridWidth - private val gridHeight: Int - get() = (frames.count().toFloat() / gridWidth).ceilToInt() + private var buffersSize = defaultBuffersSize private var bufferFramesArrayTexture: ArrayTexture? = null - private var frames = emptyList() private var framesWidth = 1 private var framesHeight = 1 private var framesChannelsType = TextureChannelsType.RGBA - private var selectedFrames = emptyList() private val framesRatio: Float get() = framesWidth.toFloat() / framesHeight.toFloat() @@ -76,32 +71,17 @@ class FramesRenderer( modelsCommonMatrix = newMatrix } - fun setGridWidth(gridWidth: Int) { - if (gridWidth < 1) { - println("The width of the frames grid should be a positive value!") - return - } + override fun onSceneFramesUpdated() { + needToReinitializeBuffers = true + } + override fun onFramesSelectionUpdated() { disableVirtualization() - installedGridWidth = gridWidth - updateGridWidth() haveNewFramesSelection = true } - override fun setNewSceneFrames(frames: List, framesSize: Vector2f) { - if (frames.isEmpty()) { - return - } - - this.frames = frames - selectedFrames = frames - needToReinitializeBuffers = true - } - - fun setFramesSelection(selection: List) { + override fun onGridWidthUpdated() { disableVirtualization() - selectedFrames = selection - updateGridWidth() haveNewFramesSelection = true } @@ -123,6 +103,7 @@ class FramesRenderer( shaderProgram.uploadInt(TexturesArrayUniformName, 0) shaderProgram.uploadFloat(TexturesRatioUniformName, framesRatio) shaderProgram.uploadVector2f(CameraPositionUniformName, getScreenTopLeftGridCellPosition().toFloatVector()) + shaderProgram.uploadFloat(FramesSpacingUniformName, FramesSpacing) } override fun createNewBatch(zIndex: Int) = @@ -279,10 +260,6 @@ class FramesRenderer( loadRectFramesToBuffers(IntRect(0, 0, gridWidth, gridHeight)) } - private fun updateGridWidth() { - this.gridWidth = min(installedGridWidth, selectedFrames.count()) - } - private fun initializeTexturesBuffers(frames: List) { val firstTextureData = Texture2D.loadData(frames.first().imagePath.toString()) if (firstTextureData == null) { @@ -316,11 +293,7 @@ class FramesRenderer( } companion object { - const val DefaultGridWidth = 10 - - private const val ProjectionUniformName = "uProjection" private const val ModelUniformName = "uModel" - private const val GridWidthUniformName = "uGridWidth" private const val BuffersSizeUniformName = "uBuffersSize" private const val TexturesArrayUniformName = "uTextures" private const val TexturesRatioUniformName = "uTexturesRatio" @@ -328,6 +301,7 @@ class FramesRenderer( private const val BuffersSizeOffset = 2 + private val defaultBuffersSize = Vector2i(10, 10) } } diff --git a/src/main/kotlin/solve/rendering/engine/core/renderers/LandmarkLayerRenderer.kt b/src/main/kotlin/solve/rendering/engine/core/renderers/LandmarkLayerRenderer.kt index f1e12f65..84219edc 100644 --- a/src/main/kotlin/solve/rendering/engine/core/renderers/LandmarkLayerRenderer.kt +++ b/src/main/kotlin/solve/rendering/engine/core/renderers/LandmarkLayerRenderer.kt @@ -11,31 +11,24 @@ abstract class LandmarkLayerRenderer( window: Window, protected val getScene: () -> Scene? ) : Renderer(window) { - protected var gridWidth = FramesRenderer.DefaultGridWidth - protected var framesSize = Vector2f() protected var framesRatio: Float = 1f abstract fun setFramesSelectionLayers(layers: List) - override fun setNewSceneFrames(frames: List, framesSize: Vector2f) { - this.framesSize = framesSize + override fun onSceneFramesUpdated() { this.framesRatio = framesSize.x / framesSize.y } - fun setNewGridWidth(gridWidth: Int) { - if (gridWidth < 1) { - println("The width of the frames grid should be a positive value!") - return - } + protected fun getFrameTopLeftShaderPosition(frameIndex: Int): Vector2f { + val frameXIndex = frameIndex % gridWidth + val frameYIndex = frameIndex / gridWidth - this.gridWidth = gridWidth + return Vector2f( + frameXIndex.toFloat() * framesRatio + frameXIndex * FramesSpacing, + frameYIndex.toFloat() + frameYIndex * FramesSpacing + ) } - protected fun getFrameTopLeftShaderPosition(frameIndex: Int) = Vector2f( - (frameIndex % gridWidth).toFloat() * framesRatio, - (frameIndex / gridWidth).toFloat() - ) - protected fun getFramePixelShaderPosition(frameIndex: Int, framePixelPosition: Vector2f): Vector2f { val frameRelativePosition = Vector2f(framePixelPosition) / framesSize.y val frameTopLeftPosition = getFrameTopLeftShaderPosition(frameIndex) diff --git a/src/main/kotlin/solve/rendering/engine/core/renderers/LinesLayerRenderer.kt b/src/main/kotlin/solve/rendering/engine/core/renderers/LinesLayerRenderer.kt index 12416de6..6213ba46 100644 --- a/src/main/kotlin/solve/rendering/engine/core/renderers/LinesLayerRenderer.kt +++ b/src/main/kotlin/solve/rendering/engine/core/renderers/LinesLayerRenderer.kt @@ -132,7 +132,6 @@ class LinesLayerRenderer( } companion object { - private const val ProjectionUniformName = "uProjection" private const val UseCommonColorUniformName = "uUseCommonColor" private const val CommonColorUniformName = "uCommonColor" diff --git a/src/main/kotlin/solve/rendering/engine/core/renderers/PlanesLayerRenderer.kt b/src/main/kotlin/solve/rendering/engine/core/renderers/PlanesLayerRenderer.kt index 38dae745..5c7e2bc0 100644 --- a/src/main/kotlin/solve/rendering/engine/core/renderers/PlanesLayerRenderer.kt +++ b/src/main/kotlin/solve/rendering/engine/core/renderers/PlanesLayerRenderer.kt @@ -99,7 +99,6 @@ class PlanesLayerRenderer( } } companion object { - private const val ProjectionUniformName = "uProjection" private const val TexturesUniformName = "uTextures" private val texturesIndices = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7) diff --git a/src/main/kotlin/solve/rendering/engine/core/renderers/PointsLayerRenderer.kt b/src/main/kotlin/solve/rendering/engine/core/renderers/PointsLayerRenderer.kt index c9775d23..4e1d15f7 100644 --- a/src/main/kotlin/solve/rendering/engine/core/renderers/PointsLayerRenderer.kt +++ b/src/main/kotlin/solve/rendering/engine/core/renderers/PointsLayerRenderer.kt @@ -114,7 +114,6 @@ class PointsLayerRenderer( } companion object { - private const val ProjectionUniformName = "uProjection" private const val UseCommonColorUniformName = "uUseCommonColor" private const val CommonColorUniformName = "uCommonColor" diff --git a/src/main/kotlin/solve/rendering/engine/core/renderers/Renderer.kt b/src/main/kotlin/solve/rendering/engine/core/renderers/Renderer.kt index 333de766..e2becfe3 100644 --- a/src/main/kotlin/solve/rendering/engine/core/renderers/Renderer.kt +++ b/src/main/kotlin/solve/rendering/engine/core/renderers/Renderer.kt @@ -8,6 +8,8 @@ import solve.rendering.engine.core.batch.RenderBatch import solve.rendering.engine.core.texture.Texture import solve.rendering.engine.shader.ShaderProgram import solve.scene.model.VisualizationFrame +import solve.utils.ceilToInt +import kotlin.math.min abstract class Renderer(protected val window: Window) : Comparable { protected abstract val maxBatchSize: Int @@ -16,13 +18,50 @@ abstract class Renderer(protected val window: Window) : Comparable { protected lateinit var shaderProgram: ShaderProgram protected val batches = mutableListOf() + protected var frames = emptyList() + protected var selectedFrames = emptyList() + protected var framesSize = Vector2f() + protected var renderPriority = 0 + protected var gridWidth = DefaultGridWidth + protected var installedGridWidth = gridWidth + protected val gridHeight: Int + get() = (frames.count().toFloat() / gridWidth).ceilToInt() + init { initialize() } - abstract fun setNewSceneFrames(frames: List, framesSize: Vector2f) + open fun onSceneFramesUpdated() { } + + open fun onFramesSelectionUpdated() { } + + open fun onGridWidthUpdated() { } + + fun setNewSceneFrames(frames: List, framesSize: Vector2f) + { + this.frames = frames + this.framesSize = framesSize + onSceneFramesUpdated() + } + + fun setFramesSelection(selection: List) { + selectedFrames = selection + updateGridWidth() + onFramesSelectionUpdated() + } + + fun setNewGridWidth(gridWidth: Int) { + if (gridWidth < 1) { + println("The width of the frames grid should be a positive value!") + return + } + + installedGridWidth = gridWidth + updateGridWidth() + onGridWidthUpdated() + } open fun render() { shaderProgram.use() @@ -47,6 +86,10 @@ abstract class Renderer(protected val window: Window) : Comparable { shaderProgram.detach() } + protected fun updateGridWidth() { + this.gridWidth = min(installedGridWidth, selectedFrames.count()) + } + override fun compareTo(other: Renderer): Int { return if (renderPriority < other.renderPriority) { -1 @@ -112,4 +155,14 @@ abstract class Renderer(protected val window: Window) : Comparable { private fun rebufferBatches() { batches.forEach { it.rebuffer() } } + + companion object { + const val ProjectionUniformName = "uProjection" + const val GridWidthUniformName = "uGridWidth" + const val FramesSpacingUniformName = "uFramesSpacing" + + + const val DefaultGridWidth = 10 + const val FramesSpacing = 0.02f + } } diff --git a/src/main/resources/engine/shaders/frame/frame.geom b/src/main/resources/engine/shaders/frame/frame.geom index 00488b98..bd7bb8da 100644 --- a/src/main/resources/engine/shaders/frame/frame.geom +++ b/src/main/resources/engine/shaders/frame/frame.geom @@ -5,6 +5,7 @@ uniform mat4 uModel; uniform int uGridWidth; uniform ivec2 uBuffersSize; uniform float uTexturesRatio; +uniform float uFramesSpacing; in VS_OUT { int frameID; @@ -30,8 +31,8 @@ void main() { float texID = float(bufferY * uBuffersSize.x + bufferX); vec4 initialPosition = vec4( - gl_in[0].gl_Position.x * uTexturesRatio, - gl_in[0].gl_Position.y, + (gl_in[0].gl_Position.x * uTexturesRatio + uFramesSpacing * frameX), + gl_in[0].gl_Position.y + uFramesSpacing * frameY, gl_in[0].gl_Position.z, gl_in[0].gl_Position.w );