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.data.block.fab.RoomMetadata;
|
||||
import electrosphere.data.block.fab.StructureMetadata;
|
||||
import electrosphere.engine.Globals;
|
||||
|
||||
/**
|
||||
* Solves for the rooms in a structure
|
||||
@ -22,6 +23,16 @@ public class RoomSolver {
|
||||
* Maximum radius of room in blocks
|
||||
*/
|
||||
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)
|
||||
@ -67,9 +78,12 @@ public class RoomSolver {
|
||||
}
|
||||
}
|
||||
|
||||
//vectors used across scanning
|
||||
Vector3d selectionStart = new Vector3d();
|
||||
|
||||
while(localMaximums.size() > 0){
|
||||
Vector3i toConsider = localMaximums.poll();
|
||||
Vector3d selectionStart = new Vector3d(boundingArea.getRectStart()).add(
|
||||
selectionStart.set(boundingArea.getRectStart()).add(
|
||||
toConsider.x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
toConsider.y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
toConsider.z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||
@ -87,14 +101,301 @@ public class RoomSolver {
|
||||
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 roomCenterBlockPos = ClientWorldData.convertRealToLocalBlockSpace(selectionStart);
|
||||
|
||||
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