package ru.dbotthepony.kstarbound.client import org.lwjgl.opengl.GL46.* import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf import ru.dbotthepony.kstarbound.client.gl.VertexTransformers import ru.dbotthepony.kstarbound.client.render.ILayeredRenderer import ru.dbotthepony.kstarbound.client.render.renderLayeredList import ru.dbotthepony.kstarbound.defs.ParallaxPrototype import ru.dbotthepony.kstarbound.math.encasingChunkPosAABB import ru.dbotthepony.kstarbound.util.DoubleEdgeProgression import ru.dbotthepony.kstarbound.world.* import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kvector.matrix.Matrix4fStack import ru.dbotthepony.kvector.util2d.AABB class ClientWorld( val client: StarboundClient, seed: Long, widthInChunks: Int, ) : World(seed, widthInChunks) { init { physics.debugDraw = client.gl.box2dRenderer } override fun chunkFactory(pos: ChunkPos): ClientChunk { return ClientChunk( world = this, pos = pos, ) } var parallax: ParallaxPrototype? = null /** * Отрисовывает этот с обрезкой невидимой геометрии с точки зрения [size] в Starbound Units * * Все координаты "местности" сохраняются, поэтому, если отрисовывать слишком далеко от 0, 0 * то геометрия может начать искажаться из-за погрешности плавающей запятой */ fun render( size: AABB, ) { val parallax = parallax if (parallax != null) { client.gl.matrixStack.push() client.gl.matrixStack.translateWithMultiplication(y = parallax.verticalOrigin.toFloat() - 20f) client.gl.shaderVertexTexture.use() val stateful = client.gl.flat2DTexturedQuads.statefulSmall val builder = stateful.builder client.gl.activeTexture = 0 client.gl.shaderVertexTexture["_texture"] = 0 val centre = size.centre for (layer in parallax.layers) { client.gl.matrixStack.push() client.gl.matrixStack.translateWithMultiplication(x = layer.offset.x.toFloat() / PIXELS_IN_STARBOUND_UNITf, y = layer.offset.y.toFloat() / PIXELS_IN_STARBOUND_UNITf) client.gl.shaderVertexTexture.transform.set(client.gl.matrixStack.last) val texture = client.gl.loadNamedTextureSafe("/parallax/images/${layer.kind}/base/1.png") texture.bind() texture.textureMagFilter = GL_NEAREST texture.textureMinFilter = GL_NEAREST builder.begin() for (xPos in DoubleEdgeProgression()) { var x0 = xPos.toFloat() * texture.width / PIXELS_IN_STARBOUND_UNITf var x1 = (xPos + 1f) * texture.width / PIXELS_IN_STARBOUND_UNITf val diffx = layer.parallax.x * centre.x - centre.x val diffy = (layer.parallax.y * (centre.y + 20.0) - centre.y - 20.0).toFloat() / PIXELS_IN_STARBOUND_UNITf x0 += diffx.toFloat() / PIXELS_IN_STARBOUND_UNITf x1 += diffx.toFloat() / PIXELS_IN_STARBOUND_UNITf builder.quadZ(x0, diffy, x1, diffy + texture.height.toFloat() / PIXELS_IN_STARBOUND_UNITf, 1f, VertexTransformers.uv(0f, 1f, 1f, 0f)) /*if (x1 < size.mins.x) { break }*/ if (xPos < -40) { break } } stateful.upload() stateful.draw() client.gl.matrixStack.pop() } client.gl.matrixStack.pop() } val determineRenderers = ArrayList() for (chunk in collectPositionAware(size.encasingChunkPosAABB())) { determineRenderers.add(chunk.second.BakedLayeredRenderer(chunk.first)) chunk.second.bake() } renderLayeredList(client.gl.matrixStack, determineRenderers) physics.debugDraw() /*for (renderer in determineRenderers) { renderer.renderDebug() }*/ } override fun thinkInner(delta: Double) { val copy = arrayOfNulls(entities.size) var i = 0 for (ent in entities) { copy[i++] = ent } for (ent in copy) { ent!!.think(delta) } } }