fix prism meshgen + farm plot geom

This commit is contained in:
austin 2025-05-28 21:11:15 -04:00
parent 732e0c51e9
commit 6b335310e8
10 changed files with 166 additions and 35 deletions

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file #maven.buildNumber.plugin properties file
#Wed May 28 11:59:04 EDT 2025 #Wed May 28 21:00:17 EDT 2025
buildNumber=639 buildNumber=643

View File

@ -2039,6 +2039,8 @@ Scaffolding for laying out farm plots around towns
Region interface Region interface
Town layout non-statically generates farm plots Town layout non-statically generates farm plots
Y-aligned prism meshgen Y-aligned prism meshgen
Rendering prism regions
Utilities for turning mesh gen algos into renderable entities

View File

@ -3,13 +3,20 @@ package electrosphere.entity;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import electrosphere.data.entity.graphics.NonproceduralModel; import electrosphere.data.entity.graphics.NonproceduralModel;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.queue.QueuedModel;
import electrosphere.entity.state.idle.ClientIdleTree; import electrosphere.entity.state.idle.ClientIdleTree;
import electrosphere.renderer.RenderUtils;
import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.model.Mesh;
/** /**
* Utilities to manipulating drawable entities (eg making an entity transparent) * Utilities to manipulating drawable entities (eg making an entity transparent)
@ -96,4 +103,26 @@ public class DrawableUtils {
} }
} }
/**
* Makes an entity drawable with a mesh to be generated via a callback
* @param entity The entity
* @param meshGenerator The callback to generate a mesh
*/
public static void makeEntityDrawable(Entity entity, Callable<Mesh> meshGenerator){
QueuedModel model = new QueuedModel(() -> {
Mesh mesh = meshGenerator.call();
return RenderUtils.wrapMeshInModel(mesh);
});
String path = Globals.assetManager.queuedAsset(model);
entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorOfLoadingModel(path));
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
entity.putData(EntityDataStrings.DATA_STRING_DRAW, true);
entity.putData(EntityDataStrings.DRAW_SOLID_PASS, true);
Globals.clientState.clientScene.registerEntityToTag(entity, EntityTags.DRAWABLE);
Globals.clientState.clientScene.registerEntityToTag(entity, EntityTags.DRAW_VOLUMETIC_SOLIDS_PASS);
Globals.clientState.clientScene.registerEntityToTag(entity, EntityTags.DRAW_CAST_SHADOW);
}
} }

View File

