diff --git a/src/main/java/engine/components/StaticGeometry.java b/src/main/java/engine/components/StaticGeometry.java new file mode 100644 index 00000000..96eb8d1a --- /dev/null +++ b/src/main/java/engine/components/StaticGeometry.java @@ -0,0 +1,85 @@ +package engine.components; + +import engine.render.Material; +import engine.vbo.VBO; +import engine.vbo.VBOFactory; +import math.Bounds; +import mesh.Mesh3D; +import mesh.util.MeshBoundsCalculator; +import workspace.ui.Graphics; + +/** + * The {@code Geometry} class represents a 3D object in a scene with a mesh and material applied to + * it. It is responsible for rendering the mesh and applying the appropriate material to it. The + * class also provides access to the mesh's bounding box, which is useful for purposes like culling, + * spatial partitioning, and debugging. + * + *

This class implements the {@link RenderableComponent} interface, indicating that it has a + * render method to be invoked during the render loop of the engine. + * + * @see RenderableComponent + * @see Material + * @see Mesh3D + * @see Bounds + */ +public class StaticGeometry extends AbstractComponent implements RenderableComponent { + + /** The bounding box of the mesh used for culling, spatial partitioning, and debugging. */ + private Bounds bounds; + + private VBO vbo; + + /** + * Constructs a {@code StaticGeometry} with the specified mesh and a default material. + * + * @param mesh The {@link Mesh3D} object representing the geometry of the object. + * @throws IllegalArgumentException If the mesh is {@code null}. + */ + public StaticGeometry(Mesh3D mesh) { + this(mesh, Material.DEFAULT_WHITE); + } + + /** + * Constructs a {@code StaticGeometry} with the specified mesh and material. + * + * @param mesh The {@link Mesh3D} object representing the geometry of the object. + * @param material The {@link Material} to be applied to the mesh. + * @throws IllegalArgumentException If the mesh or material is {@code null}. + */ + public StaticGeometry(Mesh3D mesh, Material material) { + validate(mesh, material); + this.bounds = MeshBoundsCalculator.calculateBounds(mesh); + this.vbo = VBOFactory.getInstance().create(); + this.vbo.create(mesh, material); + } + + /** + * Validates the mesh and material to ensure they are not {@code null}. + * + * @param mesh The {@link Mesh3D} object to validate. + * @param material The {@link Material} to validate. + * @throws IllegalArgumentException If the mesh or material is {@code null}. + */ + private void validate(Mesh3D mesh, Material material) { + if (mesh == null) { + throw new IllegalArgumentException("Mesh cannot be null."); + } + if (material == null) { + throw new IllegalArgumentException("Material cannot be null."); + } + } + + @Override + public void render(Graphics g) { + g.draw(vbo); + } + + @Override + public void update(float tpf) {} + + @Override + public void onAttach() {} + + @Override + public void onDetach() {} +} diff --git a/src/main/java/engine/demos/landmass/MapGenerator.java b/src/main/java/engine/demos/landmass/MapGenerator.java index 9bbe3dab..c04ea4c5 100644 --- a/src/main/java/engine/demos/landmass/MapGenerator.java +++ b/src/main/java/engine/demos/landmass/MapGenerator.java @@ -13,7 +13,8 @@ */ public class MapGenerator { - private int chunkSize = 241; +// private int chunkSize = 481; + private int chunkSize = 961; private int mapWidth = chunkSize; private int mapHeight = chunkSize; private int seed = 221; diff --git a/src/main/java/engine/demos/landmass/ProceduralLandmassDemo.java b/src/main/java/engine/demos/landmass/ProceduralLandmassDemo.java index 596a1e0b..751850c7 100644 --- a/src/main/java/engine/demos/landmass/ProceduralLandmassDemo.java +++ b/src/main/java/engine/demos/landmass/ProceduralLandmassDemo.java @@ -2,7 +2,7 @@ import engine.application.ApplicationSettings; import engine.application.BasicApplication; -import engine.components.Geometry; +import engine.components.StaticGeometry; import engine.components.RoundReticle; import engine.components.SmoothFlyByCameraControl; import engine.render.Material; @@ -41,7 +41,7 @@ public enum DrawMode { } // Configuration fields - private int levelOfDetail = 1; // Level of detail for the terrain mesh (0 - 6) + private int levelOfDetail = 0; // Level of detail for the terrain mesh (0 - 6) private DrawMode drawMode = DrawMode.COLOR_MAP; private Scene scene; @@ -103,7 +103,7 @@ private void createTerrain() { terrainMesh.apply(new ScaleModifier(3)); terrainMesh.apply(new CenterAtModifier()); - Geometry terrainGeometry = new Geometry(terrainMesh, mapMaterial); + StaticGeometry terrainGeometry = new StaticGeometry(terrainMesh, mapMaterial); SceneNode terrainNode = new SceneNode(); terrainNode.addComponent(terrainGeometry); scene.addNode(terrainNode); diff --git a/src/main/java/engine/processing/ProcessingApplication.java b/src/main/java/engine/processing/ProcessingApplication.java index 2b755112..a452b1a5 100644 --- a/src/main/java/engine/processing/ProcessingApplication.java +++ b/src/main/java/engine/processing/ProcessingApplication.java @@ -7,6 +7,7 @@ import engine.input.MouseInput; import engine.resources.ResourceManager; import engine.resources.TextureManager; +import engine.vbo.VBOFactory; import processing.core.PApplet; import workspace.GraphicsPImpl; import workspace.ui.Graphics; @@ -33,6 +34,8 @@ public void setup() { Graphics g = new GraphicsPImpl(this); ResourceManager.getInstance().setImageLoader(new ProcessingImageLoader(this)); TextureManager.getInstance().setTextureLoader(new ProcessingTextureLoader(this)); + VBOFactory.getInstance() + .setVBOCreationStrategy(new ProcessingVBOCreationStrategy(getGraphics())); container.setGraphics(g); getSurface().setTitle(settings.getTitle()); setupInput(); diff --git a/src/main/java/engine/vbo/VBO.java b/src/main/java/engine/vbo/VBO.java new file mode 100644 index 00000000..2e4e3a69 --- /dev/null +++ b/src/main/java/engine/vbo/VBO.java @@ -0,0 +1,22 @@ +package engine.vbo; + +import engine.render.Material; +import mesh.Mesh3D; + +public interface VBO { + void create(float[] vertices, int[] indices); + + void create(Mesh3D mesh, Material material); + + void bind(); + + void unbind(); + + void updateData(float[] newData); + + void delete(); + + int getVertexCount(); + + int getFaceCount(); +} diff --git a/src/main/java/engine/vbo/VBOCreationStrategy.java b/src/main/java/engine/vbo/VBOCreationStrategy.java new file mode 100644 index 00000000..8b755319 --- /dev/null +++ b/src/main/java/engine/vbo/VBOCreationStrategy.java @@ -0,0 +1,6 @@ +package engine.vbo; + +public interface VBOCreationStrategy { + + public VBO create(); +} diff --git a/src/main/java/engine/vbo/VBOFactory.java b/src/main/java/engine/vbo/VBOFactory.java new file mode 100644 index 00000000..eb6e6fa0 --- /dev/null +++ b/src/main/java/engine/vbo/VBOFactory.java @@ -0,0 +1,28 @@ +package engine.vbo; + +public class VBOFactory { + + private static VBOFactory instance; + private static VBOCreationStrategy strategy; + + private VBOFactory() {} + + public static VBOFactory getInstance() { + if (instance == null) { + instance = new VBOFactory(); + } + return instance; + } + + public void setVBOCreationStrategy(VBOCreationStrategy strategy) { + VBOFactory.strategy = strategy; + } + + public VBO create() { + if (strategy == null) { + System.err.println("No VBOCreationStrategy set!"); + return null; + } + return strategy.create(); + } +} diff --git a/src/main/java/workspace/GraphicsPImpl.java b/src/main/java/workspace/GraphicsPImpl.java index c0c923f3..30698d59 100644 --- a/src/main/java/workspace/GraphicsPImpl.java +++ b/src/main/java/workspace/GraphicsPImpl.java @@ -5,6 +5,7 @@ import engine.processing.LightGizmoRenderer; import engine.processing.LightRendererImpl; import engine.processing.ProcessingTexture; +import engine.processing.VBOProcessing; import engine.render.Material; import engine.resources.FilterMode; import engine.resources.Image; @@ -13,6 +14,7 @@ import engine.scene.camera.Camera; import engine.scene.light.Light; import engine.scene.light.LightRenderer; +import engine.vbo.VBO; import math.Matrix4f; import math.Vector2f; import math.Vector3f; @@ -104,6 +106,15 @@ public void drawFaces(Mesh3D mesh) { drawMeshFaces(mesh); } + @Override + public void draw(VBO vbo) { + faceCount += vbo.getFaceCount(); + vertexCount += vbo.getVertexCount(); + applyTexture(); + VBOProcessing vboProcessing = (VBOProcessing) vbo; + vboProcessing.draw(g); + } + @Override public void renderInstances(Mesh3D mesh, List instanceTransforms) { if (mesh.getFaces().isEmpty() || mesh.getVertices().isEmpty()) {