work on rotating buildings on placement
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-23 22:36:29 -04:00
parent 086c6da72e
commit 2f05fc06dd
5 changed files with 156 additions and 24 deletions

View File

@ -49,7 +49,7 @@ public class BeginStructureNode implements AITreeNode {
Vector3d placementPos = StructurePlacementUtils.getPlacementPosition(macroData, structureData, position);
//add to macro data
VirtualStructure struct = VirtualStructure.createStructure(macroData, structureData, placementPos);
VirtualStructure struct = VirtualStructure.createStructure(macroData, structureData, placementPos, VirtualStructure.ROT_FACE_NORTH);
struct.setRepairable(true);
struct.setFab(BlockFab.read(FileUtils.getAssetFile(struct.getFabPath())));
// macroData.getStructures().add(struct);

View File

@ -1,8 +1,10 @@
package electrosphere.server.macro.structure;
import org.joml.AABBd;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import electrosphere.controls.cursor.CursorState;
import electrosphere.data.block.fab.BlockFab;
import electrosphere.data.struct.StructureData;
import electrosphere.server.macro.MacroData;
@ -14,56 +16,84 @@ import electrosphere.util.annotation.Exclude;
*/
public class VirtualStructure implements MacroAreaObject {
/**
* Rotates the structure to face east
*/
public static final int ROT_FACE_EAST = 0;
/**
* Rotates the structure ot face north
*/
public static final int ROT_FACE_NORTH = 1;
/**
* Rotates the structure to face west
*/
public static final int ROT_FACE_WEST = 2;
/**
* Rotates the structure to face south
*/
public static final int ROT_FACE_SOUTH = 3;
/**
* The id of the structure
*/
int id;
private int id;
/**
* The position of the structure
*/
Vector3d position;
private Vector3d position;
/**
* The rotation of the fab
*/
private int rotation = 0;
/**
* The bounding box for the structure
*/
AABBd aabb;
private AABBd aabb;
/**
* The path to the block fab for the structure
*/
String fabPath;
private String fabPath;
/**
* The actual fab
*/
@Exclude
BlockFab fab;
private BlockFab fab;
/**
* The type of the structure
*/
String type;
private String type;
/**
* Tracks whether this structure needs repairs or not
*/
boolean repairable = false;
private boolean repairable = false;
/**
* Creates a structure
* @param macroData The macro data
* @param data The data
* @param position The position
* @param rotation The rotation of the structure
* @return The structure
*/
public static VirtualStructure createStructure(MacroData macroData, StructureData data, Vector3d position){
public static VirtualStructure createStructure(MacroData macroData, StructureData data, Vector3d position, int rotation){
VirtualStructure rVal = new VirtualStructure();
rVal.fabPath = data.getFabPath();
rVal.fab = data.getFab();
rVal.type = data.getId();
rVal.position = position;
rVal.aabb = new AABBd(new Vector3d(position), new Vector3d(position).add(data.getDimensions()));
rVal.rotation = rotation;
rVal.aabb = new AABBd();
VirtualStructure.setAABB(rVal.aabb, rVal.position, data.getDimensions(), rotation);
macroData.addStructure(rVal);
return rVal;
}
@ -146,6 +176,40 @@ public class VirtualStructure implements MacroAreaObject {
public void setId(int id){
this.id = id;
}
/**
* Sets the rotation of the structure
* @param rotation The rotation
*/
public void setRotation(int rotation){
this.rotation = rotation;
}
/**
* Gets the rotation of the structure
* @return The rotation of the structure
*/
public int getRotation(){
return this.rotation;
}
/**
* Calculates the aabb of this structure given a rotation, dims, and start position
* @param aabb The aabb to populate
* @param startPos The start position
* @param dims The dimensions of the structure
* @param rotation The rotation
*/
public static void setAABB(AABBd aabb, Vector3d startPos, Vector3d dims, int rotation){
//construct aabb based on rotation
Quaterniond rotationQuat = CursorState.getBlockRotation(rotation);
Vector3d dimVec = new Vector3d(dims);
rotationQuat.transform(dimVec);
Vector3d startVec = startPos;
Vector3d endVec = new Vector3d(startPos).add(dimVec);
aabb.setMin(Math.min(startVec.x,endVec.x),Math.min(startVec.y,endVec.y),Math.min(startVec.z,endVec.z));
aabb.setMax(Math.max(startVec.x,endVec.x),Math.max(startVec.y,endVec.y),Math.max(startVec.z,endVec.z));
}
}

View File

@ -5,9 +5,11 @@ import java.util.List;
import java.util.stream.Collectors;
import org.joml.AABBd;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.joml.Vector3i;
import electrosphere.controls.cursor.CursorState;
import electrosphere.data.struct.StructureData;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
@ -212,6 +214,8 @@ public class TownLayout {
closedSet.add(openHash);
}
// System.out.println("Structure count: " + town.getStructures(macroData).size());
town.setResolution(Town.TOWN_RES_MAX);
}
@ -252,10 +256,23 @@ public class TownLayout {
//offset applied to the scan location to not place it on top of the road
Vector3d roadOffset = null;
int rotation1 = VirtualStructure.ROT_FACE_WEST;
int rotation2 = VirtualStructure.ROT_FACE_EAST;
Vector3d rotOffset = new Vector3d();
Quaterniond rotQuat1 = null;
Quaterniond rotQuat2 = null;
if(isNorthSouth){
roadOffset = new Vector3d(roadRadiusOffsetRaw,0,0);
rotation1 = VirtualStructure.ROT_FACE_SOUTH;
rotation2 = VirtualStructure.ROT_FACE_NORTH;
rotQuat1 = CursorState.getBlockRotation(rotation1);
rotQuat2 = CursorState.getBlockRotation(rotation2);
} else {
roadOffset = new Vector3d(0,0,roadRadiusOffsetRaw);
rotation1 = VirtualStructure.ROT_FACE_WEST;
rotation2 = VirtualStructure.ROT_FACE_EAST;
rotQuat1 = CursorState.getBlockRotation(rotation1);
rotQuat2 = CursorState.getBlockRotation(rotation2);
}
//the position to try at
@ -267,17 +284,29 @@ public class TownLayout {
//scan along the length of the road
for(int i = roadRadiusOffsetRaw; i < len; i++){
//update rotation spatial offset based on current struct
rotOffset.set(structureData.getDimensions());
rotQuat1.transform(rotOffset);
rotOffset.x = Math.min(rotOffset.x,0);
rotOffset.y = Math.min(rotOffset.y,0);
rotOffset.z = Math.min(rotOffset.z,0);
rotOffset.mul(-1);
//solve terrain position to place
currPos.set(startPoint).lerp(endPoint,i/(double)len).add(roadOffset);
// currPos.set(dir).mul(i).add(startPoint).add(roadOffset);
currPos.y = realm.getServerWorldData().getServerTerrainManager().getElevation(currPos);
//apply structure placement offset
currPos.add(structureData.getPlacementOffset());
//add offset to re-align after rotation
currPos.add(rotOffset);
//update aabb
aabb.setMin(currPos);
aabb.setMax(new Vector3d(currPos).add(structureData.getDimensions()));
VirtualStructure.setAABB(aabb, currPos, structureData.getDimensions(), rotation1);
if(!macroData.intersectsStruct(aabb)){
VirtualStructure struct = VirtualStructure.createStructure(macroData, structureData, currPos);
VirtualStructure struct = VirtualStructure.createStructure(macroData, structureData, currPos, rotation1);
town.addStructure(struct);
//TODO: once have successfully placed this structure type, pick a new one to place
}
@ -285,16 +314,27 @@ public class TownLayout {
//scan along the length of the road
for(int i = 0; i < len; i++){
//update rotation spatial offset based on current struct
rotOffset.set(structureData.getDimensions());
rotQuat2.transform(rotOffset);
rotOffset.x = Math.max(rotOffset.x,0);
rotOffset.y = Math.max(rotOffset.y,0);
rotOffset.z = Math.max(rotOffset.z,0);
rotOffset.mul(-1);
//solve terrain position to place
currPos.set(dir).mul(i).add(startPoint).sub(roadOffset).sub(structureData.getDimensions().x,0,structureData.getDimensions().z);
currPos.set(dir).mul(i).add(startPoint).sub(roadOffset).sub(structureData.getDimensions());
currPos.y = realm.getServerWorldData().getServerTerrainManager().getElevation(currPos);
//apply structure placement offset
currPos.add(structureData.getPlacementOffset());
//add offset to re-align after rotation
// currPos.add(5,0,5);
//update aabb
aabb.setMin(currPos);
aabb.setMax(new Vector3d(currPos).add(structureData.getDimensions()));
VirtualStructure.setAABB(aabb, currPos, structureData.getDimensions(), rotation2);
if(!macroData.intersectsStruct(aabb)){
VirtualStructure struct = VirtualStructure.createStructure(macroData, structureData, currPos);
VirtualStructure struct = VirtualStructure.createStructure(macroData, structureData, currPos, rotation2);
town.addStructure(struct);
//TODO: once have successfully placed this structure type, pick a new one to place
}

View File

@ -7,11 +7,13 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.joml.AABBd;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.joml.Vector3i;
import electrosphere.client.block.BlockChunkCache;
import electrosphere.client.block.BlockChunkData;
import electrosphere.controls.cursor.CursorState;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.datacell.ServerWorldData;
@ -223,8 +225,9 @@ public class ServerBlockChunkGenerationThread implements Runnable {
Vector3i chunkPos = new Vector3i(worldX, worldY, worldZ);
Vector3i blockPos = new Vector3i(0,0,0);
Vector3d chunkRealPos = ServerWorldData.convertChunkToRealSpace(chunkPos);
Vector3i localBlockPos = new Vector3i();
Vector3d localBlockPos = new Vector3d();
Vector3d currRealPos = new Vector3d(chunkRealPos);
Vector3d dimVec = new Vector3d();
//contains at least one structure
for(int x = 0; x < BlockChunkData.CHUNK_DATA_WIDTH; x++){
for(int y = 0; y < BlockChunkData.CHUNK_DATA_WIDTH; y++){
@ -241,13 +244,38 @@ public class ServerBlockChunkGenerationThread implements Runnable {
if(struct.getAABB().testPoint(currRealPos.x, currRealPos.y, currRealPos.z)){
AABBd aabb = struct.getAABB();
localBlockPos.set(
(int)((currRealPos.x - aabb.minX) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
(int)((currRealPos.y - aabb.minY) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
(int)((currRealPos.z - aabb.minZ) / BlockChunkData.BLOCK_SIZE_MULTIPLIER)
(int)Math.round((currRealPos.x - aabb.minX) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
(int)Math.round((currRealPos.y - aabb.minY) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
(int)Math.round((currRealPos.z - aabb.minZ) / BlockChunkData.BLOCK_SIZE_MULTIPLIER)
);
Quaterniond rotationQuat = CursorState.getBlockRotation(struct.getRotation());
rotationQuat.transform(localBlockPos);
dimVec.set(struct.getFab().getDimensions());
rotationQuat.transform(dimVec);
dimVec.absolute();
if(localBlockPos.x < 0){
localBlockPos.x = (int)(dimVec.x + localBlockPos.x);
}
if(localBlockPos.y < 0){
localBlockPos.y = (int)(dimVec.y + localBlockPos.y);
}
if(localBlockPos.z < 0){
localBlockPos.z = (int)(dimVec.z + localBlockPos.z);
}
localBlockPos.x = Math.round(localBlockPos.x);
localBlockPos.y = Math.round(localBlockPos.y);
localBlockPos.z = Math.round(localBlockPos.z);
//structure file might have dimensions larger than fab, so need to make sure we're inbounds on fab file to draw data from fab file
if(localBlockPos.x < struct.getFab().getDimensions().x && localBlockPos.y < struct.getFab().getDimensions().y && localBlockPos.z < struct.getFab().getDimensions().z){
short blocktype = struct.getFab().getType(localBlockPos.x,localBlockPos.y,localBlockPos.z);
if(
(int)localBlockPos.x >= 0 &&
(int)localBlockPos.y >= 0 &&
(int)localBlockPos.z >= 0 &&
(int)localBlockPos.x < struct.getFab().getDimensions().x &&
(int)localBlockPos.y < struct.getFab().getDimensions().y &&
(int)localBlockPos.z < struct.getFab().getDimensions().z
){
short blocktype = struct.getFab().getType((int)localBlockPos.x,(int)localBlockPos.y,(int)localBlockPos.z);
chunk.setType(x, y, z, blocktype);
placedBlock = true;
}

View File

@ -75,7 +75,7 @@ public class CharaSimulation {
Vector3d placementPos = StructurePlacementUtils.getPlacementPosition(macroData, structureData, position);
//add to macro data
VirtualStructure struct = VirtualStructure.createStructure(macroData, structureData, placementPos);
VirtualStructure struct = VirtualStructure.createStructure(macroData, structureData, placementPos, VirtualStructure.ROT_FACE_NORTH);
struct.setRepairable(true);
struct.setFab(BlockFab.read(FileUtils.getAssetFile(struct.getFabPath())));
CharacterUtils.addShelter(chara, struct);