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
#Wed May 28 11:59:04 EDT 2025
buildNumber=639
#Wed May 28 21:00:17 EDT 2025
buildNumber=643

View File

@ -2039,6 +2039,8 @@ Scaffolding for laying out farm plots around towns
Region interface
Town layout non-statically generates farm plots
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.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.joml.Vector3f;
import electrosphere.data.entity.graphics.NonproceduralModel;
import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.queue.QueuedModel;
import electrosphere.entity.state.idle.ClientIdleTree;
import electrosphere.renderer.RenderUtils;
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)
@ -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;
}
/**
* 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
public static Model createBitmapDisplay(){

View File

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

View File

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

View File

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

View File

@ -29,7 +29,10 @@ import electrosphere.data.entity.common.CommonEntityType;
import electrosphere.data.entity.grident.GridAlignedData;
import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.DrawableUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
@ -39,6 +42,7 @@ import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.meshgen.GeometryMeshGen;
import electrosphere.renderer.model.Model;
import electrosphere.renderer.pipelines.RenderPipeline;
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.structure.VirtualStructure;
import electrosphere.util.math.SpatialMathUtils;
import electrosphere.util.math.region.Region;
import electrosphere.util.math.region.RegionPrism;
/**
* Pipeline for rendering content to assist debugging
@ -56,6 +62,11 @@ public class DebugContentPipeline implements RenderPipeline {
//The bone debugging pipeline
DebugBonesPipeline debugBonesPipeline = new DebugBonesPipeline();
/**
* The farm plot macro data entities to draw
*/
private List<Entity> farmPlotEntities = new LinkedList<Entity>();
@Override
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
Globals.profiler.beginCpuSample("DebugContentPipeline.render");
@ -210,6 +221,31 @@ public class DebugContentPipeline implements RenderPipeline {
for(Road road : Globals.serverState.realmManager.first().getMacroData().getRoads()){
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
plotPoint1.set(currPoint);
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));
plotPoint3.set(scanPoint);
plotPoint3 = TownLayout.getTownCenter(realm, scanPoint);
scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER * (x + 0),0,TOWN_LAYOUT_SCALER * (z + 1));
plotPoint4.set(scanPoint);
plotPoint4 = TownLayout.getTownCenter(realm, scanPoint);
if(
plotPoint1.distance(townCenter) > TOWN_CENTER_RADIUS &&
plotPoint2.distance(townCenter) > TOWN_CENTER_RADIUS &&
@ -284,6 +284,9 @@ public class TownLayout {
plotPoint4.distance(townCenter) > TOWN_CENTER_RADIUS
){
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
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){
RegionPrism region = RegionPrism.create(new Vector3d[]{
new Vector3d(point1).add(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point2).add(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point3).add(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point4).add(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point1).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point2).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point3).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point4).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
}, FARM_PLOT_DEFAULT_HEIGHT);
town.addFarmPlot(region);
}

View File

@ -48,25 +48,37 @@ public class RegionPrism implements Region {
if(rVal.aabb.minX > points[i].x){
rVal.aabb.minX = points[i].x;
}
if(rVal.aabb.minX > points[i].y){
rVal.aabb.minX = points[i].y;
}
if(rVal.aabb.minX > points[i].z){
rVal.aabb.minX = points[i].z;
if(rVal.aabb.minZ > points[i].z){
rVal.aabb.minZ = points[i].z;
}
if(rVal.aabb.maxX < points[i].x){
rVal.aabb.maxX = points[i].x;
}
if(rVal.aabb.maxX < points[i].y){
rVal.aabb.maxX = points[i].y;
}
if(rVal.aabb.maxX < points[i].z){
rVal.aabb.maxX = points[i].z;
if(rVal.aabb.maxZ < points[i].z){
rVal.aabb.maxZ = points[i].z;
}
}
rVal.aabb.minY = points[0].y;
rVal.aabb.maxY = points[0].y + height;
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
public RegionType getType() {
return RegionType.Y_ALIGNED_PRISM;