solve for entry points
This commit is contained in:
parent
5def6da2de
commit
e964bceac4
@ -12,6 +12,7 @@ import electrosphere.client.interact.select.AreaSelection.AreaSelectionType;
|
|||||||
import electrosphere.client.scene.ClientWorldData;
|
import electrosphere.client.scene.ClientWorldData;
|
||||||
import electrosphere.data.block.fab.RoomMetadata;
|
import electrosphere.data.block.fab.RoomMetadata;
|
||||||
import electrosphere.data.block.fab.StructureMetadata;
|
import electrosphere.data.block.fab.StructureMetadata;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Solves for the rooms in a structure
|
* Solves for the rooms in a structure
|
||||||
@ -22,6 +23,16 @@ public class RoomSolver {
|
|||||||
* Maximum radius of room in blocks
|
* Maximum radius of room in blocks
|
||||||
*/
|
*/
|
||||||
public static final int MAX_ROOM_SIZE = 20;
|
public static final int MAX_ROOM_SIZE = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum height of a doorway
|
||||||
|
*/
|
||||||
|
public static final int DOORWAY_MIN_HEIGHT = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum width of a doorway
|
||||||
|
*/
|
||||||
|
public static final int DOORWAY_MIN_WIDTH = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 6-connected neighbors (orthogonal)
|
* 6-connected neighbors (orthogonal)
|
||||||
@ -67,9 +78,12 @@ public class RoomSolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//vectors used across scanning
|
||||||
|
Vector3d selectionStart = new Vector3d();
|
||||||
|
|
||||||
while(localMaximums.size() > 0){
|
while(localMaximums.size() > 0){
|
||||||
Vector3i toConsider = localMaximums.poll();
|
Vector3i toConsider = localMaximums.poll();
|
||||||
Vector3d selectionStart = new Vector3d(boundingArea.getRectStart()).add(
|
selectionStart.set(boundingArea.getRectStart()).add(
|
||||||
toConsider.x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
toConsider.x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
toConsider.y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
toConsider.y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
toConsider.z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
toConsider.z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
@ -87,14 +101,301 @@ public class RoomSolver {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//create the new room
|
//don't consider edge points
|
||||||
|
if(
|
||||||
|
toConsider.x == 0 || toConsider.y == 0 || toConsider.z == 0 ||
|
||||||
|
toConsider.x == dimX || toConsider.y == dimY || toConsider.z == dimZ
|
||||||
|
){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Calculate the cavity
|
||||||
Vector3i roomCenterChunkPos = ClientWorldData.convertRealToChunkSpace(selectionStart);
|
Vector3i roomCenterChunkPos = ClientWorldData.convertRealToChunkSpace(selectionStart);
|
||||||
Vector3i roomCenterBlockPos = ClientWorldData.convertRealToLocalBlockSpace(selectionStart);
|
Vector3i roomCenterBlockPos = ClientWorldData.convertRealToLocalBlockSpace(selectionStart);
|
||||||
|
|
||||||
AreaSelection roomArea = AreaSelection.selectRectangularBlockCavity(roomCenterChunkPos, roomCenterBlockPos, MAX_ROOM_SIZE);
|
AreaSelection roomArea = AreaSelection.selectRectangularBlockCavity(roomCenterChunkPos, roomCenterBlockPos, MAX_ROOM_SIZE);
|
||||||
structureMetadata.getRooms().add(new RoomMetadata(roomArea));
|
|
||||||
|
//check if outside bounds of map
|
||||||
|
if(roomArea.getRectStart().y <= 0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//scan along the floor and make sure we have voxels underneath each position
|
||||||
|
boolean floorIsValid = true;
|
||||||
|
int floorDimX = (int)((roomArea.getRectEnd().x - roomArea.getRectStart().x) * BlockChunkData.BLOCKS_PER_UNIT_DISTANCE);
|
||||||
|
int floorDimZ = (int)((roomArea.getRectEnd().z - roomArea.getRectStart().z) * BlockChunkData.BLOCKS_PER_UNIT_DISTANCE);
|
||||||
|
for(int x = 0; x < floorDimX; x++){
|
||||||
|
for(int z = 0; z < floorDimZ; z++){
|
||||||
|
selectionStart.set(roomArea.getRectStart()).add(
|
||||||
|
floorDimX * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
-1 * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
floorDimZ * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
);
|
||||||
|
Vector3i floorChunkPos = ClientWorldData.convertRealToChunkSpace(selectionStart);
|
||||||
|
Vector3i floorBlockPos = ClientWorldData.convertRealToLocalBlockSpace(selectionStart);
|
||||||
|
BlockChunkData chunkData = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(floorChunkPos, BlockChunkData.LOD_FULL_RES);
|
||||||
|
short type = chunkData.getType(floorBlockPos.x, floorBlockPos.y, floorBlockPos.z);
|
||||||
|
if(!RoomSolver.isFloor(type)){
|
||||||
|
floorIsValid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!floorIsValid){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!floorIsValid){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//scan for entrances to the room
|
||||||
|
LinkedList<Vector3d> entryPoints = RoomSolver.scanForEntrances(roomArea.getRectStart(), floorDimX, floorDimZ);
|
||||||
|
if(entryPoints.size() < 1){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomMetadata data = new RoomMetadata(roomArea);
|
||||||
|
data.setEntryPoints(entryPoints);
|
||||||
|
structureMetadata.getRooms().add(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans the room for entrances
|
||||||
|
* @param roomStart The start point of the room
|
||||||
|
* @param floorDimX The x dimension of the floor
|
||||||
|
* @param floorDimZ The z dimension of the floor
|
||||||
|
*/
|
||||||
|
private static LinkedList<Vector3d> scanForEntrances(Vector3d roomStart, int floorDimX, int floorDimZ){
|
||||||
|
LinkedList<Vector3d> rVal = new LinkedList<Vector3d>();
|
||||||
|
|
||||||
|
Vector3d tempVec = new Vector3d();
|
||||||
|
//scan for entrances to the room
|
||||||
|
int lastSolidBlock = 0;
|
||||||
|
|
||||||
|
//scan negative z dir
|
||||||
|
for(int x = 0; x < floorDimX; x++){
|
||||||
|
tempVec.set(roomStart).add(
|
||||||
|
x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
0,
|
||||||
|
-1 * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
);
|
||||||
|
Vector3i floorChunkPos = ClientWorldData.convertRealToChunkSpace(tempVec);
|
||||||
|
Vector3i floorBlockPos = ClientWorldData.convertRealToLocalBlockSpace(tempVec);
|
||||||
|
BlockChunkData chunkData = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(floorChunkPos, BlockChunkData.LOD_FULL_RES);
|
||||||
|
short type = chunkData.getType(floorBlockPos.x, floorBlockPos.y, floorBlockPos.z);
|
||||||
|
if(RoomSolver.isWall(type)){
|
||||||
|
int dist = (x - lastSolidBlock);
|
||||||
|
if(dist >= DOORWAY_MIN_WIDTH){
|
||||||
|
//scan for doorway from here
|
||||||
|
boolean foundDoor = true;
|
||||||
|
for(int z = lastSolidBlock + 1; z < x; z++){
|
||||||
|
for(int y = 0; y < DOORWAY_MIN_HEIGHT; y++){
|
||||||
|
tempVec.set(roomStart).add(
|
||||||
|
z * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
-1 * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
);
|
||||||
|
floorChunkPos = ClientWorldData.convertRealToChunkSpace(tempVec);
|
||||||
|
floorBlockPos = ClientWorldData.convertRealToLocalBlockSpace(tempVec);
|
||||||
|
chunkData = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(floorChunkPos, BlockChunkData.LOD_FULL_RES);
|
||||||
|
type = chunkData.getType(floorBlockPos.x, floorBlockPos.y, floorBlockPos.z);
|
||||||
|
if(!RoomSolver.isDoorway(type)){
|
||||||
|
foundDoor = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!foundDoor){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(foundDoor){
|
||||||
|
rVal.add(new Vector3d(roomStart).add(
|
||||||
|
(lastSolidBlock + dist / 2.0) * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastSolidBlock = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//scan positive z dir
|
||||||
|
for(int x = 0; x < floorDimX; x++){
|
||||||
|
tempVec.set(roomStart).add(
|
||||||
|
x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
0,
|
||||||
|
floorDimZ * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
);
|
||||||
|
Vector3i floorChunkPos = ClientWorldData.convertRealToChunkSpace(tempVec);
|
||||||
|
Vector3i floorBlockPos = ClientWorldData.convertRealToLocalBlockSpace(tempVec);
|
||||||
|
BlockChunkData chunkData = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(floorChunkPos, BlockChunkData.LOD_FULL_RES);
|
||||||
|
short type = chunkData.getType(floorBlockPos.x, floorBlockPos.y, floorBlockPos.z);
|
||||||
|
if(RoomSolver.isWall(type)){
|
||||||
|
int dist = (x - lastSolidBlock);
|
||||||
|
if(dist >= DOORWAY_MIN_WIDTH){
|
||||||
|
//scan for doorway from here
|
||||||
|
boolean foundDoor = true;
|
||||||
|
for(int z = lastSolidBlock + 1; z < x; z++){
|
||||||
|
for(int y = 0; y < DOORWAY_MIN_HEIGHT; y++){
|
||||||
|
tempVec.set(roomStart).add(
|
||||||
|
z * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
floorDimZ * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
);
|
||||||
|
floorChunkPos = ClientWorldData.convertRealToChunkSpace(tempVec);
|
||||||
|
floorBlockPos = ClientWorldData.convertRealToLocalBlockSpace(tempVec);
|
||||||
|
chunkData = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(floorChunkPos, BlockChunkData.LOD_FULL_RES);
|
||||||
|
type = chunkData.getType(floorBlockPos.x, floorBlockPos.y, floorBlockPos.z);
|
||||||
|
if(!RoomSolver.isDoorway(type)){
|
||||||
|
foundDoor = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!foundDoor){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(foundDoor){
|
||||||
|
rVal.add(new Vector3d(roomStart).add(
|
||||||
|
(lastSolidBlock + dist / 2.0) * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
0,
|
||||||
|
(floorDimZ - 1) * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastSolidBlock = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//scan negative x dir
|
||||||
|
lastSolidBlock = 0;
|
||||||
|
for(int x = 0; x < floorDimZ; x++){
|
||||||
|
tempVec.set(roomStart).add(
|
||||||
|
-1 * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
0,
|
||||||
|
x * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
);
|
||||||
|
Vector3i floorChunkPos = ClientWorldData.convertRealToChunkSpace(tempVec);
|
||||||
|
Vector3i floorBlockPos = ClientWorldData.convertRealToLocalBlockSpace(tempVec);
|
||||||
|
BlockChunkData chunkData = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(floorChunkPos, BlockChunkData.LOD_FULL_RES);
|
||||||
|
short type = chunkData.getType(floorBlockPos.x, floorBlockPos.y, floorBlockPos.z);
|
||||||
|
if(RoomSolver.isWall(type)){
|
||||||
|
int dist = (x - lastSolidBlock);
|
||||||
|
if(dist >= DOORWAY_MIN_WIDTH){
|
||||||
|
//scan for doorway from here
|
||||||
|
boolean foundDoor = true;
|
||||||
|
for(int z = lastSolidBlock + 1; z < x; z++){
|
||||||
|
for(int y = 0; y < DOORWAY_MIN_HEIGHT; y++){
|
||||||
|
tempVec.set(roomStart).add(
|
||||||
|
-1 * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
);
|
||||||
|
floorChunkPos = ClientWorldData.convertRealToChunkSpace(tempVec);
|
||||||
|
floorBlockPos = ClientWorldData.convertRealToLocalBlockSpace(tempVec);
|
||||||
|
chunkData = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(floorChunkPos, BlockChunkData.LOD_FULL_RES);
|
||||||
|
type = chunkData.getType(floorBlockPos.x, floorBlockPos.y, floorBlockPos.z);
|
||||||
|
if(!RoomSolver.isDoorway(type)){
|
||||||
|
foundDoor = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!foundDoor){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(foundDoor){
|
||||||
|
rVal.add(new Vector3d(roomStart).add(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
(lastSolidBlock + dist / 2.0) * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastSolidBlock = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//scan negative x dir
|
||||||
|
lastSolidBlock = 0;
|
||||||
|
for(int x = 0; x < floorDimZ; x++){
|
||||||
|
tempVec.set(roomStart).add(
|
||||||
|
floorDimX * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
0,
|
||||||
|
x * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
);
|
||||||
|
Vector3i floorChunkPos = ClientWorldData.convertRealToChunkSpace(tempVec);
|
||||||
|
Vector3i floorBlockPos = ClientWorldData.convertRealToLocalBlockSpace(tempVec);
|
||||||
|
BlockChunkData chunkData = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(floorChunkPos, BlockChunkData.LOD_FULL_RES);
|
||||||
|
short type = chunkData.getType(floorBlockPos.x, floorBlockPos.y, floorBlockPos.z);
|
||||||
|
if(RoomSolver.isWall(type)){
|
||||||
|
int dist = (x - lastSolidBlock);
|
||||||
|
if(dist >= DOORWAY_MIN_WIDTH){
|
||||||
|
//scan for doorway from here
|
||||||
|
boolean foundDoor = true;
|
||||||
|
for(int z = lastSolidBlock + 1; z < x; z++){
|
||||||
|
for(int y = 0; y < DOORWAY_MIN_HEIGHT; y++){
|
||||||
|
tempVec.set(roomStart).add(
|
||||||
|
floorDimX * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
);
|
||||||
|
floorChunkPos = ClientWorldData.convertRealToChunkSpace(tempVec);
|
||||||
|
floorBlockPos = ClientWorldData.convertRealToLocalBlockSpace(tempVec);
|
||||||
|
chunkData = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(floorChunkPos, BlockChunkData.LOD_FULL_RES);
|
||||||
|
type = chunkData.getType(floorBlockPos.x, floorBlockPos.y, floorBlockPos.z);
|
||||||
|
if(!RoomSolver.isDoorway(type)){
|
||||||
|
foundDoor = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!foundDoor){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(foundDoor){
|
||||||
|
rVal.add(new Vector3d(roomStart).add(
|
||||||
|
(floorDimX - 1) * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||||
|
0,
|
||||||
|
(lastSolidBlock + dist / 2.0) * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastSolidBlock = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a block is a valid floor block
|
||||||
|
* @param type The type of block
|
||||||
|
* @return true if it is a valid floor block, false otherwise
|
||||||
|
*/
|
||||||
|
private static boolean isFloor(short type){
|
||||||
|
return type != BlockChunkData.BLOCK_TYPE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a block is a valid wall block
|
||||||
|
* @param type The type of block
|
||||||
|
* @return true if it is a valid wall block, false otherwise
|
||||||
|
*/
|
||||||
|
private static boolean isWall(short type){
|
||||||
|
return type != BlockChunkData.BLOCK_TYPE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a block is a valid dooway block
|
||||||
|
* @param type The type of block
|
||||||
|
* @return true if is a valid doorway block, false otherwise
|
||||||
|
*/
|
||||||
|
private static boolean isDoorway(short type){
|
||||||
|
return type == BlockChunkData.BLOCK_TYPE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user