@ -630,6 +630,19 @@ public class RenderUtils {
return model; return model;
} }
/**
* Wraps a mesh in a model
* @param mesh The mesh
* @return The model that wraps the mesh
*/
public static Model wrapMeshInModel(Mesh mesh){
Model model = new Model();
//setup extra structures
mesh.setParent(model);
model.getMeshes().add(mesh);
return model;
}
@Deprecated @Deprecated
public static Model createBitmapDisplay(){ public static Model createBitmapDisplay(){

View File

@ -20,6 +20,11 @@ public class ActorUtils {
return rVal; return rVal;
} }
/**
* Creates an actor from an already-loading path
* @param modelPath The path
* @return The actor
*/
public static Actor createActorOfLoadingModel(String modelPath){ public static Actor createActorOfLoadingModel(String modelPath){
Actor rVal = new Actor(modelPath); Actor rVal = new Actor(modelPath);
return rVal; return rVal;

View File

@ -299,8 +299,8 @@ public class GeometryMeshGen {
Vector3d centerpoint = new Vector3d(points[0]); Vector3d centerpoint = new Vector3d(points[0]);
for(int i = 1; i < points.length; i++){ for(int i = 1; i < points.length; i++){
centerpoint = centerpoint.add(points[i]); centerpoint = centerpoint.add(points[i]);
centerpoint = centerpoint.mul(1.0f / (float)points.length);
} }
centerpoint = centerpoint.mul(1.0f / (float)points.length);
//allocate buffers //allocate buffers
@ -323,7 +323,7 @@ public class GeometryMeshGen {
normalBuffer.put(-1f); normalBuffer.put(-1f);
normalBuffer.put(0f); normalBuffer.put(0f);
normalBuffer.put(0f); normalBuffer.put(0f);
normalBuffer.put(11f); normalBuffer.put(1f);
normalBuffer.put(0f); normalBuffer.put(0f);
uvBuffer.put(0); uvBuffer.put(0);
uvBuffer.put(0); uvBuffer.put(0);
@ -353,23 +353,31 @@ public class GeometryMeshGen {
uvBuffer.put(1); uvBuffer.put(1);
uvBuffer.put(1); uvBuffer.put(1);
uvBuffer.put(1); uvBuffer.put(1);
int p1index = ((i + 0) * 2) + 2;
int p2index = ((i + 0) * 2) + 3;
int p3index = ((i + 1) * 2) + 2;
int p4index = ((i + 1) * 2) + 3;
//add face data //add face data
//bottom triangle //bottom triangle
faceBuffer.put(0); faceBuffer.put(0);
faceBuffer.put(((i + 0) * 2) + 0); faceBuffer.put(p1index);
faceBuffer.put(((i + 1) * 2) + 0); faceBuffer.put(p3index);
//top triangle //top triangle
faceBuffer.put(1); faceBuffer.put(1);
faceBuffer.put(((i + 0) * 2) + 1); faceBuffer.put(p2index);
faceBuffer.put(((i + 1) * 2) + 1); faceBuffer.put(p4index);
//perimeter face 1 //perimeter face 1
faceBuffer.put(((i + 0) * 2) + 0); faceBuffer.put(p2index);
faceBuffer.put(((i + 1) * 2) + 0); faceBuffer.put(p1index);
faceBuffer.put(((i + 0) * 2) + 1); faceBuffer.put(p3index);
//perimeter face 2 //perimeter face 2
faceBuffer.put(((i + 1) * 2) + 0); faceBuffer.put(p2index);
faceBuffer.put(((i + 0) * 2) + 1); faceBuffer.put(p3index);
faceBuffer.put(((i + 1) * 2) + 1); faceBuffer.put(p4index);
// System.out.println(p2index + "--" + p4index);
// System.out.println("|\\ |");
// System.out.println("| \\|");
// System.out.println(p1index + "--" + p3index);
} }
// //
@ -392,11 +400,31 @@ public class GeometryMeshGen {
uvBuffer.put(1); uvBuffer.put(1);
uvBuffer.put(1); uvBuffer.put(1);
uvBuffer.put(1); uvBuffer.put(1);
//add face data
int p1index = (3 * 2) + 2;
int p2index = (3 * 2) + 3;
int p3index = (0 * 2) + 2;
int p4index = (0 * 2) + 3;
//bottom triangle
faceBuffer.put(0);
faceBuffer.put(p1index);
faceBuffer.put(p3index);
//top triangle
faceBuffer.put(1);
faceBuffer.put(p2index);
faceBuffer.put(p4index);
//perimeter face 1
faceBuffer.put(p2index);
faceBuffer.put(p1index);
faceBuffer.put(p3index);
//perimeter face 2
faceBuffer.put(p2index);
faceBuffer.put(p3index);
faceBuffer.put(p4index);
//actually store in mesh //actually store in mesh
int elementCount = points.length * 12;
try { try {
//actually buffer vertices //actually buffer vertices
if(vertBuffer.position() > 0){ if(vertBuffer.position() > 0){
@ -404,19 +432,19 @@ public class GeometryMeshGen {
mesh.bufferVertices(vertBuffer, 3); mesh.bufferVertices(vertBuffer, 3);
} }
//actually buffer normals //actually buffer normals
if(normalBuffer != null && normalBuffer.position() > 0){ if(normalBuffer.position() > 0){
normalBuffer.flip(); normalBuffer.flip();
mesh.bufferNormals(normalBuffer, 3); mesh.bufferNormals(normalBuffer, 3);
} }
//actually buffer UVs //actually buffer UVs
if(uvBuffer != null && uvBuffer.position() > 0){ if(uvBuffer.position() > 0){
uvBuffer.flip(); uvBuffer.flip();
mesh.bufferTextureCoords(uvBuffer, 2); mesh.bufferTextureCoords(uvBuffer, 2);
} }
//buffer element indices //buffer element indices
if(faceBuffer.position() > 0){ if(faceBuffer.position() > 0){
faceBuffer.flip(); faceBuffer.flip();
mesh.bufferFaces(faceBuffer, elementCount); mesh.bufferFaces(faceBuffer, faceBuffer.limit());
} }
} catch (NullPointerException ex){ } catch (NullPointerException ex){
ex.printStackTrace(); ex.printStackTrace();

View File

@ -456,6 +456,9 @@ public class Mesh {
if(selectedProgram == null){ if(selectedProgram == null){
selectedProgram = shader; selectedProgram = shader;
} }
if(selectedProgram == null){
selectedProgram = Globals.defaultMeshShader;
}
openGLState.setActiveShader(renderPipelineState, selectedProgram); openGLState.setActiveShader(renderPipelineState, selectedProgram);
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }

View File

@ -29,7 +29,10 @@ import electrosphere.data.entity.common.CommonEntityType;
import electrosphere.data.entity.grident.GridAlignedData; import electrosphere.data.entity.grident.GridAlignedData;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.DrawableUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags; import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
@ -39,6 +42,7 @@ import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.renderer.OpenGLState; import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.RenderingEngine; import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.meshgen.GeometryMeshGen;
import electrosphere.renderer.model.Model; import electrosphere.renderer.model.Model;
import electrosphere.renderer.pipelines.RenderPipeline; import electrosphere.renderer.pipelines.RenderPipeline;
import electrosphere.renderer.texture.Texture; import electrosphere.renderer.texture.Texture;
@ -47,6 +51,8 @@ import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.macro.civilization.road.Road; import electrosphere.server.macro.civilization.road.Road;
import electrosphere.server.macro.structure.VirtualStructure; import electrosphere.server.macro.structure.VirtualStructure;
import electrosphere.util.math.SpatialMathUtils; import electrosphere.util.math.SpatialMathUtils;
import electrosphere.util.math.region.Region;
import electrosphere.util.math.region.RegionPrism;
/** /**
* Pipeline for rendering content to assist debugging * Pipeline for rendering content to assist debugging
@ -56,6 +62,11 @@ public class DebugContentPipeline implements RenderPipeline {
//The bone debugging pipeline //The bone debugging pipeline
DebugBonesPipeline debugBonesPipeline = new DebugBonesPipeline(); DebugBonesPipeline debugBonesPipeline = new DebugBonesPipeline();
/**
* The farm plot macro data entities to draw
*/
private List<Entity> farmPlotEntities = new LinkedList<Entity>();
@Override @Override
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) { public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
Globals.profiler.beginCpuSample("DebugContentPipeline.render"); Globals.profiler.beginCpuSample("DebugContentPipeline.render");
@ -210,6 +221,31 @@ public class DebugContentPipeline implements RenderPipeline {
for(Road road : Globals.serverState.realmManager.first().getMacroData().getRoads()){ for(Road road : Globals.serverState.realmManager.first().getMacroData().getRoads()){
DebugContentPipeline.renderTube(openGLState, renderPipelineState, modelTransformMatrix, road.getPoint1(), road.getPoint2(), road.getRadius(), AssetDataStrings.TEXTURE_BLUE_TRANSPARENT); DebugContentPipeline.renderTube(openGLState, renderPipelineState, modelTransformMatrix, road.getPoint1(), road.getPoint2(), road.getRadius(), AssetDataStrings.TEXTURE_BLUE_TRANSPARENT);
} }
if(this.farmPlotEntities.isEmpty()){
if(Globals.serverState.realmManager.first().getMacroData().getTown(0).getFarmPlots().size() > 0){
for(Region region : Globals.serverState.realmManager.first().getMacroData().getTown(0).getFarmPlots()){
if(region instanceof RegionPrism prism){
Entity plotDebugEnt = EntityCreationUtils.createClientSpatialEntity();
DrawableUtils.makeEntityDrawable(plotDebugEnt, () -> {
Vector3d[] finalPoints = new Vector3d[prism.getPoints().length];
for(int i = 0; i < finalPoints.length; i++){
finalPoints[i] = new Vector3d(prism.getPoints()[i]).sub(prism.getAABB().minX,prism.getAABB().minY,prism.getAABB().minZ);
}
return GeometryMeshGen.genPrism(finalPoints, prism.getHeight());
});
EntityUtils.getPosition(plotDebugEnt).set(prism.getAABB().minX,prism.getAABB().minY,prism.getAABB().minZ);
this.farmPlotEntities.add(plotDebugEnt);
}
}
}
}
} else {
if(!this.farmPlotEntities.isEmpty()){
for(Entity entity : this.farmPlotEntities){
ClientEntityUtils.destroyEntity(entity);
}
this.farmPlotEntities.clear();
}
} }
// //

View File

@ -272,11 +272,11 @@ public class TownLayout {
//this is +0,+0 //this is +0,+0
plotPoint1.set(currPoint); plotPoint1.set(currPoint);
scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER * (x + 1),0,TOWN_LAYOUT_SCALER * (z + 0)); scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER * (x + 1),0,TOWN_LAYOUT_SCALER * (z + 0));
plotPoint2.set(scanPoint); plotPoint2 = TownLayout.getTownCenter(realm, scanPoint);
scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER * (x + 1),0,TOWN_LAYOUT_SCALER * (z + 1)); scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER * (x + 1),0,TOWN_LAYOUT_SCALER * (z + 1));
plotPoint3.set(scanPoint); plotPoint3 = TownLayout.getTownCenter(realm, scanPoint);
scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER * (x + 0),0,TOWN_LAYOUT_SCALER * (z + 1)); scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER * (x + 0),0,TOWN_LAYOUT_SCALER * (z + 1));
plotPoint4.set(scanPoint); plotPoint4 = TownLayout.getTownCenter(realm, scanPoint);
if( if(
plotPoint1.distance(townCenter) > TOWN_CENTER_RADIUS && plotPoint1.distance(townCenter) > TOWN_CENTER_RADIUS &&
plotPoint2.distance(townCenter) > TOWN_CENTER_RADIUS && plotPoint2.distance(townCenter) > TOWN_CENTER_RADIUS &&
@ -284,6 +284,9 @@ public class TownLayout {
plotPoint4.distance(townCenter) > TOWN_CENTER_RADIUS plotPoint4.distance(townCenter) > TOWN_CENTER_RADIUS
){ ){
plotPoint1.y = realm.getServerWorldData().getServerTerrainManager().getElevation(plotPoint1); plotPoint1.y = realm.getServerWorldData().getServerTerrainManager().getElevation(plotPoint1);
plotPoint2.y = plotPoint1.y;
plotPoint3.y = plotPoint1.y;
plotPoint4.y = plotPoint1.y;
//define a farm plot with these points //define a farm plot with these points
TownLayout.generateFarmPlot(realm,town,plotPoint1,plotPoint2,plotPoint3,plotPoint4); TownLayout.generateFarmPlot(realm,town,plotPoint1,plotPoint2,plotPoint3,plotPoint4);
} }
@ -413,10 +416,10 @@ public class TownLayout {
*/ */
private static void generateFarmPlot(Realm realm, Town town, Vector3d point1, Vector3d point2, Vector3d point3, Vector3d point4){ private static void generateFarmPlot(Realm realm, Town town, Vector3d point1, Vector3d point2, Vector3d point3, Vector3d point4){
RegionPrism region = RegionPrism.create(new Vector3d[]{ RegionPrism region = RegionPrism.create(new Vector3d[]{
new Vector3d(point1).add(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0), new Vector3d(point1).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point2).add(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0), new Vector3d(point2).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point3).add(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0), new Vector3d(point3).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point4).add(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0), new Vector3d(point4).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
}, FARM_PLOT_DEFAULT_HEIGHT); }, FARM_PLOT_DEFAULT_HEIGHT);
town.addFarmPlot(region); town.addFarmPlot(region);
} }

View File

@ -48,25 +48,37 @@ public class RegionPrism implements Region {
if(rVal.aabb.minX > points[i].x){ if(rVal.aabb.minX > points[i].x){
rVal.aabb.minX = points[i].x; rVal.aabb.minX = points[i].x;
} }
if(rVal.aabb.minX > points[i].y){ if(rVal.aabb.minZ > points[i].z){
rVal.aabb.minX = points[i].y; rVal.aabb.minZ = points[i].z;
}
if(rVal.aabb.minX > points[i].z){
rVal.aabb.minX = points[i].z;
} }
if(rVal.aabb.maxX < points[i].x){ if(rVal.aabb.maxX < points[i].x){
rVal.aabb.maxX = points[i].x; rVal.aabb.maxX = points[i].x;
} }
if(rVal.aabb.maxX < points[i].y){ if(rVal.aabb.maxZ < points[i].z){
rVal.aabb.maxX = points[i].y; rVal.aabb.maxZ = points[i].z;
}
if(rVal.aabb.maxX < points[i].z){
rVal.aabb.maxX = points[i].z;
} }
} }
rVal.aabb.minY = points[0].y;
rVal.aabb.maxY = points[0].y + height;
return rVal; return rVal;
} }
/**
* Gets the height of the prism
* @return The height
*/
public double getHeight(){
return this.height;
}
/**
* Gets the points of the prism
* @return The points of the prism
*/
public Vector3d[] getPoints(){
return this.points;
}
@Override @Override
public RegionType getType() { public RegionType getType() {
return RegionType.Y_ALIGNED_PRISM; return RegionType.Y_ALIGNED_PRISM;