WorldGeometry.split, little more work on world bindings
This commit is contained in:
parent
3b11fcf792
commit
df329f7087
@ -154,7 +154,13 @@ fun luaFunctionN(name: String, callable: ExecutionContext.(ArgumentIterator) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(context: ExecutionContext, args: Array<out Any>) {
|
override fun invoke(context: ExecutionContext, args: Array<out Any>) {
|
||||||
callable.invoke(context, ArgumentIterator.of(context, name, args))
|
try {
|
||||||
|
callable.invoke(context, ArgumentIterator.of(context, name, args))
|
||||||
|
} catch (err: ClassCastException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
} catch (err: NullPointerException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,7 +172,13 @@ fun luaFunctionNS(name: String, callable: ExecutionContext.(ArgumentIterator) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(context: ExecutionContext, args: Array<out Any>) {
|
override fun invoke(context: ExecutionContext, args: Array<out Any>) {
|
||||||
callable.invoke(context, ArgumentIterator.of(context, name, args)).run(context)
|
try {
|
||||||
|
callable.invoke(context, ArgumentIterator.of(context, name, args)).run(context)
|
||||||
|
} catch (err: ClassCastException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
} catch (err: NullPointerException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +190,13 @@ fun luaFunctionArray(callable: ExecutionContext.(Array<out Any?>) -> Unit): LuaF
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(context: ExecutionContext, args: Array<out Any?>) {
|
override fun invoke(context: ExecutionContext, args: Array<out Any?>) {
|
||||||
callable.invoke(context, args)
|
try {
|
||||||
|
callable.invoke(context, args)
|
||||||
|
} catch (err: ClassCastException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
} catch (err: NullPointerException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,7 +208,13 @@ fun luaFunction(callable: ExecutionContext.() -> Unit): LuaFunction<*, *, *, *,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(context: ExecutionContext) {
|
override fun invoke(context: ExecutionContext) {
|
||||||
callable.invoke(context)
|
try {
|
||||||
|
callable.invoke(context)
|
||||||
|
} catch (err: ClassCastException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
} catch (err: NullPointerException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,7 +226,13 @@ fun <T> luaFunction(callable: ExecutionContext.(T) -> Unit): LuaFunction<T, *, *
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(context: ExecutionContext, arg1: T) {
|
override fun invoke(context: ExecutionContext, arg1: T) {
|
||||||
callable.invoke(context, arg1)
|
try {
|
||||||
|
callable.invoke(context, arg1)
|
||||||
|
} catch (err: ClassCastException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
} catch (err: NullPointerException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +244,13 @@ fun <T, T2> luaFunction(callable: ExecutionContext.(T, T2) -> Unit): LuaFunction
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(context: ExecutionContext, arg1: T, arg2: T2) {
|
override fun invoke(context: ExecutionContext, arg1: T, arg2: T2) {
|
||||||
callable.invoke(context, arg1, arg2)
|
try {
|
||||||
|
callable.invoke(context, arg1, arg2)
|
||||||
|
} catch (err: ClassCastException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
} catch (err: NullPointerException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +262,13 @@ fun <T, T2, T3> luaFunction(callable: ExecutionContext.(T, T2, T3) -> Unit): Lua
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(context: ExecutionContext, arg1: T, arg2: T2, arg3: T3) {
|
override fun invoke(context: ExecutionContext, arg1: T, arg2: T2, arg3: T3) {
|
||||||
callable.invoke(context, arg1, arg2, arg3)
|
try {
|
||||||
|
callable.invoke(context, arg1, arg2, arg3)
|
||||||
|
} catch (err: ClassCastException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
} catch (err: NullPointerException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,7 +280,13 @@ fun <T, T2, T3, T4> luaFunction(callable: ExecutionContext.(T, T2, T3, T4) -> Un
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(context: ExecutionContext, arg1: T, arg2: T2, arg3: T3, arg4: T4) {
|
override fun invoke(context: ExecutionContext, arg1: T, arg2: T2, arg3: T3, arg4: T4) {
|
||||||
callable.invoke(context, arg1, arg2, arg3, arg4)
|
try {
|
||||||
|
callable.invoke(context, arg1, arg2, arg3, arg4)
|
||||||
|
} catch (err: ClassCastException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
} catch (err: NullPointerException) {
|
||||||
|
throw LuaRuntimeException(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,24 @@
|
|||||||
package ru.dbotthepony.kstarbound.lua.bindings
|
package ru.dbotthepony.kstarbound.lua.bindings
|
||||||
|
|
||||||
|
import org.classdump.luna.ByteString
|
||||||
import org.classdump.luna.Table
|
import org.classdump.luna.Table
|
||||||
import org.classdump.luna.runtime.ExecutionContext
|
import org.classdump.luna.runtime.ExecutionContext
|
||||||
|
import ru.dbotthepony.kommons.collect.map
|
||||||
|
import ru.dbotthepony.kommons.collect.toList
|
||||||
|
import ru.dbotthepony.kommons.vector.Vector2d
|
||||||
import ru.dbotthepony.kstarbound.lua.LuaEnvironment
|
import ru.dbotthepony.kstarbound.lua.LuaEnvironment
|
||||||
|
import ru.dbotthepony.kstarbound.lua.from
|
||||||
import ru.dbotthepony.kstarbound.lua.get
|
import ru.dbotthepony.kstarbound.lua.get
|
||||||
|
import ru.dbotthepony.kstarbound.lua.iterator
|
||||||
import ru.dbotthepony.kstarbound.lua.luaFunction
|
import ru.dbotthepony.kstarbound.lua.luaFunction
|
||||||
import ru.dbotthepony.kstarbound.lua.set
|
import ru.dbotthepony.kstarbound.lua.set
|
||||||
import ru.dbotthepony.kstarbound.lua.toPoly
|
import ru.dbotthepony.kstarbound.lua.toPoly
|
||||||
import ru.dbotthepony.kstarbound.lua.toVector2d
|
import ru.dbotthepony.kstarbound.lua.toVector2d
|
||||||
|
import ru.dbotthepony.kstarbound.util.valueOf
|
||||||
import ru.dbotthepony.kstarbound.world.World
|
import ru.dbotthepony.kstarbound.world.World
|
||||||
|
import ru.dbotthepony.kstarbound.world.physics.CollisionType
|
||||||
|
import java.util.EnumSet
|
||||||
|
import java.util.function.Predicate
|
||||||
|
|
||||||
fun provideWorldBindings(self: World<*, *>, lua: LuaEnvironment) {
|
fun provideWorldBindings(self: World<*, *>, lua: LuaEnvironment) {
|
||||||
val callbacks = lua.newTable()
|
val callbacks = lua.newTable()
|
||||||
@ -29,4 +39,39 @@ fun provideWorldBindings(self: World<*, *>, lua: LuaEnvironment) {
|
|||||||
callbacks["polyContains"] = luaFunction { poly: Table, position: Table ->
|
callbacks["polyContains"] = luaFunction { poly: Table, position: Table ->
|
||||||
returnBuffer.setTo(self.geometry.polyContains(toPoly(poly), toVector2d(position)))
|
returnBuffer.setTo(self.geometry.polyContains(toPoly(poly), toVector2d(position)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callbacks["xwrap"] = luaFunction { position: Any ->
|
||||||
|
if (position is Number) {
|
||||||
|
returnBuffer.setTo(self.geometry.x.cell(position.toDouble()))
|
||||||
|
} else {
|
||||||
|
returnBuffer.setTo(from(self.geometry.wrap(toVector2d(position))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks["ywrap"] = luaFunction { position: Any ->
|
||||||
|
if (position is Number) {
|
||||||
|
returnBuffer.setTo(self.geometry.y.cell(position.toDouble()))
|
||||||
|
} else {
|
||||||
|
returnBuffer.setTo(from(self.geometry.wrap(toVector2d(position))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks["nearestTo"] = luaFunction { pos0: Any, pos1: Any ->
|
||||||
|
if (pos1 is Number) {
|
||||||
|
val source = if (pos0 is Number) pos0.toDouble() else toVector2d(pos0).x
|
||||||
|
returnBuffer.setTo(self.geometry.x.nearestTo(source, pos1.toDouble()))
|
||||||
|
} else {
|
||||||
|
val source = if (pos0 is Number) Vector2d(pos0.toDouble()) else toVector2d(pos0)
|
||||||
|
returnBuffer.setTo(self.geometry.nearestTo(source, toVector2d(pos1)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks["rectCollision"] = luaFunction { rect: Table, collisions: Table? ->
|
||||||
|
if (collisions == null) {
|
||||||
|
returnBuffer.setTo(self.collide(toPoly(rect), Predicate { it.type.isSolidCollision }).findAny().isPresent)
|
||||||
|
} else {
|
||||||
|
val actualCollisions = EnumSet.copyOf(collisions.iterator().map { CollisionType.entries.valueOf((it.value as ByteString).decode()) }.toList())
|
||||||
|
returnBuffer.setTo(self.collide(toPoly(rect), Predicate { it.type in actualCollisions }).findAny().isPresent)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,15 @@ data class Line2d(val p0: Vector2d, val p1: Vector2d) {
|
|||||||
stream.writeStruct2d(p1, isLegacy)
|
stream.writeStruct2d(p1, isLegacy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * if > 0.0 - left side
|
||||||
|
* * if < 0.0 - right side
|
||||||
|
* * if = 0.0 - rests upon
|
||||||
|
*/
|
||||||
|
fun isLeft(p2: IStruct2d): Double {
|
||||||
|
return (p1.component1() - p0.component1()) * (p2.component2() - p0.component2()) - (p2.component1() - p0.component1()) * (p1.component2() - p0.component2())
|
||||||
|
}
|
||||||
|
|
||||||
// original source of this intersection algorithm:
|
// original source of this intersection algorithm:
|
||||||
// https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
|
// https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
|
||||||
// article "Intersection of two lines in three-space" by Ronald Goldman, published in Graphics Gems, page 304
|
// article "Intersection of two lines in three-space" by Ronald Goldman, published in Graphics Gems, page 304
|
||||||
|
@ -898,7 +898,7 @@ class ServerChunk(world: ServerWorld, pos: ChunkPos) : Chunk<ServerWorld, Server
|
|||||||
// is trying to achieve, mostly because the style it is written in
|
// is trying to achieve, mostly because the style it is written in
|
||||||
// suggests it was written WAY early in game development
|
// suggests it was written WAY early in game development
|
||||||
|
|
||||||
var badNodes = HashSet<Vector2i>()
|
var badNodes = HashSet<Vector2i>(1024)
|
||||||
val candidateNodes = HashSet<Vector2i>()
|
val candidateNodes = HashSet<Vector2i>()
|
||||||
|
|
||||||
// this gives a rectangle of this chunk plus all neighbours BUT the very last border cell
|
// this gives a rectangle of this chunk plus all neighbours BUT the very last border cell
|
||||||
@ -974,7 +974,7 @@ class ServerChunk(world: ServerWorld, pos: ChunkPos) : Chunk<ServerWorld, Server
|
|||||||
|
|
||||||
while (badNodes.isNotEmpty()) {
|
while (badNodes.isNotEmpty()) {
|
||||||
val oldNodes = badNodes
|
val oldNodes = badNodes
|
||||||
badNodes = HashSet()
|
badNodes = HashSet(1024)
|
||||||
|
|
||||||
// TODO: same as above
|
// TODO: same as above
|
||||||
for (node in oldNodes) {
|
for (node in oldNodes) {
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package ru.dbotthepony.kstarbound.world
|
package ru.dbotthepony.kstarbound.world
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
import ru.dbotthepony.kommons.vector.Vector2d
|
import ru.dbotthepony.kommons.vector.Vector2d
|
||||||
import ru.dbotthepony.kommons.vector.Vector2i
|
import ru.dbotthepony.kommons.vector.Vector2i
|
||||||
|
import ru.dbotthepony.kstarbound.math.Line2d
|
||||||
import ru.dbotthepony.kstarbound.math.divideUp
|
import ru.dbotthepony.kstarbound.math.divideUp
|
||||||
|
import ru.dbotthepony.kstarbound.world.physics.Poly
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
@ -28,6 +31,8 @@ fun positiveModulo(a: Float, b: Int): Float {
|
|||||||
|
|
||||||
abstract class CoordinateMapper {
|
abstract class CoordinateMapper {
|
||||||
abstract val chunks: Int
|
abstract val chunks: Int
|
||||||
|
abstract val cells: Int
|
||||||
|
abstract val cellsD: Double
|
||||||
|
|
||||||
abstract fun cell(value: Int): Int
|
abstract fun cell(value: Int): Int
|
||||||
abstract fun cell(value: Double): Double
|
abstract fun cell(value: Double): Double
|
||||||
@ -72,9 +77,11 @@ abstract class CoordinateMapper {
|
|||||||
abstract fun nearestTo(source: Int, target: Int): Int
|
abstract fun nearestTo(source: Int, target: Int): Int
|
||||||
abstract fun nearestTo(source: Double, target: Double): Double
|
abstract fun nearestTo(source: Double, target: Double): Double
|
||||||
|
|
||||||
class Wrapper(private val cells: Int) : CoordinateMapper() {
|
abstract val isSplitting: Boolean
|
||||||
|
|
||||||
|
class Wrapper(override val cells: Int) : CoordinateMapper() {
|
||||||
override val chunks = divideUp(cells, CHUNK_SIZE)
|
override val chunks = divideUp(cells, CHUNK_SIZE)
|
||||||
private val cellsD = cells.toDouble()
|
override val cellsD = cells.toDouble()
|
||||||
|
|
||||||
// try to approach reasonable "edge" value, which is just little less than `cells`
|
// try to approach reasonable "edge" value, which is just little less than `cells`
|
||||||
private var cellsEdge = cellsD
|
private var cellsEdge = cellsD
|
||||||
@ -95,6 +102,9 @@ abstract class CoordinateMapper {
|
|||||||
override fun isValidCellIndex(value: Int) = true
|
override fun isValidCellIndex(value: Int) = true
|
||||||
override fun isValidChunkIndex(value: Int) = true
|
override fun isValidChunkIndex(value: Int) = true
|
||||||
|
|
||||||
|
override val isSplitting: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
override fun diff(a: Int, b: Int): Int {
|
override fun diff(a: Int, b: Int): Int {
|
||||||
val a = cell(a)
|
val a = cell(a)
|
||||||
@ -221,9 +231,9 @@ abstract class CoordinateMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Clamper(private val cells: Int) : CoordinateMapper() {
|
class Clamper(override val cells: Int) : CoordinateMapper() {
|
||||||
override val chunks = divideUp(cells, CHUNK_SIZE)
|
override val chunks = divideUp(cells, CHUNK_SIZE)
|
||||||
private val cellsD = cells.toDouble()
|
override val cellsD = cells.toDouble()
|
||||||
private val cellsF = cells.toFloat()
|
private val cellsF = cells.toFloat()
|
||||||
|
|
||||||
// try to approach reasonable "edge" value, which is just little less than `cells`
|
// try to approach reasonable "edge" value, which is just little less than `cells`
|
||||||
@ -277,6 +287,9 @@ abstract class CoordinateMapper {
|
|||||||
return SplitResultDouble(Vector2d(cell(first), cell(last)), null, 0.0)
|
return SplitResultDouble(Vector2d(cell(first), cell(last)), null, 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val isSplitting: Boolean
|
||||||
|
get() = false
|
||||||
|
|
||||||
override fun cell(value: Int): Int {
|
override fun cell(value: Int): Int {
|
||||||
return value.coerceIn(0, cells - 1)
|
return value.coerceIn(0, cells - 1)
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import ru.dbotthepony.kommons.util.IStruct2i
|
|||||||
import ru.dbotthepony.kommons.vector.Vector2d
|
import ru.dbotthepony.kommons.vector.Vector2d
|
||||||
import ru.dbotthepony.kommons.vector.Vector2i
|
import ru.dbotthepony.kommons.vector.Vector2i
|
||||||
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
|
||||||
|
import ru.dbotthepony.kstarbound.math.Line2d
|
||||||
import ru.dbotthepony.kstarbound.world.physics.Poly
|
import ru.dbotthepony.kstarbound.world.physics.Poly
|
||||||
import java.io.DataInputStream
|
import java.io.DataInputStream
|
||||||
import java.io.DataOutputStream
|
import java.io.DataOutputStream
|
||||||
@ -242,7 +243,83 @@ data class WorldGeometry(val size: Vector2i, val loopX: Boolean = true, val loop
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun split(poly: Poly): List<Poly> {
|
fun split(poly: Poly): List<Poly> {
|
||||||
TODO()
|
val lines = ObjectArrayList<Pair<Line2d, Pair<Vector2d, Vector2d>>>(4)
|
||||||
|
|
||||||
|
if (x.isSplitting) {
|
||||||
|
lines.add(Line2d(Vector2d.ZERO, Vector2d.POSITIVE_Y) to (Vector2d(x.cellsD, 0.0) to Vector2d.ZERO))
|
||||||
|
lines.add(Line2d(Vector2d(x.cellsD, 0.0), Vector2d(x.cellsD, 1.0)) to (Vector2d.ZERO to Vector2d(-x.cellsD, 0.0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y.isSplitting) {
|
||||||
|
lines.add(Line2d(Vector2d.ZERO, Vector2d.POSITIVE_X) to (Vector2d.ZERO to Vector2d(0.0, y.cellsD)))
|
||||||
|
lines.add(Line2d(Vector2d(0.0, y.cellsD), Vector2d(1.0, y.cellsD)) to (Vector2d(0.0, -y.cellsD) to Vector2d.ZERO))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lines.isEmpty) {
|
||||||
|
return listOf(poly)
|
||||||
|
}
|
||||||
|
|
||||||
|
val split = ObjectArrayList<Poly>()
|
||||||
|
split.add(poly)
|
||||||
|
|
||||||
|
for ((line, corrections) in lines) {
|
||||||
|
val (correctionIfLeft, correctionIfRight) = corrections
|
||||||
|
val itr = split.listIterator()
|
||||||
|
|
||||||
|
for (tpoly in itr) {
|
||||||
|
val leftPoints = ObjectArrayList<Vector2d>(tpoly.edges.size)
|
||||||
|
val rightPoints = ObjectArrayList<Vector2d>(tpoly.edges.size)
|
||||||
|
|
||||||
|
for (vedge in tpoly.edges) {
|
||||||
|
val left0 = line.isLeft(vedge.p0)
|
||||||
|
val left1 = line.isLeft(vedge.p1)
|
||||||
|
|
||||||
|
if (left0 >= 0.0 && left1 >= 0.0) {
|
||||||
|
leftPoints.add(vedge.p0 + correctionIfLeft)
|
||||||
|
leftPoints.add(vedge.p1 + correctionIfLeft)
|
||||||
|
} else if (left0 < 0.0 && left1 < 0.0) {
|
||||||
|
rightPoints.add(vedge.p0 + correctionIfRight)
|
||||||
|
rightPoints.add(vedge.p1 + correctionIfRight)
|
||||||
|
} else {
|
||||||
|
// edge gets split in half by our line
|
||||||
|
val result = line.intersect(vedge, true)
|
||||||
|
|
||||||
|
// check if it is an actual split, if poly points just rest on that line consider they rest on left side
|
||||||
|
if (result.intersects) {
|
||||||
|
val point = line.intersect(vedge, true).point.orThrow { RuntimeException() }
|
||||||
|
|
||||||
|
if (left0 < 0.0 && left1 >= 0.0) {
|
||||||
|
leftPoints.add(vedge.p1 + correctionIfLeft)
|
||||||
|
rightPoints.add(vedge.p0 + correctionIfRight)
|
||||||
|
} else {
|
||||||
|
leftPoints.add(vedge.p0 + correctionIfLeft)
|
||||||
|
rightPoints.add(vedge.p1 + correctionIfRight)
|
||||||
|
}
|
||||||
|
|
||||||
|
leftPoints.add(point + correctionIfLeft)
|
||||||
|
rightPoints.add(point + correctionIfRight)
|
||||||
|
} else {
|
||||||
|
// dang it
|
||||||
|
leftPoints.add(vedge.p0 + correctionIfLeft)
|
||||||
|
leftPoints.add(vedge.p1 + correctionIfLeft)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
itr.remove()
|
||||||
|
|
||||||
|
if (leftPoints.isEmpty) {
|
||||||
|
itr.add(Poly.quickhull(rightPoints))
|
||||||
|
} else if (rightPoints.isEmpty) {
|
||||||
|
itr.add(Poly.quickhull(leftPoints))
|
||||||
|
} else {
|
||||||
|
itr.add(Poly.quickhull(leftPoints))
|
||||||
|
itr.add(Poly.quickhull(rightPoints))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return split
|
||||||
}
|
}
|
||||||
|
|
||||||
fun polyContains(poly: Poly, point: IStruct2d): Boolean {
|
fun polyContains(poly: Poly, point: IStruct2d): Boolean {
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
package ru.dbotthepony.kstarbound.world.physics
|
package ru.dbotthepony.kstarbound.world.physics
|
||||||
|
|
||||||
enum class CollisionType(val isEmpty: Boolean, val isSolidCollision: Boolean, val isTileCollision: Boolean) {
|
import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
|
||||||
|
|
||||||
|
enum class CollisionType(override val jsonName: String, val isEmpty: Boolean, val isSolidCollision: Boolean, val isTileCollision: Boolean) : IStringSerializable {
|
||||||
// not loaded, block collisions by default
|
// not loaded, block collisions by default
|
||||||
NULL(true, true, false),
|
NULL("Null", true, true, false),
|
||||||
// air
|
// air
|
||||||
NONE(true, false, false),
|
NONE("None", true, false, false),
|
||||||
// including stairs made of platforms
|
// including stairs made of platforms
|
||||||
PLATFORM(false, false, false),
|
PLATFORM("Platform", false, false, false),
|
||||||
DYNAMIC(false, true, false),
|
DYNAMIC("Dynamic", false, true, false),
|
||||||
SLIPPERY(false, true, true),
|
SLIPPERY("Slippery", false, true, true),
|
||||||
BLOCK(false, true, true);
|
BLOCK("Block", false, true, true);
|
||||||
|
|
||||||
fun maxOf(other: CollisionType): CollisionType {
|
fun maxOf(other: CollisionType): CollisionType {
|
||||||
if (this === NULL || other === NULL)
|
if (this === NULL || other === NULL)
|
||||||
|
@ -71,10 +71,6 @@ private fun calculateEdges(points: List<Vector2d>): Pair<ImmutableList<Line2d>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isLeft(p0: IStruct2d, p1: IStruct2d, p2: IStruct2d): Double {
|
|
||||||
return (p1.component1() - p0.component1()) * (p2.component2() - p0.component2()) - (p2.component1() - p0.component1()) * (p1.component2() - p0.component2())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rotate(point: Vector2d, sin: Double, cos: Double): Vector2d {
|
private fun rotate(point: Vector2d, sin: Double, cos: Double): Vector2d {
|
||||||
return Vector2d(
|
return Vector2d(
|
||||||
point.x * cos + point.y * sin,
|
point.x * cos + point.y * sin,
|
||||||
@ -230,7 +226,7 @@ class Poly private constructor(val edges: ImmutableList<Line2d>, val vertices: I
|
|||||||
if (edge.p0.y <= y) {
|
if (edge.p0.y <= y) {
|
||||||
if (edge.p1.y > y) {
|
if (edge.p1.y > y) {
|
||||||
// an upward crossing
|
// an upward crossing
|
||||||
if (isLeft(edge.p0, edge.p1, point) > 0.0) {
|
if (edge.isLeft(point) > 0.0) {
|
||||||
// p left of edge
|
// p left of edge
|
||||||
// have a valid up intersect
|
// have a valid up intersect
|
||||||
++wn
|
++wn
|
||||||
@ -240,7 +236,7 @@ class Poly private constructor(val edges: ImmutableList<Line2d>, val vertices: I
|
|||||||
// start y > p[1] (no test needed)
|
// start y > p[1] (no test needed)
|
||||||
if (edge.p1.y <= y) {
|
if (edge.p1.y <= y) {
|
||||||
// a downward crossing
|
// a downward crossing
|
||||||
if (isLeft(edge.p0, edge.p1, point) < 0.0) {
|
if (edge.isLeft(point) < 0.0) {
|
||||||
// p right of edge
|
// p right of edge
|
||||||
// have a valid down intersect
|
// have a valid down intersect
|
||||||
--wn
|
--wn
|
||||||
|
@ -3,12 +3,15 @@ package ru.dbotthepony.kstarbound.test
|
|||||||
import org.junit.jupiter.api.Assertions.assertTrue
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import ru.dbotthepony.kommons.util.AABB
|
||||||
import ru.dbotthepony.kommons.vector.Vector2d
|
import ru.dbotthepony.kommons.vector.Vector2d
|
||||||
|
import ru.dbotthepony.kommons.vector.Vector2i
|
||||||
import ru.dbotthepony.kstarbound.math.*
|
import ru.dbotthepony.kstarbound.math.*
|
||||||
import ru.dbotthepony.kstarbound.util.random.random
|
import ru.dbotthepony.kstarbound.util.random.random
|
||||||
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE
|
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE
|
||||||
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF
|
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF
|
||||||
import ru.dbotthepony.kstarbound.world.ChunkPos
|
import ru.dbotthepony.kstarbound.world.ChunkPos
|
||||||
|
import ru.dbotthepony.kstarbound.world.WorldGeometry
|
||||||
import ru.dbotthepony.kstarbound.world.physics.Poly
|
import ru.dbotthepony.kstarbound.world.physics.Poly
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
|
Loading…
Reference in New Issue
Block a user