diff --git a/build.gradle.kts b/build.gradle.kts index 3500cb41..c660868a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -82,8 +82,7 @@ dependencies { implementation("net.java.dev.jna:jna:5.13.0") implementation("com.github.jnr:jnr-ffi:2.2.13") - implementation("ru.dbotthepony:kbox2d:2.4.1-1.0.2") - implementation("ru.dbotthepony:kvector:2.10.2") + implementation("ru.dbotthepony:kvector:2.11.0") implementation("com.github.ben-manes.caffeine:caffeine:3.1.5") } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Constants.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Constants.kt deleted file mode 100644 index bf194b95..00000000 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Constants.kt +++ /dev/null @@ -1,8 +0,0 @@ -package ru.dbotthepony.kstarbound - -const val METRES_IN_STARBOUND_UNIT = 0.5 -const val METRES_IN_STARBOUND_UNITf = 0.5f - -const val PIXELS_IN_STARBOUND_UNITi = 8 -const val PIXELS_IN_STARBOUND_UNIT = PIXELS_IN_STARBOUND_UNITi.toDouble() -const val PIXELS_IN_STARBOUND_UNITf = PIXELS_IN_STARBOUND_UNITi.toFloat() diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt index dfc934d9..80a5630c 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt @@ -20,6 +20,7 @@ import ru.dbotthepony.kstarbound.io.readVarInt import ru.dbotthepony.kstarbound.util.AssetPathStack import ru.dbotthepony.kstarbound.world.entities.WorldObject import ru.dbotthepony.kstarbound.world.physics.Poly +import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.vector.Vector2d import java.io.BufferedInputStream import java.io.ByteArrayInputStream @@ -122,12 +123,12 @@ fun main() { val item = Registries.items.values.random() val rand = Random() - for (i in 0 .. 0) { + for (i in 0 .. 128) { val item = ItemEntity(client.world!!, item.value) - item.position = Vector2d(225.0 + i, 685.0) + item.position = Vector2d(225.0 - i, 685.0) item.spawn() - item.velocity = Vector2d(0.01, -0.08) + item.velocity = Vector2d(rand.nextDouble() * 32.0 - 16.0, rand.nextDouble() * 32.0 - 16.0) //item.movement.applyVelocity(Vector2d(rand.nextDouble() * 1000.0 - 500.0, rand.nextDouble() * 1000.0 - 500.0)) } @@ -164,53 +165,6 @@ fun main() { client.font.render("World chunk: ${client.world!!.chunkFromCell(client.camera.pos)}", y = 180f, scale = 0.25f) } - var p = Poly(Starbound.gson.fromJson>("""[ [1.75, 2.55], [2.25, 2.05], [2.75, -3.55], [2.25, -3.95], [-2.25, -3.95], [-2.75, -3.55], [-2.25, 2.05], [-1.75, 2.55] ]""", TypeToken.getParameterized(ImmutableList::class.java, Vector2d::class.java).type)) - val polies = ArrayList() - - val box = Poly(listOf(Vector2d(-0.5, -0.5), Vector2d(-0.5, 0.5), Vector2d(0.5, 0.5), Vector2d(0.5, -0.5))) - p = box - val triangle = Poly(listOf(Vector2d(-0.5, -0.5), Vector2d(0.5, 0.5), Vector2d(0.5, -0.5))) - - //polies.add(triangle + Vector2d(0.0, -1.5)) - polies.add(box) - polies.add(box + Vector2d(1.0)) - //polies.add(box + Vector2d(1.0, -1.0)) - //polies.add(box + Vector2d(1.0, -2.0)) - //polies.add(box + Vector2d(1.0, -3.0)) - - //client.foregroundExecutor.scheduleAtFixedRate({ p.intersect(p2)?.let { p += it; println(it) } }, 1, 1, TimeUnit.SECONDS) - - p += client.camera.pos - - for (i in polies.indices) - polies[i] = polies[i] + client.camera.pos - - client.onPostDrawWorld { - //client.camera.pos.x = ent.pos.x.toFloat() - //client.camera.pos.y = ent.pos.y.toFloat() - - p += client.screenToWorld(client.mouseCoordinates) - p.aabb.centre - - for (i in 0 until 10) { - val intersects = ArrayList() - - polies.forEach { p.intersect(it)?.let { intersects.add(it) } } - - if (intersects.isEmpty()) - break - else - p += intersects.max() - } - - p.render() - polies.forEach { it.render() } - } - - client.box2dRenderer.drawShapes = false - client.box2dRenderer.drawPairs = false - client.box2dRenderer.drawAABB = false - client.box2dRenderer.drawJoints = false - //ent.spawn() client.input.addScrollCallback { _, x, y -> diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt index d94aa9f3..483c8418 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt @@ -60,6 +60,7 @@ import ru.dbotthepony.kstarbound.util.WriteOnce import ru.dbotthepony.kstarbound.util.filterNotNull import ru.dbotthepony.kstarbound.util.set import ru.dbotthepony.kstarbound.util.traverseJsonPath +import ru.dbotthepony.kstarbound.world.physics.Poly import java.io.* import java.lang.ref.Cleaner import java.text.DateFormat @@ -163,7 +164,6 @@ object Starbound : ISBFileLocator { registerTypeAdapter(Vector2iTypeAdapter) registerTypeAdapter(Vector4iTypeAdapter) registerTypeAdapter(Vector4dTypeAdapter) - registerTypeAdapter(PolyTypeAdapter) registerTypeAdapter(LineF::Adapter) // Функции @@ -192,6 +192,8 @@ object Starbound : ISBFileLocator { registerTypeAdapter(Image.Companion) + registerTypeAdapterFactory(Poly.Companion) + registerTypeAdapterFactory(with(RegistryReferenceFactory()) { add(Registries.tiles) add(Registries.tileModifiers) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt index eb06a766..58f97d45 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt @@ -15,8 +15,8 @@ import org.lwjgl.system.MemoryStack import org.lwjgl.system.MemoryUtil import ru.dbotthepony.kstarbound.LoadingLog import ru.dbotthepony.kstarbound.util.ManualExecutorService -import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNIT -import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf +import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNIT +import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNITf import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.client.freetype.FreeType import ru.dbotthepony.kstarbound.client.freetype.InvalidArgumentException @@ -41,7 +41,6 @@ import ru.dbotthepony.kstarbound.client.gl.shader.UberShader import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder import ru.dbotthepony.kstarbound.client.input.UserInput -import ru.dbotthepony.kstarbound.client.render.Box2DRenderer import ru.dbotthepony.kstarbound.client.render.Camera import ru.dbotthepony.kstarbound.client.render.Font import ru.dbotthepony.kstarbound.client.render.LayeredRenderer @@ -382,7 +381,6 @@ class StarboundClient : Closeable { val freeType = FreeType() val font = Font() - val box2dRenderer = Box2DRenderer() val programs = GLPrograms() init { @@ -683,7 +681,8 @@ class StarboundClient : Closeable { viewportRectangle = AABB.rectangle( camera.pos, viewportWidth / settings.zoom / PIXELS_IN_STARBOUND_UNIT, - viewportHeight / settings.zoom / PIXELS_IN_STARBOUND_UNIT) + viewportHeight / settings.zoom / PIXELS_IN_STARBOUND_UNIT + ) viewportCellX = roundTowardsNegativeInfinity(viewportRectangle.mins.x) - 16 viewportCellY = roundTowardsNegativeInfinity(viewportRectangle.mins.y) - 16 @@ -855,10 +854,6 @@ class StarboundClient : Closeable { layers.render() - box2dRenderer.begin() - world.physics.debugDraw() - box2dRenderer.render() - for (lambda in onPostDrawWorld) { lambda.invoke() } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/Box2DRenderer.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/Box2DRenderer.kt deleted file mode 100644 index 76ce24cc..00000000 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/Box2DRenderer.kt +++ /dev/null @@ -1,137 +0,0 @@ -package ru.dbotthepony.kstarbound.client.render - -import org.lwjgl.opengl.GL45.* -import ru.dbotthepony.kbox2d.api.IDebugDraw -import ru.dbotthepony.kbox2d.api.Transform -import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNIT -import ru.dbotthepony.kstarbound.client.StarboundClient -import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType -import ru.dbotthepony.kstarbound.client.gl.vertex.StreamVertexBuilder -import ru.dbotthepony.kstarbound.client.gl.vertex.VertexAttributes -import ru.dbotthepony.kvector.arrays.Matrix3f -import ru.dbotthepony.kvector.vector.RGBAColor -import ru.dbotthepony.kvector.vector.Vector2d -import kotlin.math.cos -import kotlin.math.sin - -class Box2DRenderer : IDebugDraw { - val state = StarboundClient.current() - - override var drawShapes: Boolean = false - override var drawJoints: Boolean = false - override var drawAABB: Boolean = false - override var drawTreeAABB: Boolean = false - override var drawPairs: Boolean = false - override var drawCenterOfMess: Boolean = false - - private val identity = Matrix3f.identity() - - private val lines = StreamVertexBuilder(VertexAttributes.POSITION_COLOR, GeometryType.LINES) - private val triangles = StreamVertexBuilder(VertexAttributes.POSITION_COLOR, GeometryType.TRIANGLES) - - fun begin() { - lines.builder.begin() - triangles.builder.begin() - } - - fun render() { - if (lines.builder.isEmpty() && triangles.builder.isEmpty()) return - - lines.upload(GL_STREAM_DRAW) - triangles.upload(GL_STREAM_DRAW) - - state.programs.positionColor.use() - state.programs.positionColor.colorMultiplier = RGBAColor.WHITE - state.programs.positionColor.modelMatrix = identity - - lines.draw(GL_LINES) - triangles.draw(GL_TRIANGLES) - } - - override fun drawPolygon(vertices: List, color: RGBAColor) { - require(vertices.size > 1) { "Vertex list had only ${vertices.size} namings in it" } - - if (!vertices.any { state.viewportRectangle.isInside(it) }) return - - for (i in vertices.indices) { - val current = vertices[i] - val next = vertices[(i + 1) % vertices.size] - lines.builder.vertex(state.stack.last(), current).color(color) - lines.builder.vertex(state.stack.last(), next).color(color) - } - } - - private fun drawSolid(vertices: List, color: RGBAColor) { - require(vertices.size >= 3) { "Vertex list had only ${vertices.size} namings in it" } - - if (!vertices.any { state.viewportRectangle.isInside(it) }) return - - val zero = vertices[0] - - for (i in 1 until vertices.size) { - val current = vertices[i] - val next = vertices[(i + 1) % vertices.size] - triangles.builder.vertex(state.stack.last(), zero.x.toFloat(), zero.y.toFloat()).color(color) - triangles.builder.vertex(state.stack.last(), current.x.toFloat(), current.y.toFloat()).color(color) - triangles.builder.vertex(state.stack.last(), next.x.toFloat(), next.y.toFloat()).color(color) - } - } - - override fun drawSolidPolygon(vertices: List, color: RGBAColor) { - drawSolid(vertices, color.copy(alpha = 0.5f)) - drawPolygon(vertices, color) - } - - override fun drawCircle(center: Vector2d, radius: Double, color: RGBAColor) { - val vertexList = ArrayList() - - for (i in 0 until 360 step 15) { - val rad = Math.toRadians(i.toDouble()) - val c = cos(rad) - val s = sin(rad) - - vertexList.add(Vector2d( - center.x + c * radius, - center.y + s * radius - )) - } - - drawPolygon(vertexList, color) - } - - override fun drawSolidCircle(center: Vector2d, radius: Double, axis: Vector2d, color: RGBAColor) { - val vertexList = ArrayList() - - for (i in 0 until 360 step 15) { - val rad = Math.toRadians(i.toDouble()) - val c = cos(rad) - val s = sin(rad) - - vertexList.add(Vector2d( - center.x + c * radius, - center.y + s * radius - )) - } - - drawSolidPolygon(vertexList, color.copy(alpha = 0.5f)) - drawPolygon(vertexList, color) - drawPolygon(listOf(center, center + axis * radius), color) - } - - override fun drawSegment(p1: Vector2d, p2: Vector2d, color: RGBAColor) { - drawPolygon(listOf(p1, p2), color) - } - - override fun drawTransform(xf: Transform) { - TODO("Not yet implemented") - } - - override fun drawPoint(p: Vector2d, size: Double, color: RGBAColor) { - drawSolid(listOf( - Vector2d(x = p.x - size / (PIXELS_IN_STARBOUND_UNIT * 2.0), y = p.y - size / (PIXELS_IN_STARBOUND_UNIT * 2.0)), - Vector2d(x = p.x + size / (PIXELS_IN_STARBOUND_UNIT * 2.0), y = p.y - size / (PIXELS_IN_STARBOUND_UNIT * 2.0)), - Vector2d(x = p.x + size / (PIXELS_IN_STARBOUND_UNIT * 2.0), y = p.y + size / (PIXELS_IN_STARBOUND_UNIT * 2.0)), - Vector2d(x = p.x - size / (PIXELS_IN_STARBOUND_UNIT * 2.0), y = p.y + size / (PIXELS_IN_STARBOUND_UNIT * 2.0)), - ), color) - } -} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt index 4df63da4..0df41eee 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/TileRenderer.kt @@ -5,7 +5,7 @@ import com.github.benmanes.caffeine.cache.Caffeine import com.github.benmanes.caffeine.cache.Scheduler import org.apache.logging.log4j.LogManager import org.lwjgl.opengl.GL45.* -import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf +import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNITf import ru.dbotthepony.kstarbound.Registries import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.gl.* diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt index 0e35ee90..b265c93a 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt @@ -5,12 +5,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongArraySet import it.unimi.dsi.fastutil.objects.ObjectArrayList import it.unimi.dsi.fastutil.objects.ReferenceArraySet -import ru.dbotthepony.kbox2d.api.BodyDef -import ru.dbotthepony.kbox2d.api.BodyType -import ru.dbotthepony.kbox2d.api.FixtureDef -import ru.dbotthepony.kbox2d.collision.shapes.PolygonShape -import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf -import ru.dbotthepony.kstarbound.Starbound +import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNITf import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.render.ConfiguredMesh import ru.dbotthepony.kstarbound.client.render.LayeredRenderer @@ -21,27 +16,18 @@ import ru.dbotthepony.kstarbound.math.roundTowardsNegativeInfinity import ru.dbotthepony.kstarbound.math.roundTowardsPositiveInfinity import ru.dbotthepony.kstarbound.world.CHUNK_SIZE import ru.dbotthepony.kstarbound.world.ChunkPos -import ru.dbotthepony.kstarbound.world.NeverFilter -import ru.dbotthepony.kstarbound.world.NonEmptyFilter -import ru.dbotthepony.kstarbound.world.RayCastResult import ru.dbotthepony.kstarbound.world.World import ru.dbotthepony.kstarbound.world.api.ITileAccess import ru.dbotthepony.kstarbound.world.api.OffsetCellAccess import ru.dbotthepony.kstarbound.world.api.TileView -import ru.dbotthepony.kstarbound.world.castRay import ru.dbotthepony.kstarbound.world.positiveModulo import ru.dbotthepony.kvector.api.IStruct2i import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.vector.RGBAColor -import ru.dbotthepony.kvector.vector.Vector2d import ru.dbotthepony.kvector.vector.Vector2f import ru.dbotthepony.kvector.vector.Vector2i import java.util.concurrent.Callable -import java.util.concurrent.ForkJoinPool import java.util.concurrent.Future -import kotlin.math.PI -import kotlin.math.cos -import kotlin.math.sin class ClientWorld( val client: StarboundClient, @@ -50,10 +36,6 @@ class ClientWorld( loopX: Boolean = false, loopY: Boolean = false ) : World(seed, size, loopX, loopY) { - init { - physics.debugDraw = client.box2dRenderer - } - private fun determineChunkSize(cells: Int): Int { for (i in 32 downTo 1) { if (cells % i == 0) { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/BaseMovementParameters.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/BaseMovementParameters.kt index 93b0cb23..e928707f 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/BaseMovementParameters.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/BaseMovementParameters.kt @@ -7,11 +7,11 @@ import ru.dbotthepony.kstarbound.util.KOptional @JsonImplementation(BaseMovementParameters.Impl::class) interface BaseMovementParameters { - val mass: KOptional - val gravityMultiplier: KOptional - val liquidBuoyancy: KOptional - val airBuoyancy: KOptional - val bounceFactor: KOptional + val mass: KOptional + val gravityMultiplier: KOptional + val liquidBuoyancy: KOptional + val airBuoyancy: KOptional + val bounceFactor: KOptional // If set to true, during an update that has more than one internal movement // step, the movement will stop on the first bounce. @@ -21,50 +21,50 @@ interface BaseMovementParameters { // other directions (within a set limit). Allows smooth sliding along // horizontal ground without losing horizontal speed. val enableSurfaceSlopeCorrection: KOptional - val slopeSlidingFactor: KOptional - val maxMovementPerStep: KOptional - val maximumCorrection: KOptional - val speedLimit: KOptional + val slopeSlidingFactor: KOptional + val maxMovementPerStep: KOptional + val maximumCorrection: KOptional + val speedLimit: KOptional val stickyCollision: KOptional - val stickyForce: KOptional + val stickyForce: KOptional - val airFriction: KOptional - val liquidFriction: KOptional - val groundFriction: KOptional + val airFriction: KOptional + val liquidFriction: KOptional + val groundFriction: KOptional val collisionEnabled: KOptional val frictionEnabled: KOptional val gravityEnabled: KOptional - val maximumPlatformCorrection: KOptional - val maximumPlatformCorrectionVelocityFactor: KOptional + val maximumPlatformCorrection: KOptional + val maximumPlatformCorrectionVelocityFactor: KOptional val physicsEffectCategories: KOptional> @JsonFactory data class Impl( - override val mass: KOptional = KOptional.empty(), - override val gravityMultiplier: KOptional = KOptional.empty(), - override val liquidBuoyancy: KOptional = KOptional.empty(), - override val airBuoyancy: KOptional = KOptional.empty(), - override val bounceFactor: KOptional = KOptional.empty(), + override val mass: KOptional = KOptional.empty(), + override val gravityMultiplier: KOptional = KOptional.empty(), + override val liquidBuoyancy: KOptional = KOptional.empty(), + override val airBuoyancy: KOptional = KOptional.empty(), + override val bounceFactor: KOptional = KOptional.empty(), override val stopOnFirstBounce: KOptional = KOptional.empty(), override val enableSurfaceSlopeCorrection: KOptional = KOptional.empty(), - override val slopeSlidingFactor: KOptional = KOptional.empty(), - override val maxMovementPerStep: KOptional = KOptional.empty(), - override val maximumCorrection: KOptional = KOptional.empty(), - override val speedLimit: KOptional = KOptional.empty(), + override val slopeSlidingFactor: KOptional = KOptional.empty(), + override val maxMovementPerStep: KOptional = KOptional.empty(), + override val maximumCorrection: KOptional = KOptional.empty(), + override val speedLimit: KOptional = KOptional.empty(), override val stickyCollision: KOptional = KOptional.empty(), - override val stickyForce: KOptional = KOptional.empty(), - override val airFriction: KOptional = KOptional.empty(), - override val liquidFriction: KOptional = KOptional.empty(), - override val groundFriction: KOptional = KOptional.empty(), + override val stickyForce: KOptional = KOptional.empty(), + override val airFriction: KOptional = KOptional.empty(), + override val liquidFriction: KOptional = KOptional.empty(), + override val groundFriction: KOptional = KOptional.empty(), override val collisionEnabled: KOptional = KOptional.empty(), override val frictionEnabled: KOptional = KOptional.empty(), override val gravityEnabled: KOptional = KOptional.empty(), - override val maximumPlatformCorrection: KOptional = KOptional.empty(), - override val maximumPlatformCorrectionVelocityFactor: KOptional = KOptional.empty(), + override val maximumPlatformCorrection: KOptional = KOptional.empty(), + override val maximumPlatformCorrectionVelocityFactor: KOptional = KOptional.empty(), override val physicsEffectCategories: KOptional> = KOptional.empty(), ) : BaseMovementParameters { fun merge(other: Impl): Impl { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/Drawable.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/Drawable.kt index 1fd33cf2..877180f9 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/Drawable.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/Drawable.kt @@ -8,7 +8,7 @@ import com.google.gson.reflect.TypeToken import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonWriter import org.apache.logging.log4j.LogManager -import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf +import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNITf import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType import ru.dbotthepony.kstarbound.client.render.IGeometryLayer diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/MovementParameters.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/MovementParameters.kt index 07b60aa3..24e6dd8c 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/MovementParameters.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/MovementParameters.kt @@ -1,10 +1,9 @@ package ru.dbotthepony.kstarbound.defs -import com.google.common.collect.ImmutableList import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFlat import ru.dbotthepony.kstarbound.util.KOptional -import ru.dbotthepony.kvector.vector.Vector2d +import ru.dbotthepony.kstarbound.world.physics.Poly @JsonFactory data class MovementParameters( @@ -12,7 +11,7 @@ data class MovementParameters( val base: BaseMovementParameters.Impl = BaseMovementParameters.Impl(), val discontinuityThreshold: KOptional = KOptional.empty(), - val collisionPoly: KOptional> = KOptional.empty(), + val collisionPoly: KOptional = KOptional.empty(), val ignorePlatformCollision: KOptional = KOptional.empty(), val restDuration: KOptional = KOptional.empty(), ) : BaseMovementParameters by base { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/image/Image.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/image/Image.kt index 0bf1c1fb..30004c53 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/image/Image.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/image/Image.kt @@ -20,8 +20,8 @@ import org.apache.logging.log4j.LogManager import org.lwjgl.opengl.GL45 import org.lwjgl.stb.STBImage import org.lwjgl.system.MemoryUtil -import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNIT -import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITi +import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNIT +import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNITi import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.api.IStarboundFile import ru.dbotthepony.kstarbound.client.StarboundClient diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/object/ObjectOrientation.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/object/ObjectOrientation.kt index e9e551a3..601fb53d 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/object/ObjectOrientation.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/object/ObjectOrientation.kt @@ -10,7 +10,7 @@ import com.google.gson.TypeAdapter import com.google.gson.reflect.TypeToken import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonWriter -import ru.dbotthepony.kstarbound.PIXELS_IN_STARBOUND_UNITf +import ru.dbotthepony.kstarbound.world.PIXELS_IN_STARBOUND_UNITf import ru.dbotthepony.kstarbound.client.render.RenderLayer import ru.dbotthepony.kstarbound.defs.Drawable import ru.dbotthepony.kstarbound.defs.JsonReference diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/player/PlayerMovementParameters.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/player/PlayerMovementParameters.kt index 81763402..90b2173f 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/player/PlayerMovementParameters.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/player/PlayerMovementParameters.kt @@ -1,14 +1,12 @@ package ru.dbotthepony.kstarbound.defs.player -import com.google.common.collect.ImmutableList -import com.google.common.collect.ImmutableSet import ru.dbotthepony.kstarbound.defs.BaseMovementParameters import ru.dbotthepony.kstarbound.defs.JumpProfile import ru.dbotthepony.kstarbound.io.json.builder.JsonAlias import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory import ru.dbotthepony.kstarbound.io.json.builder.JsonFlat import ru.dbotthepony.kstarbound.util.KOptional -import ru.dbotthepony.kvector.vector.Vector2d +import ru.dbotthepony.kstarbound.world.physics.Poly @JsonFactory data class PlayerMovementParameters( @@ -16,9 +14,9 @@ data class PlayerMovementParameters( val base: BaseMovementParameters.Impl = BaseMovementParameters.Impl(), @JsonAlias("collisionPoly") - val standingPoly: KOptional> = KOptional.empty(), + val standingPoly: KOptional = KOptional.empty(), @JsonAlias("collisionPoly") - val crouchingPoly: KOptional> = KOptional.empty(), + val crouchingPoly: KOptional = KOptional.empty(), val walkSpeed: KOptional = KOptional.empty(), val runSpeed: KOptional = KOptional.empty(), diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/BuiltinMetaMaterials.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/BuiltinMetaMaterials.kt index 0469c4d2..a07ca8aa 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/BuiltinMetaMaterials.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/BuiltinMetaMaterials.kt @@ -2,7 +2,7 @@ package ru.dbotthepony.kstarbound.defs.tile import com.google.common.collect.ImmutableList import ru.dbotthepony.kstarbound.defs.AssetReference -import ru.dbotthepony.kstarbound.defs.CollisionType +import ru.dbotthepony.kstarbound.world.physics.CollisionType import ru.dbotthepony.kstarbound.defs.ThingDescription object BuiltinMetaMaterials { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDefinition.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDefinition.kt index e55e21da..0e4e24e3 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDefinition.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/tile/TileDefinition.kt @@ -2,7 +2,7 @@ package ru.dbotthepony.kstarbound.defs.tile import com.google.common.collect.ImmutableList import ru.dbotthepony.kstarbound.defs.AssetReference -import ru.dbotthepony.kstarbound.defs.CollisionType +import ru.dbotthepony.kstarbound.world.physics.CollisionType import ru.dbotthepony.kstarbound.defs.IThingWithDescription import ru.dbotthepony.kstarbound.defs.ThingDescription import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/math/Poly.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/math/Poly.kt deleted file mode 100644 index 26930c97..00000000 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/math/Poly.kt +++ /dev/null @@ -1,43 +0,0 @@ -package ru.dbotthepony.kstarbound.math - -import com.google.common.collect.ImmutableList -import com.google.gson.TypeAdapter -import com.google.gson.stream.JsonReader -import com.google.gson.stream.JsonToken -import com.google.gson.stream.JsonWriter -import ru.dbotthepony.kstarbound.io.json.Vector2dTypeAdapter -import ru.dbotthepony.kvector.vector.Vector2d - -class Poly(vararg points: Vector2d) { - val points: List = ImmutableList.copyOf(points) - - override fun toString(): String { - return "Poly($points)" - } -} - -object PolyTypeAdapter : TypeAdapter() { - override fun write(out: JsonWriter, value: Poly) { - `out`.beginArray() - - for (point in value.points) { - Vector2dTypeAdapter.write(out, point) - } - - `out`.endArray() - } - - override fun read(`in`: JsonReader): Poly { - `in`.beginArray() - - val points = mutableListOf() - - while (`in`.peek() == JsonToken.BEGIN_ARRAY) { - points.add(Vector2dTypeAdapter.read(`in`)) - } - - `in`.endArray() - - return Poly(*points.toTypedArray()) - } -} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt index b95e8dd2..3ad2f794 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt @@ -1,10 +1,6 @@ package ru.dbotthepony.kstarbound.world import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet -import ru.dbotthepony.kbox2d.api.BodyDef -import ru.dbotthepony.kbox2d.api.FixtureDef -import ru.dbotthepony.kbox2d.collision.shapes.PolygonShape -import ru.dbotthepony.kbox2d.dynamics.B2Fixture import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier @@ -49,8 +45,6 @@ abstract class Chunk, This : Chunk, This : Chunk() private val collisionCacheView = Collections.unmodifiableCollection(collisionCache) - private val body by lazy { - world.physics.createBody(BodyDef( - position = pos.tile.toDoubleVector(), - userData = this - )) - } - - private val collisionChains = ArrayList() - protected open fun foregroundChanges(cell: Cell) { cellChanges(cell) tileChangeset++ - - collisionChangeset++ foregroundChangeset++ - markPhysicsDirty() } protected open fun backgroundChanges(cell: Cell) { cellChanges(cell) tileChangeset++ - backgroundChangeset++ } @@ -147,14 +128,6 @@ abstract class Chunk, This : Chunk, This : Chunk { - bakeCollisions() - return collisionCacheView - } - override fun randomLongFor(x: Int, y: Int): Long { return world.randomLongFor(x or pos.x shl CHUNK_SIZE_BITS, y or pos.y shl CHUNK_SIZE_BITS) } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Constants.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Constants.kt new file mode 100644 index 00000000..7c039373 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Constants.kt @@ -0,0 +1,15 @@ +package ru.dbotthepony.kstarbound.world + +const val METRES_IN_STARBOUND_UNIT = 0.5 +const val METRES_IN_STARBOUND_UNITf = 0.5f +const val PIXELS_IN_STARBOUND_UNITi = 8 +const val PIXELS_IN_STARBOUND_UNIT = PIXELS_IN_STARBOUND_UNITi.toDouble() +const val PIXELS_IN_STARBOUND_UNITf = PIXELS_IN_STARBOUND_UNITi.toFloat() + +const val CHUNK_SIZE_BITS = 5 +const val CHUNK_SIZE_MASK = 1 or 2 or 4 or 8 or 16 +const val CHUNK_SIZE = 1 shl CHUNK_SIZE_BITS // 32 +const val CHUNK_SIZE_FF = CHUNK_SIZE - 1 +const val CHUNK_SIZEd = CHUNK_SIZE.toDouble() + +const val EARTH_FREEFALL_ACCELERATION = 9.8312 / METRES_IN_STARBOUND_UNIT diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Raycasting.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Raycasting.kt index 089b55f6..aa9e3366 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Raycasting.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Raycasting.kt @@ -1,6 +1,6 @@ package ru.dbotthepony.kstarbound.world -import ru.dbotthepony.kstarbound.METRES_IN_STARBOUND_UNIT +import ru.dbotthepony.kstarbound.world.METRES_IN_STARBOUND_UNIT import ru.dbotthepony.kstarbound.math.roundTowardsNegativeInfinity import ru.dbotthepony.kstarbound.world.api.ICellAccess import ru.dbotthepony.kstarbound.world.api.IChunkCell @@ -10,8 +10,6 @@ import kotlin.collections.ArrayList import kotlin.math.pow import kotlin.math.sqrt -const val EARTH_FREEFALL_ACCELERATION = 9.8312 / METRES_IN_STARBOUND_UNIT - data class RayCastResult( val traversedTiles: List, val hitTile: HitCell?, diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt index d5070a5c..3d199b84 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt @@ -5,14 +5,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet -import ru.dbotthepony.kbox2d.api.ContactImpulse -import ru.dbotthepony.kbox2d.api.IContactFilter -import ru.dbotthepony.kbox2d.api.IContactListener -import ru.dbotthepony.kbox2d.api.Manifold -import ru.dbotthepony.kbox2d.dynamics.B2Fixture -import ru.dbotthepony.kbox2d.dynamics.B2World -import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact -import ru.dbotthepony.kstarbound.Starbound +import ru.dbotthepony.kstarbound.client.world.ClientWorld import ru.dbotthepony.kstarbound.math.* import ru.dbotthepony.kstarbound.util.ManualExecutorService import ru.dbotthepony.kstarbound.world.api.ICellAccess @@ -20,6 +13,9 @@ import ru.dbotthepony.kstarbound.world.api.IChunkCell import ru.dbotthepony.kstarbound.world.api.TileView import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kstarbound.world.entities.WorldObject +import ru.dbotthepony.kstarbound.world.physics.CollisionPoly +import ru.dbotthepony.kstarbound.world.physics.CollisionType +import ru.dbotthepony.kstarbound.world.physics.Poly import ru.dbotthepony.kvector.api.IStruct2d import ru.dbotthepony.kvector.api.IStruct2i import ru.dbotthepony.kvector.arrays.Object2DArray @@ -30,12 +26,6 @@ import java.lang.ref.ReferenceQueue import java.lang.ref.WeakReference import java.util.random.RandomGenerator -const val CHUNK_SIZE_BITS = 5 -const val CHUNK_SIZE_MASK = 1 or 2 or 4 or 8 or 16 -const val CHUNK_SIZE = 1 shl CHUNK_SIZE_BITS // 32 -const val CHUNK_SIZE_FF = CHUNK_SIZE - 1 -const val CHUNK_SIZEd = CHUNK_SIZE.toDouble() - @Suppress("UNCHECKED_CAST") abstract class World, ChunkType : Chunk>( val seed: Long, @@ -244,81 +234,7 @@ abstract class World, ChunkType : Chunk() - - val physics = B2World(Vector2d(0.0, -EARTH_FREEFALL_ACCELERATION)) - - init { - physics.contactFilter = object : IContactFilter { - override fun shouldCollide(fixtureA: B2Fixture, fixtureB: B2Fixture): Boolean { - val dataA = fixtureA.body!!.userData - val dataB = fixtureB.body!!.userData - - //if (dataA is AbstractProjectileMovementController && dataB is AbstractProjectileMovementController) { - // return false - //} - - return true - } - } - - physics.contactListener = object : IContactListener { - override fun beginContact(contact: AbstractContact) { - val dataA = contact.fixtureA.body!!.userData - val dataB = contact.fixtureB.body!!.userData - - if (dataA is IContactListener) { - dataA.beginContact(contact) - } - - if (dataB is IContactListener) { - dataB.beginContact(contact) - } - } - - override fun endContact(contact: AbstractContact) { - val dataA = contact.fixtureA.body!!.userData - val dataB = contact.fixtureB.body!!.userData - - if (dataA is IContactListener) { - dataA.endContact(contact) - } - - if (dataB is IContactListener) { - dataB.endContact(contact) - } - } - - override fun preSolve(contact: AbstractContact, oldManifold: Manifold) { - val dataA = contact.fixtureA.body!!.userData - val dataB = contact.fixtureB.body!!.userData - - if (dataA is IContactListener) { - dataA.preSolve(contact, oldManifold) - } - - if (dataB is IContactListener) { - dataB.preSolve(contact, oldManifold) - } - } - - override fun postSolve(contact: AbstractContact, impulse: ContactImpulse) { - val dataA = contact.fixtureA.body!!.userData - val dataB = contact.fixtureB.body!!.userData - - if (dataA is IContactListener) { - dataA.postSolve(contact, impulse) - } - - if (dataB is IContactListener) { - dataB.postSolve(contact, impulse) - } - } - } - } + var gravity = Vector2d(0.0, -EARTH_FREEFALL_ACCELERATION) var ticks = 0 private set @@ -326,12 +242,6 @@ abstract class World, ChunkType : Chunk, ChunkType : Chunk() - /** - * Стандартное ускорение свободного падения в Starbound Units/секунда^2 - * - * При Vector2d.ZERO = невесомость - */ - var gravity by physics::gravity - protected abstract fun chunkFactory(pos: ChunkPos): ChunkType - fun testSpace(aabb: AABB, predicate: Predicate = Predicate { it.foreground.material != null }): Boolean { + fun testSpace(aabb: AABB, predicate: Predicate = Predicate { !it.foreground.material.collisionKind.isEmpty }): Boolean { val tiles = aabb.encasingIntAABB() for (x in tiles.mins.x .. tiles.maxs.x) { @@ -375,4 +278,21 @@ abstract class World, ChunkType : Chunk { + val result = ArrayList() + val tiles = aabb.encasingIntAABB() + + for (x in tiles.mins.x .. tiles.maxs.x) { + for (y in tiles.mins.y .. tiles.maxs.y) { + val cell = getCell(x, y) ?: continue + + for (poly in cell.polies) { + result.add(CollisionPoly(poly, cell.foreground.material.collisionKind, Vector2d(EARTH_FREEFALL_ACCELERATION, 0.0))) + } + } + } + + return result + } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/IChunkCell.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/IChunkCell.kt index 71d7a6af..09198e79 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/IChunkCell.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/api/IChunkCell.kt @@ -32,9 +32,6 @@ interface IChunkCell : IStruct2i { } val polies: Collection get() { - if (foreground.material.isMeta) - return emptyList() - return listOf(rect + Vector2d(this.x.toDouble(), this.y.toDouble())) } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt index 85ee373e..7e8bdc7e 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt @@ -1,15 +1,17 @@ package ru.dbotthepony.kstarbound.world.entities +import ru.dbotthepony.kstarbound.GlobalDefaults +import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.client.StarboundClient +import ru.dbotthepony.kstarbound.defs.BaseMovementParameters import ru.dbotthepony.kstarbound.world.Chunk import ru.dbotthepony.kstarbound.world.World +import ru.dbotthepony.kstarbound.world.physics.CollisionPoly import ru.dbotthepony.kstarbound.world.physics.Poly +import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.vector.Vector2d abstract class Entity(val world: World<*, *>) { - /** - * The chunk this entity currently in, it is automatically updated on each change of [position] - */ var chunk: Chunk<*, *>? = null set(value) { if (!isSpawned) { @@ -40,16 +42,6 @@ abstract class Entity(val world: World<*, *>) { } } - - /** - * Current entity position. If entity is logical, this can only be changed - * by external means, otherwise it always stands where it is. - * - * If entity is physical, then movement controller will update this on each physics step - * to match position of physical body. - * - * Setting this value will update [chunk] immediately, if [isSpawned] is true and [isRemoved] is false. - */ var position = Vector2d() set(value) { if (field == value) @@ -68,27 +60,9 @@ abstract class Entity(val world: World<*, *>) { } } - - /** - * This entity's angle in radians. - * - * Logical entities never rotate. - * - * Alive entities usually don't rotate. - * - * If entity is physical, this value is updated by movement controller on - * each physics step to match angle of physical body. - */ - var angle: Double = 0.0 - set(value) { - if (field == value) - return - - field = value - } - var velocity = Vector2d.ZERO val hitboxes = ArrayList() + open var movementParameters: BaseMovementParameters = GlobalDefaults.movementParameters /** * Whenever is this entity spawned in world ([spawn] called). @@ -128,9 +102,6 @@ abstract class Entity(val world: World<*, *>) { } } - /** - * Заставляет сущность "думать". - */ fun think() { if (!isSpawned) { throw IllegalStateException("Tried to think before spawning in world") @@ -143,24 +114,20 @@ abstract class Entity(val world: World<*, *>) { protected abstract fun thinkInner() protected open fun move() { - position += velocity + velocity += world.gravity * Starbound.TICK_TIME_ADVANCE + position += velocity * Starbound.TICK_TIME_ADVANCE - val polies = ArrayList() - - for (x in -1 .. 1) { - for (y in -1 .. 1) { - world.chunkMap.getCell(position.x.toInt() + x, position.y.toInt() + y)?.let { - polies.addAll(it.polies) - } - } - } + if (hitboxes.isEmpty()) return for (i in 0 until 10) { - val intersects = ArrayList() + val localHitboxes = hitboxes.map { it + position } + val polies = world.queryCollisions(localHitboxes.stream().map { it.aabb }.reduce(AABB::combine).get().enlarge(1.0, 1.0)).filter { !it.type.isEmpty } + if (polies.isEmpty()) break - this.hitboxes.forEach { hitbox0 -> - val hitbox = hitbox0 + position - polies.forEach { poly -> hitbox.intersect(poly)?.let { intersects.add(it) } } + val intersects = ArrayList>() + + localHitboxes.forEach { hitbox -> + polies.forEach { poly -> hitbox.intersect(poly.poly, poly)?.let { intersects.add(it) } } } if (intersects.isEmpty()) @@ -170,7 +137,13 @@ abstract class Entity(val world: World<*, *>) { // resolve collision position += max.vector // collision response - velocity -= max.axis * velocity.dot(max.axis * 1.1) + velocity -= max.axis * velocity.dot(max.axis) + + val gravityDot = world.gravity.unitVector.dot(max.axis) + // impulse? + velocity += max.data.velocity * gravityDot * Starbound.TICK_TIME_ADVANCE + // friction + velocity *= 1.0 - gravityDot * 0.08 } } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/ItemEntity.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/ItemEntity.kt index 3c0a7b39..d6a23e95 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/ItemEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/ItemEntity.kt @@ -1,11 +1,5 @@ package ru.dbotthepony.kstarbound.world.entities -import ru.dbotthepony.kbox2d.api.ContactImpulse -import ru.dbotthepony.kbox2d.api.FixtureDef -import ru.dbotthepony.kbox2d.api.Manifold -import ru.dbotthepony.kbox2d.collision.shapes.PolygonShape -import ru.dbotthepony.kbox2d.dynamics.contact.AbstractContact -import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.defs.item.api.IItemDefinition import ru.dbotthepony.kstarbound.world.World import ru.dbotthepony.kstarbound.world.physics.Poly diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/CollisionPoly.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/CollisionPoly.kt new file mode 100644 index 00000000..ac280142 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/CollisionPoly.kt @@ -0,0 +1,9 @@ +package ru.dbotthepony.kstarbound.world.physics + +import ru.dbotthepony.kvector.vector.Vector2d + +data class CollisionPoly( + val poly: Poly, + val type: CollisionType, + val velocity: Vector2d = Vector2d.ZERO +) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/CollisionType.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/CollisionType.kt similarity index 75% rename from src/main/kotlin/ru/dbotthepony/kstarbound/defs/CollisionType.kt rename to src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/CollisionType.kt index a30e76e0..f875032d 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/CollisionType.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/CollisionType.kt @@ -1,4 +1,4 @@ -package ru.dbotthepony.kstarbound.defs +package ru.dbotthepony.kstarbound.world.physics enum class CollisionType(val isEmpty: Boolean) { NULL(true), diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/Poly.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/Poly.kt index 2cd821c2..dddcd9b9 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/Poly.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/physics/Poly.kt @@ -1,10 +1,18 @@ package ru.dbotthepony.kstarbound.world.physics import com.google.common.collect.ImmutableList +import com.google.gson.Gson +import com.google.gson.TypeAdapter +import com.google.gson.TypeAdapterFactory +import com.google.gson.reflect.TypeToken +import com.google.gson.stream.JsonReader +import com.google.gson.stream.JsonWriter import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import org.lwjgl.opengl.GL11.GL_LINES import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType +import ru.dbotthepony.kstarbound.io.json.consumeNull +import ru.dbotthepony.kstarbound.io.json.listAdapter import ru.dbotthepony.kvector.api.IStruct2d import ru.dbotthepony.kvector.arrays.Matrix3f import ru.dbotthepony.kvector.util2d.AABB @@ -63,15 +71,15 @@ class Poly private constructor(val edges: ImmutableList, val vertices: Imm } } - data class Penetration(val axis: Vector2d, val penetration: Double) : Comparable { + data class Penetration(val axis: Vector2d, val penetration: Double, val data: T) : Comparable> { val vector = axis * penetration - override fun compareTo(other: Penetration): Int { + override fun compareTo(other: Penetration<*>): Int { return penetration.absoluteValue.compareTo(other.penetration.absoluteValue) } } - operator fun plus(value: Penetration): Poly { + operator fun plus(value: Penetration<*>): Poly { val vertices = ImmutableList.Builder() val edges = ImmutableList.Builder() @@ -136,7 +144,7 @@ class Poly private constructor(val edges: ImmutableList, val vertices: Imm return Vector2d(min, max) } - fun intersect(other: Poly): Penetration? { + fun intersect(other: Poly, data: T): Penetration? { if (!aabb.intersectWeak(other.aabb)) return null @@ -144,7 +152,7 @@ class Poly private constructor(val edges: ImmutableList, val vertices: Imm edges.forEach { normals.add(it.normal) } other.edges.forEach { normals.add(it.normal) } - val intersections = ArrayList() + val intersections = ArrayList>() for (normal in normals) { val projectThis = project(normal) @@ -165,10 +173,10 @@ class Poly private constructor(val edges: ImmutableList, val vertices: Imm if (minMin <= maxMax) { // push to left - intersections.add(Penetration(normal, -minMin - width)) + intersections.add(Penetration(normal, -minMin - width, data)) } else { // push to right - intersections.add(Penetration(normal, maxMax + width)) + intersections.add(Penetration(normal, maxMax + width, data)) } } else if ( projectThis.component1() in projectOther.component1() .. projectOther.component2() && @@ -180,20 +188,20 @@ class Poly private constructor(val edges: ImmutableList, val vertices: Imm if (minMin <= maxMax) { // push to left - intersections.add(Penetration(normal, -minMin - width)) + intersections.add(Penetration(normal, -minMin - width, data)) } else { // push to right - intersections.add(Penetration(normal, maxMax + width)) + intersections.add(Penetration(normal, maxMax + width, data)) } } else if (projectOther.component1() in projectThis.component1() .. projectThis.component2()) { // other's min point is within this - intersections.add(Penetration(normal, projectOther.component1() - projectThis.component2())) + intersections.add(Penetration(normal, projectOther.component1() - projectThis.component2(), data)) } else { // other's max point in within this - intersections.add(Penetration(normal, projectOther.component2() - projectThis.component1())) + intersections.add(Penetration(normal, projectOther.component2() - projectThis.component1(), data)) } - if (intersections.last().penetration == 0.0) { + if (intersections.last().penetration.absoluteValue <= EPSILON) { return null } } @@ -205,19 +213,23 @@ class Poly private constructor(val edges: ImmutableList, val vertices: Imm return intersections.min() } + fun intersect(other: Poly) = intersect(other, Unit) + fun render(client: StarboundClient = StarboundClient.current(), color: RGBAColor = RGBAColor.LIGHT_GREEN) { val program = client.programs.position val lines = program.builder.builder program.use() lines.begin(GeometryType.LINES) + val normalSize = (aabb.width.coerceAtMost(aabb.height) / 3.0).coerceAtLeast(0.1) + for (edge in edges) { val current = edge.p0 val next = edge.p1 lines.vertex(client.stack.last(), current) lines.vertex(client.stack.last(), next) lines.vertex(client.stack.last(), (next + current) / 2.0) - lines.vertex(client.stack.last(), (next + current) / 2.0 + edge.normal * 3.0) + lines.vertex(client.stack.last(), (next + current) / 2.0 + edge.normal * normalSize) } program.modelMatrix = identity @@ -227,10 +239,40 @@ class Poly private constructor(val edges: ImmutableList, val vertices: Imm } override fun toString(): String { - return "Poly[edges = $edges]" + return "Poly[aabb = $aabb; edges = $edges]" } - companion object { + override fun equals(other: Any?): Boolean { + return other === this || other is Poly && vertices == other.vertices + } + + override fun hashCode(): Int { + return vertices.hashCode() + } + + companion object : TypeAdapterFactory { + const val EPSILON = 0.01 private val identity = Matrix3f.identity() + + override fun create(gson: Gson, type: TypeToken): TypeAdapter? { + if (type.rawType === Poly::class.java) { + return object : TypeAdapter() { + private val list = gson.listAdapter() + + override fun write(out: JsonWriter, value: Poly?) { + list.write(out, value?.vertices) + } + + override fun read(`in`: JsonReader): Poly? { + if (`in`.consumeNull()) + return null + else + return Poly(list.read(`in`)) + } + } as TypeAdapter + } + + return null + } } }