Skip to content

Commit 1b24fc9

Browse files
committed
Add bounding box to Geometry class for culling, spatial partitioning,
and debugging - Implemented a bounding box calculation for the Geometry class, utilizing MeshBoundsCalculator. - Bounding box is now accessible for culling and spatial partitioning optimizations. - Updated debug rendering to visualize the bounding box in red for easier debugging of mesh extents. - Added documentation explaining the broader use of the bounding box beyond debugging (e.g., for frustum culling).
1 parent a8d746b commit 1b24fc9

File tree

1 file changed

+111
-61
lines changed

1 file changed

+111
-61
lines changed
Lines changed: 111 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,75 @@
11
package engine.components;
22

33
import engine.render.Material;
4+
import math.Bounds;
5+
import math.Color;
46
import mesh.Mesh3D;
7+
import mesh.util.MeshBoundsCalculator;
58
import workspace.ui.Graphics;
69

710
/**
8-
* Represents a renderable geometry component within the scene graph.
9-
* <p>
10-
* The Geometry class is a component that encapsulates a 3D mesh and its
11-
* associated material. It implements rendering behavior through the
12-
* {@link RenderableComponent} interface, allowing it to be drawn during the
13-
* rendering pass of the scene graph traversal.
14-
* </p>
15-
* <p>
16-
* This class is responsible for applying the provided {@link Material} during
17-
* rendering, ensuring proper visualization of the associated {@link Mesh3D}.
18-
* </p>
11+
* The {@code Geometry} class represents a 3D object in a scene with a mesh and
12+
* material applied to it. It is responsible for rendering the mesh and applying
13+
* the appropriate material to it. The class also provides access to the mesh's
14+
* bounding box, which is useful for purposes like culling, spatial
15+
* partitioning, and debugging.
1916
*
20-
* <h3>Key Features</h3>
21-
* <ul>
22-
* <li>Supports a default white material if no custom material is provided.</li>
23-
* <li>Handles cleanup by releasing references to the mesh and material.</li>
24-
* <li>Integrates with the graphics context to issue rendering commands via the
25-
* {@link Graphics} class.</li>
26-
* </ul>
17+
* This class implements the {@link RenderableComponent} interface, indicating
18+
* that it has a render method to be invoked during the render loop of the
19+
* engine.
20+
*
21+
* @see RenderableComponent
22+
* @see Material
23+
* @see Mesh3D
24+
* @see Bounds
2725
*/
2826
public class Geometry extends AbstractComponent implements RenderableComponent {
2927

30-
/** The 3D mesh to be rendered by this component. */
28+
/** The mesh representing the geometry of the object. */
3129
private Mesh3D mesh;
3230

33-
/** The material associated with this geometry for rendering purposes. */
31+
/** The material applied to the mesh for rendering. */
3432
private Material material;
3533

3634
/**
37-
* Constructs a Geometry component with a provided mesh and the default white
35+
* The bounding box of the mesh used for culling, spatial partitioning, and
36+
* debugging.
37+
*/
38+
private Bounds bounds;
39+
40+
/**
41+
* Constructs a {@code Geometry} with the specified mesh and a default
3842
* material.
39-
*
40-
* @param mesh The mesh to associate with this geometry.
43+
*
44+
* @param mesh The {@link Mesh3D} object representing the geometry of the
45+
* object.
46+
* @throws IllegalArgumentException If the mesh is {@code null}.
4147
*/
4248
public Geometry(Mesh3D mesh) {
4349
this(mesh, Material.DEFAULT_WHITE);
4450
}
4551

4652
/**
47-
* Constructs a Geometry component with a specific mesh and material.
48-
*
49-
* @param mesh The 3D mesh to associate with this geometry. Must not be
50-
* null.
51-
* @param material The material to use for rendering. Must not be null.
52-
* @throws IllegalArgumentException if either mesh or material is null.
53+
* Constructs a {@code Geometry} with the specified mesh and material.
54+
*
55+
* @param mesh The {@link Mesh3D} object representing the geometry of the
56+
* object.
57+
* @param material The {@link Material} to be applied to the mesh.
58+
* @throws IllegalArgumentException If the mesh or material is {@code null}.
5359
*/
5460
public Geometry(Mesh3D mesh, Material material) {
5561
validate(mesh, material);
5662
this.mesh = mesh;
5763
this.material = material;
64+
this.bounds = MeshBoundsCalculator.calculateBounds(mesh);
5865
}
5966

6067
/**
61-
* Validates the provided mesh and material to ensure they are non-null.
62-
*
63-
* @param mesh The 3D mesh to validate.
64-
* @param material The material to validate.
65-
* @throws IllegalArgumentException if either mesh or material is null.
68+
* Validates the mesh and material to ensure they are not {@code null}.
69+
*
70+
* @param mesh The {@link Mesh3D} object to validate.
71+
* @param material The {@link Material} to validate.
72+
* @throws IllegalArgumentException If the mesh or material is {@code null}.
6673
*/
6774
private void validate(Mesh3D mesh, Material material) {
6875
if (mesh == null) {
@@ -74,53 +81,96 @@ private void validate(Mesh3D mesh, Material material) {
7481
}
7582

7683
/**
77-
* Cleans up resources associated with this component by nullifying references
78-
* to the mesh and material. This is called when the component is no longer
79-
* needed or during application shutdown.
84+
* Renders the geometry by applying the material and drawing the mesh using
85+
* the specified graphics context.
86+
*
87+
* @param g The {@link Graphics} context used for rendering.
8088
*/
8189
@Override
82-
public void cleanup() {
83-
mesh = null;
84-
material = null;
90+
public void render(Graphics g) {
91+
material.apply(g);
92+
g.fillFaces(mesh);
93+
material.release(g);
94+
debugRenderBounds(g);
8595
}
8696

8797
/**
88-
* Handles rendering of the mesh with its material using the provided graphics
89-
* context.
98+
* Debugs the rendering by drawing the bounding box of the mesh using the
99+
* specified graphics context. The bounding box is rendered in red to help
100+
* visualize the mesh's extents. This method can be used for debugging
101+
* purposes to ensure the mesh is properly positioned and scaled in the scene.
90102
*
91103
* <p>
92-
* This method applies the material, renders the associated mesh's faces using
93-
* the {@link Graphics} instance, and then releases the material's state
94-
* afterward.
104+
* Beyond debugging, the bounding box is useful for spatial partitioning
105+
* techniques like frustum culling, as well as for determining the overall
106+
* size and position of the mesh in the 3D world.
95107
* </p>
96-
*
97-
* @param g The graphics context to use for rendering the geometry.
108+
*
109+
* @param g The {@link Graphics} context used for rendering the debug bounding
110+
* box.
111+
*/
112+
public void debugRenderBounds(Graphics g) {
113+
if (bounds == null) {
114+
return;
115+
}
116+
117+
g.setColor(Color.RED);
118+
119+
// Extract corner points for readability
120+
float minX = bounds.getMin().x;
121+
float minY = bounds.getMin().y;
122+
float minZ = bounds.getMin().z;
123+
float maxX = bounds.getMax().x;
124+
float maxY = bounds.getMax().y;
125+
float maxZ = bounds.getMax().z;
126+
127+
// Draw lines for each edge of the bounding box
128+
g.drawLine(minX, minY, minZ, maxX, minY, minZ);
129+
g.drawLine(minX, minY, minZ, minX, maxY, minZ);
130+
g.drawLine(minX, minY, minZ, minX, minY, maxZ);
131+
132+
g.drawLine(maxX, maxY, maxZ, minX, maxY, maxZ);
133+
g.drawLine(maxX, maxY, maxZ, maxX, minY, maxZ);
134+
g.drawLine(maxX, maxY, maxZ, maxX, maxY, minZ);
135+
136+
g.drawLine(minX, maxY, minZ, maxX, maxY, minZ);
137+
g.drawLine(maxX, minY, minZ, maxX, maxY, minZ);
138+
g.drawLine(maxX, minY, minZ, maxX, minY, maxZ);
139+
140+
g.drawLine(minX, maxY, maxZ, minX, minY, maxZ);
141+
g.drawLine(maxX, minY, maxZ, minX, minY, maxZ);
142+
g.drawLine(minX, maxY, maxZ, minX, maxY, minZ);
143+
}
144+
145+
/**
146+
* Updates the state of the geometry. This method is a placeholder for
147+
* potential updates to the mesh state over time.
148+
*
149+
* @param tpf The time per frame used for the update (in seconds).
98150
*/
99151
@Override
100-
public void render(Graphics g) {
101-
material.apply(g);
102-
g.fillFaces(mesh);
103-
material.release(g);
152+
public void update(float tpf) {
153+
// Placeholder for potential mesh state updates
104154
}
105155

106156
/**
107-
* Placeholder for initialization logic if needed in future development.
108-
* Currently, no specific initialization is necessary.
157+
* Called when the component is attached to a parent object in the scene. This
158+
* method is a hook for additional initialization or setup when the component
159+
* is added.
109160
*/
110161
@Override
111-
public void initialize() {
112-
// Initialization logic, if needed
162+
public void onAttach() {
163+
// Hook for additional setup on attachment
113164
}
114165

115166
/**
116-
* Updates geometry's state over time, if necessary. Currently, this is a
117-
* placeholder for potential future logic.
118-
*
119-
* @param tpf Time per frame, used to synchronize updates across frames.
167+
* Called when the component is detached from its parent object in the scene.
168+
* This method is a hook for cleanup or other actions when the component is
169+
* removed.
120170
*/
121171
@Override
122-
public void update(float tpf) {
123-
// Placeholder for potential mesh state updates
172+
public void onDetach() {
173+
// Hook for cleanup on detachment
124174
}
125175

126176
}

0 commit comments

Comments
 (0)