mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 10:55:01 -04:00
improve voxel side calculating
Less memory allocation, faster performance, better results. Still not perfect
This commit is contained in:
parent
199aab67d7
commit
aca80648d3
@ -15,8 +15,8 @@ package de.bixilon.minosoft.data.registries.blocks.light
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.Axes
|
import de.bixilon.minosoft.data.Axes
|
||||||
import de.bixilon.minosoft.data.direction.Directions
|
import de.bixilon.minosoft.data.direction.Directions
|
||||||
|
import de.bixilon.minosoft.data.registries.shapes.side.SideQuad
|
||||||
import de.bixilon.minosoft.data.registries.shapes.side.VoxelSide
|
import de.bixilon.minosoft.data.registries.shapes.side.VoxelSide
|
||||||
import de.bixilon.minosoft.data.registries.shapes.side.VoxelSideSet
|
|
||||||
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
|
import de.bixilon.minosoft.data.registries.shapes.voxel.AbstractVoxelShape
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||||
|
|
||||||
@ -34,7 +34,8 @@ class DirectedProperty(
|
|||||||
companion object {
|
companion object {
|
||||||
private val TRUE = BooleanArray(Directions.SIZE) { true }
|
private val TRUE = BooleanArray(Directions.SIZE) { true }
|
||||||
private val FALSE = BooleanArray(Directions.SIZE) { false }
|
private val FALSE = BooleanArray(Directions.SIZE) { false }
|
||||||
private val FULL_SIDE = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
private val FULL_SIDE = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
|
private val REQUIRED_SURFACE_AREA = FULL_SIDE.surfaceArea() - 0.0001f // add some padding for floating point
|
||||||
|
|
||||||
private val BooleanArray.isSimple: Boolean?
|
private val BooleanArray.isSimple: Boolean?
|
||||||
get() {
|
get() {
|
||||||
@ -69,11 +70,13 @@ class DirectedProperty(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun AbstractVoxelShape.getSide(side: Directions): VoxelSideSet {
|
private fun AbstractVoxelShape.getSide(side: Directions): VoxelSide? {
|
||||||
// ToDo: This whole calculation is technically wrong, it could be that 2 different sides of 2 blocks are "free". That means that light can still not pass the blocks, but
|
// ToDo: This whole calculation is technically wrong, it could be that 2 different sides of 2 blocks are "free". That means that light can still not pass the blocks, but
|
||||||
// this algorithm does not cover it. Let's see it as performance hack
|
// this algorithm does not cover it. Let's see it as performance hack
|
||||||
|
|
||||||
val sides: MutableSet<VoxelSide> = ObjectOpenHashSet()
|
if (this.aabbs == 0) return null
|
||||||
|
|
||||||
|
val sides: MutableSet<SideQuad> = ObjectOpenHashSet()
|
||||||
|
|
||||||
for (aabb in this) {
|
for (aabb in this) {
|
||||||
when (side.axis) {
|
when (side.axis) {
|
||||||
@ -81,41 +84,60 @@ class DirectedProperty(
|
|||||||
if ((side == Directions.DOWN && aabb.min.y != 0.0) || (side == Directions.UP && aabb.max.y != 1.0)) {
|
if ((side == Directions.DOWN && aabb.min.y != 0.0) || (side == Directions.UP && aabb.max.y != 1.0)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sides += VoxelSide(aabb.min.x, aabb.min.z, aabb.max.x, aabb.max.z)
|
val side = SideQuad(aabb.min.x, aabb.min.z, aabb.max.x, aabb.max.z)
|
||||||
|
if (side.surfaceArea() > 0.0f) {
|
||||||
|
sides += side
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Axes.X -> {
|
Axes.X -> {
|
||||||
if ((side == Directions.WEST && aabb.min.x != 0.0) || (side == Directions.EAST && aabb.max.x != 1.0)) {
|
if ((side == Directions.WEST && aabb.min.x != 0.0) || (side == Directions.EAST && aabb.max.x != 1.0)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sides += VoxelSide(aabb.min.y, aabb.min.z, aabb.max.y, aabb.max.z)
|
val side = SideQuad(aabb.min.y, aabb.min.z, aabb.max.y, aabb.max.z)
|
||||||
|
if (side.surfaceArea() > 0.0f) {
|
||||||
|
sides += side
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Axes.Z -> {
|
Axes.Z -> {
|
||||||
if ((side == Directions.NORTH && aabb.min.z != 0.0) || (side == Directions.SOUTH && aabb.max.z != 1.0)) {
|
if ((side == Directions.NORTH && aabb.min.z != 0.0) || (side == Directions.SOUTH && aabb.max.z != 1.0)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sides += VoxelSide(aabb.min.x, aabb.min.y, aabb.max.x, aabb.max.y)
|
val side = SideQuad(aabb.min.x, aabb.min.y, aabb.max.x, aabb.max.y)
|
||||||
|
if (side.surfaceArea() > 0.0f) {
|
||||||
|
sides += side
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return VoxelSideSet(sides)
|
if (sides.isEmpty()) return null
|
||||||
|
|
||||||
|
return VoxelSide(sides)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun VoxelSide.getSideArea(target: SideQuad): Float {
|
||||||
|
// overlapping is broken, see https://stackoverflow.com/questions/7342935/algorithm-to-compute-total-area-covered-by-a-set-of-overlapping-segments
|
||||||
|
var area = 0.0f
|
||||||
|
|
||||||
|
for (quad in this) {
|
||||||
|
val width = minOf(target.max.x, quad.max.x) - maxOf(quad.min.x, target.min.x)
|
||||||
|
val height = minOf(target.max.y, quad.max.y) - maxOf(quad.min.y, target.min.y)
|
||||||
|
|
||||||
|
area += width * height
|
||||||
|
}
|
||||||
|
|
||||||
|
return area
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AbstractVoxelShape.isSideCovered(direction: Directions): Boolean {
|
fun AbstractVoxelShape.isSideCovered(direction: Directions): Boolean {
|
||||||
val side = getSide(direction)
|
// this should be improved: https://stackoverflow.com/questions/76373725/check-if-a-quad-is-fully-covered-by-a-set-of-others
|
||||||
if (side.isEmpty()) {
|
val side = getSide(direction) ?: return false
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val rest = FULL_SIDE - side
|
val surface = side.getSideArea(FULL_SIDE)
|
||||||
var compacted = rest.compact()
|
|
||||||
if (rest != compacted) {
|
|
||||||
compacted = FULL_SIDE - compacted
|
|
||||||
}
|
|
||||||
|
|
||||||
return !FULL_SIDE.touches(compacted)
|
return surface >= REQUIRED_SURFACE_AREA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2023 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.data.registries.shapes.side
|
||||||
|
|
||||||
|
import com.google.common.base.Objects
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||||
|
|
||||||
|
data class SideQuad(
|
||||||
|
val min: Vec2,
|
||||||
|
val max: Vec2,
|
||||||
|
) {
|
||||||
|
private val hashCode = Objects.hashCode(min.hashCode(), max.hashCode())
|
||||||
|
|
||||||
|
constructor(minX: Float, minZ: Float, maxX: Float, maxZ: Float) : this(Vec2(minOf(minX, maxX), minOf(minZ, maxZ)), Vec2(maxOf(minX, maxX), maxOf(minZ, maxZ)))
|
||||||
|
constructor(minX: Double, minZ: Double, maxX: Double, maxZ: Double) : this(Vec2(minOf(minX, maxX).toFloat(), minOf(minZ, maxZ).toFloat()), Vec2(maxOf(minX, maxX).toFloat(), maxOf(minZ, maxZ).toFloat()))
|
||||||
|
|
||||||
|
|
||||||
|
fun touches(other: SideQuad): Boolean {
|
||||||
|
return !(this.min.x > other.max.x || other.min.x > this.max.x || this.min.y > other.max.y || other.min.y > this.max.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
infix operator fun minus(set: VoxelSide): VoxelSide {
|
||||||
|
val result: MutableSet<SideQuad> = ObjectOpenHashSet()
|
||||||
|
|
||||||
|
for (side in set.sides) {
|
||||||
|
result += (this minus side).sides
|
||||||
|
}
|
||||||
|
|
||||||
|
return VoxelSide(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
infix operator fun minus(other: SideQuad): VoxelSide {
|
||||||
|
val result: MutableSet<SideQuad> = ObjectOpenHashSet()
|
||||||
|
|
||||||
|
|
||||||
|
if (other.min.x > min.x && other.min.x < max.x) {
|
||||||
|
result += SideQuad(min.x, min.y, other.min.x, max.y)
|
||||||
|
}
|
||||||
|
if (other.min.y > min.y && other.min.y < max.y) {
|
||||||
|
result += SideQuad(min.x, min.y, max.x, other.min.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max.x > other.max.x) {
|
||||||
|
result += SideQuad(other.max.x, min.y, max.x, max.y)
|
||||||
|
}
|
||||||
|
if (max.y > other.max.y) {
|
||||||
|
result += SideQuad(min.x, other.max.y, max.x, max.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return VoxelSide(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return hashCode
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is SideQuad) return false
|
||||||
|
if (hashCode != other.hashCode) return false
|
||||||
|
return min == other.min && max == other.max
|
||||||
|
}
|
||||||
|
|
||||||
|
fun surfaceArea(): Float {
|
||||||
|
val surface = (max.x - min.x) * (max.y - min.y)
|
||||||
|
if (surface <= 0.0f) return 0.0f
|
||||||
|
return surface
|
||||||
|
}
|
||||||
|
}
|
@ -13,105 +13,23 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.registries.shapes.side
|
package de.bixilon.minosoft.data.registries.shapes.side
|
||||||
|
|
||||||
import com.google.common.base.Objects
|
class VoxelSide(
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
val sides: Set<SideQuad>,
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
) : Iterable<SideQuad> {
|
||||||
|
|
||||||
data class VoxelSide(
|
fun isEmpty(): Boolean = sides.isEmpty()
|
||||||
val min: Vec2,
|
|
||||||
val max: Vec2,
|
|
||||||
) {
|
|
||||||
private val hashCode = Objects.hashCode(min.hashCode(), max.hashCode())
|
|
||||||
|
|
||||||
constructor(minX: Float, minZ: Float, maxX: Float, maxZ: Float) : this(Vec2(minOf(minX, maxX), minOf(minZ, maxZ)), Vec2(maxOf(minX, maxX), maxOf(minZ, maxZ)))
|
override fun iterator(): Iterator<SideQuad> {
|
||||||
constructor(minX: Double, minZ: Double, maxX: Double, maxZ: Double) : this(Vec2(minOf(minX, maxX).toFloat(), minOf(minZ, maxZ).toFloat()), Vec2(maxOf(minX, maxX).toFloat(), maxOf(minZ, maxZ).toFloat()))
|
return sides.iterator()
|
||||||
|
|
||||||
|
|
||||||
fun touches(set: VoxelSideSet): Boolean {
|
|
||||||
for (side in set) {
|
|
||||||
if (touches(side)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun touches(other: VoxelSide): Boolean {
|
|
||||||
return !(this.min.x > other.max.x || other.min.x > this.max.x || this.min.y > other.max.y || other.min.y > this.max.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
infix operator fun minus(set: VoxelSideSet): VoxelSideSet {
|
|
||||||
val result: MutableSet<VoxelSide> = ObjectOpenHashSet()
|
|
||||||
|
|
||||||
for (side in set.sides) {
|
|
||||||
result += (this minus side).sides
|
|
||||||
}
|
|
||||||
|
|
||||||
return VoxelSideSet(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
infix operator fun minus(other: VoxelSide): VoxelSideSet {
|
|
||||||
val result: MutableSet<VoxelSide> = ObjectOpenHashSet()
|
|
||||||
|
|
||||||
|
|
||||||
if (other.min.x > min.x && other.min.x < max.x) {
|
|
||||||
result += VoxelSide(min.x, min.y, other.min.x, max.y)
|
|
||||||
}
|
|
||||||
if (other.min.y > min.y && other.min.y < max.y) {
|
|
||||||
result += VoxelSide(min.x, min.y, max.x, other.min.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max.x > other.max.x) {
|
|
||||||
result += VoxelSide(other.max.x, min.y, max.x, max.y)
|
|
||||||
}
|
|
||||||
if (max.y > other.max.y) {
|
|
||||||
result += VoxelSide(min.x, other.max.y, max.x, max.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return VoxelSideSet(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
infix fun or(other: VoxelSide): VoxelSide {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun compact(side: VoxelSide): VoxelSideSet {
|
|
||||||
var minX = min.x
|
|
||||||
var minY = min.y
|
|
||||||
var maxX = max.x
|
|
||||||
var maxY = max.y
|
|
||||||
|
|
||||||
var changes = 0
|
|
||||||
if (side.min.y == minY && side.min.x < minX) {
|
|
||||||
minX = side.min.x; changes++
|
|
||||||
} else if (side.min.x == minX && side.min.y < minY) {
|
|
||||||
minY = side.min.y;changes++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (side.max.y == maxY && side.max.x > maxX) {
|
|
||||||
maxX = side.max.x;changes++
|
|
||||||
} else if (side.max.x == maxX && side.min.y > maxY) {
|
|
||||||
maxY = side.max.y;changes++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changes == 0) {
|
|
||||||
val set: MutableSet<VoxelSide> = ObjectOpenHashSet(2)
|
|
||||||
set += this
|
|
||||||
set += side
|
|
||||||
return VoxelSideSet(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
return VoxelSideSet(setOf(VoxelSide(minX, minY, maxX, maxY)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return hashCode
|
return sides.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other !is VoxelSide) return false
|
if (other !is VoxelSide) return false
|
||||||
if (hashCode != other.hashCode) return false
|
if (hashCode() != other.hashCode()) return false
|
||||||
return min == other.min && max == other.max
|
return sides == other.sides
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Minosoft
|
|
||||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.bixilon.minosoft.data.registries.shapes.side
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
|
||||||
|
|
||||||
class VoxelSideSet(
|
|
||||||
val sides: Set<VoxelSide>,
|
|
||||||
) : Iterable<VoxelSide> {
|
|
||||||
|
|
||||||
fun isEmpty(): Boolean = sides.isEmpty()
|
|
||||||
|
|
||||||
override fun iterator(): Iterator<VoxelSide> {
|
|
||||||
return sides.iterator()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun compact(): VoxelSideSet {
|
|
||||||
if (this.sides.size <= 1) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
val next: MutableSet<VoxelSide> = ObjectOpenHashSet()
|
|
||||||
|
|
||||||
val array = this.sides.toTypedArray()
|
|
||||||
for (i in 1 until sides.size) {
|
|
||||||
next += array[i - 1].compact(array[i])
|
|
||||||
}
|
|
||||||
val set = VoxelSideSet(next)
|
|
||||||
|
|
||||||
if (next.size < this.sides.size) {
|
|
||||||
return set.compact()
|
|
||||||
}
|
|
||||||
|
|
||||||
return set
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
return sides.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (other !is VoxelSideSet) return false
|
|
||||||
if (hashCode() != other.hashCode()) return false
|
|
||||||
return sides == other.sides
|
|
||||||
}
|
|
||||||
}
|
|
@ -80,7 +80,7 @@ internal class DirectedPropertyTest {
|
|||||||
assertTrue(shape.isSideCovered(Directions.EAST))
|
assertTrue(shape.isSideCovered(Directions.EAST))
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test // TODO: This test is correct, isSideCovered is broken
|
@Test
|
||||||
fun testSideCovered6() {
|
fun testSideCovered6() {
|
||||||
val shape = VoxelShape(
|
val shape = VoxelShape(
|
||||||
AABB(0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f),
|
AABB(0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f),
|
||||||
@ -109,4 +109,35 @@ internal class DirectedPropertyTest {
|
|||||||
assertFalse(shape.isSideCovered(Directions.WEST))
|
assertFalse(shape.isSideCovered(Directions.WEST))
|
||||||
assertFalse(shape.isSideCovered(Directions.EAST))
|
assertFalse(shape.isSideCovered(Directions.EAST))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSideCovered8() { // overlapping
|
||||||
|
val shape = VoxelShape(
|
||||||
|
AABB(0.0f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f),
|
||||||
|
AABB(0.0f, 0.4f, 0.5f, 1.0f, 1.0f, 1.0f),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertTrue(shape.isSideCovered(Directions.DOWN))
|
||||||
|
assertFalse(shape.isSideCovered(Directions.UP))
|
||||||
|
assertFalse(shape.isSideCovered(Directions.NORTH))
|
||||||
|
assertTrue(shape.isSideCovered(Directions.SOUTH))
|
||||||
|
assertFalse(shape.isSideCovered(Directions.WEST))
|
||||||
|
assertFalse(shape.isSideCovered(Directions.EAST))
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Test // TODO: This test is correct, isSideCovered is broken
|
||||||
|
fun testSideCovered9() { // overlapping
|
||||||
|
val shape = VoxelShape(
|
||||||
|
AABB(0.0f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f),
|
||||||
|
AABB(0.1f, 0.0f, 0.0f, 0.9f, 0.8f, 1.0f),
|
||||||
|
AABB(0.0f, 0.4f, 0.5f, 1.0f, 0.9f, 1.0f),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertTrue(shape.isSideCovered(Directions.DOWN))
|
||||||
|
assertFalse(shape.isSideCovered(Directions.UP))
|
||||||
|
assertFalse(shape.isSideCovered(Directions.NORTH))
|
||||||
|
assertTrue(shape.isSideCovered(Directions.SOUTH))
|
||||||
|
assertFalse(shape.isSideCovered(Directions.WEST))
|
||||||
|
assertFalse(shape.isSideCovered(Directions.EAST))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,15 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMinus1() {
|
fun testMinus1() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(0.0f, 0.0f, 0.5f, 0.5f)
|
val b = SideQuad(0.0f, 0.0f, 0.5f, 0.5f)
|
||||||
|
|
||||||
val result = a - b
|
val result = a - b
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
setOf(
|
setOf(
|
||||||
VoxelSide(0.0f, 0.5f, 1.0f, 1.0f),
|
SideQuad(0.0f, 0.5f, 1.0f, 1.0f),
|
||||||
VoxelSide(0.5f, 0.0f, 1.0f, 1.0f),
|
SideQuad(0.5f, 0.0f, 1.0f, 1.0f),
|
||||||
),
|
),
|
||||||
result.sides
|
result.sides
|
||||||
)
|
)
|
||||||
@ -36,17 +36,17 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMinus2() {
|
fun testMinus2() {
|
||||||
val a = VoxelSide(1.0f, 1.0f, 4.0f, 4.0f)
|
val a = SideQuad(1.0f, 1.0f, 4.0f, 4.0f)
|
||||||
val b = VoxelSide(2.0f, 2.0f, 3.0f, 3.0f)
|
val b = SideQuad(2.0f, 2.0f, 3.0f, 3.0f)
|
||||||
|
|
||||||
val result = a - b
|
val result = a - b
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
setOf(
|
setOf(
|
||||||
VoxelSide(1.0f, 1.0f, 4.0f, 2.0f),
|
SideQuad(1.0f, 1.0f, 4.0f, 2.0f),
|
||||||
VoxelSide(3.0f, 1.0f, 4.0f, 4.0f),
|
SideQuad(3.0f, 1.0f, 4.0f, 4.0f),
|
||||||
VoxelSide(1.0f, 3.0f, 4.0f, 4.0f),
|
SideQuad(1.0f, 3.0f, 4.0f, 4.0f),
|
||||||
VoxelSide(1.0f, 1.0f, 2.0f, 4.0f),
|
SideQuad(1.0f, 1.0f, 2.0f, 4.0f),
|
||||||
),
|
),
|
||||||
result.sides
|
result.sides
|
||||||
)
|
)
|
||||||
@ -54,60 +54,29 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMinus3() {
|
fun testMinus3() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(1.0f, 1.0f, 2.0f, 2.0f)
|
val b = SideQuad(1.0f, 1.0f, 2.0f, 2.0f)
|
||||||
|
|
||||||
val result = a - b
|
val result = a - b
|
||||||
|
|
||||||
assertEquals(emptySet<VoxelSide>(), result.sides)
|
assertEquals(emptySet<SideQuad>(), result.sides)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMinus4() {
|
fun testMinus4() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 0.5f, 0.5f)
|
val a = SideQuad(0.0f, 0.0f, 0.5f, 0.5f)
|
||||||
val b = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val b = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
|
|
||||||
val result = a - b
|
val result = a - b
|
||||||
|
|
||||||
assertEquals(emptySet<VoxelSide>(), result.sides)
|
assertEquals(emptySet<SideQuad>(), result.sides)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun testOr1() {
|
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
|
||||||
val b = VoxelSide(0.0f, 0.0f, 0.5f, 0.5f)
|
|
||||||
|
|
||||||
val or = a or b
|
|
||||||
assertEquals(or, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun testOr2() {
|
|
||||||
val a = VoxelSide(0.0f, 0.0f, 3.0f, 3.0f)
|
|
||||||
val b = VoxelSide(1.0f, 1.0f, 2.0f, 2.0f)
|
|
||||||
|
|
||||||
val or = a or b
|
|
||||||
assertEquals(or, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun testOr3() {
|
|
||||||
val a = VoxelSide(1.0f, 1.0f, 2.0f, 2.0f)
|
|
||||||
val b = VoxelSide(0.0f, 0.0f, 3.0f, 3.0f)
|
|
||||||
|
|
||||||
val or = a or b
|
|
||||||
assertEquals(or, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun testOr4() {
|
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
|
||||||
val b = VoxelSide(0.0f, 0.0f, 0.5f, 1.0f)
|
|
||||||
|
|
||||||
val or = a or b
|
|
||||||
assertEquals(or, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches1() {
|
fun testTouches1() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val b = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
|
|
||||||
assertTrue(a.touches(b))
|
assertTrue(a.touches(b))
|
||||||
assertTrue(b.touches(a))
|
assertTrue(b.touches(a))
|
||||||
@ -115,8 +84,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches2() {
|
fun testTouches2() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(0.0f, 0.0f, 0.5f, 0.5f)
|
val b = SideQuad(0.0f, 0.0f, 0.5f, 0.5f)
|
||||||
|
|
||||||
assertTrue(a.touches(b))
|
assertTrue(a.touches(b))
|
||||||
assertTrue(b.touches(a))
|
assertTrue(b.touches(a))
|
||||||
@ -124,8 +93,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches3() {
|
fun testTouches3() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(-1.0f, -1.0f, 0.5f, 0.5f)
|
val b = SideQuad(-1.0f, -1.0f, 0.5f, 0.5f)
|
||||||
|
|
||||||
assertTrue(a.touches(b))
|
assertTrue(a.touches(b))
|
||||||
assertTrue(b.touches(a))
|
assertTrue(b.touches(a))
|
||||||
@ -133,8 +102,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches4() {
|
fun testTouches4() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(-1.0f, -1.0f, 2.0f, 2.0f)
|
val b = SideQuad(-1.0f, -1.0f, 2.0f, 2.0f)
|
||||||
|
|
||||||
assertTrue(a.touches(b))
|
assertTrue(a.touches(b))
|
||||||
assertTrue(b.touches(a))
|
assertTrue(b.touches(a))
|
||||||
@ -142,8 +111,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches5() {
|
fun testTouches5() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(0.1f, -1.0f, 2.0f, 0.9f)
|
val b = SideQuad(0.1f, -1.0f, 2.0f, 0.9f)
|
||||||
|
|
||||||
assertTrue(a.touches(b))
|
assertTrue(a.touches(b))
|
||||||
assertTrue(b.touches(a))
|
assertTrue(b.touches(a))
|
||||||
@ -151,8 +120,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches6() {
|
fun testTouches6() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 3.0f, 3.0f)
|
val a = SideQuad(0.0f, 0.0f, 3.0f, 3.0f)
|
||||||
val b = VoxelSide(1.0f, 1.0f, 2.0f, 2.0f)
|
val b = SideQuad(1.0f, 1.0f, 2.0f, 2.0f)
|
||||||
|
|
||||||
assertTrue(a.touches(b))
|
assertTrue(a.touches(b))
|
||||||
assertTrue(b.touches(a))
|
assertTrue(b.touches(a))
|
||||||
@ -160,8 +129,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches7() {
|
fun testTouches7() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(1.0f, 1.0f, 2.0f, 2.0f)
|
val b = SideQuad(1.0f, 1.0f, 2.0f, 2.0f)
|
||||||
|
|
||||||
assertTrue(a.touches(b))
|
assertTrue(a.touches(b))
|
||||||
assertTrue(b.touches(a))
|
assertTrue(b.touches(a))
|
||||||
@ -169,8 +138,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches8() {
|
fun testTouches8() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(2.0f, 2.0f, 3.0f, 3.0f)
|
val b = SideQuad(2.0f, 2.0f, 3.0f, 3.0f)
|
||||||
|
|
||||||
assertFalse(a.touches(b))
|
assertFalse(a.touches(b))
|
||||||
assertFalse(b.touches(a))
|
assertFalse(b.touches(a))
|
||||||
@ -178,8 +147,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches9() {
|
fun testTouches9() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(0.0f, 2.0f, 3.0f, 3.0f)
|
val b = SideQuad(0.0f, 2.0f, 3.0f, 3.0f)
|
||||||
|
|
||||||
assertFalse(a.touches(b))
|
assertFalse(a.touches(b))
|
||||||
assertFalse(b.touches(a))
|
assertFalse(b.touches(a))
|
||||||
@ -187,8 +156,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches10() {
|
fun testTouches10() {
|
||||||
val a = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val a = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
val b = VoxelSide(2.0f, 0.0f, 3.0f, 3.0f)
|
val b = SideQuad(2.0f, 0.0f, 3.0f, 3.0f)
|
||||||
|
|
||||||
assertFalse(a.touches(b))
|
assertFalse(a.touches(b))
|
||||||
assertFalse(b.touches(a))
|
assertFalse(b.touches(a))
|
||||||
@ -196,8 +165,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches11() {
|
fun testTouches11() {
|
||||||
val a = VoxelSide(2.0f, 0.0f, 3.0f, 3.0f)
|
val a = SideQuad(2.0f, 0.0f, 3.0f, 3.0f)
|
||||||
val b = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val b = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
|
|
||||||
assertFalse(a.touches(b))
|
assertFalse(a.touches(b))
|
||||||
assertFalse(b.touches(a))
|
assertFalse(b.touches(a))
|
||||||
@ -205,8 +174,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches12() {
|
fun testTouches12() {
|
||||||
val a = VoxelSide(0.0f, 2.0f, 3.0f, 3.0f)
|
val a = SideQuad(0.0f, 2.0f, 3.0f, 3.0f)
|
||||||
val b = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val b = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
|
|
||||||
assertFalse(a.touches(b))
|
assertFalse(a.touches(b))
|
||||||
assertFalse(b.touches(a))
|
assertFalse(b.touches(a))
|
||||||
@ -214,8 +183,8 @@ internal class VoxelSideTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTouches13() {
|
fun testTouches13() {
|
||||||
val a = VoxelSide(2.0f, 2.0f, 3.0f, 3.0f)
|
val a = SideQuad(2.0f, 2.0f, 3.0f, 3.0f)
|
||||||
val b = VoxelSide(0.0f, 0.0f, 1.0f, 1.0f)
|
val b = SideQuad(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
|
|
||||||
assertFalse(a.touches(b))
|
assertFalse(a.touches(b))
|
||||||
assertFalse(b.touches(a))
|
assertFalse(b.touches(a))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user