fa67cfce14049b921d1ca40257970127000a0b95
[sixth-3d.git] /
1 /*
2  * Sixth 3D engine. Author: Svjatoslav Agejenko.
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid;
6
7 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
8 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
9 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon.SolidPolygon;
10 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
11
12 /**
13  * A solid (filled) rectangular box composed of 12 triangular polygons (2 per face,
14  * covering all 6 faces).
15  *
16  * <p>The box is defined by two diagonally opposite corner points in 3D space.
17  * The box is axis-aligned, meaning its edges are parallel to the X, Y, and Z axes.</p>
18  *
19  * <p><b>Vertex layout:</b></p>
20  * <pre>
21  *         cornerB (max) ────────┐
22  *              /│              /│
23  *             / │             / │
24  *            /  │            /  │
25  *           ┌───┼───────────┐   │
26  *           │   │           │   │
27  *           │   │           │   │
28  *           │   └───────────│───┘
29  *           │  /            │  /
30  *           │ /             │ /
31  *           │/              │/
32  *           └───────────────┘ cornerA (min)
33  * </pre>
34  *
35  * <p>The eight vertices are derived from the two corner points:</p>
36  * <ul>
37  *   <li>Corner A defines minimum X, Y, Z</li>
38  *   <li>Corner B defines maximum X, Y, Z</li>
39  *   <li>The other 6 vertices are computed from combinations of these coordinates</li>
40  * </ul>
41  *
42  * <p><b>Usage examples:</b></p>
43  * <pre>{@code
44  * // Create a box from two opposite corners
45  * SolidPolygonRectangularBox box = new SolidPolygonRectangularBox(
46  *     new Point3D(-50, -25, 100),  // cornerA (minimum X, Y, Z)
47  *     new Point3D(50, 25, 200),    // cornerB (maximum X, Y, Z)
48  *     Color.BLUE
49  * );
50  *
51  * // Create a cube using center + size (see SolidPolygonCube for convenience)
52  * double size = 50;
53  * SolidPolygonRectangularBox cube = new SolidPolygonRectangularBox(
54  *     new Point3D(0 - size, 0 - size, 200 - size),  // cornerA
55  *     new Point3D(0 + size, 0 + size, 200 + size),  // cornerB
56  *     Color.RED
57  * );
58  * }</pre>
59  *
60  * @see SolidPolygonCube
61  * @see SolidPolygon
62  */
63 public class SolidPolygonRectangularBox extends AbstractCompositeShape {
64
65     /**
66      * Constructs a solid rectangular box between two diagonally opposite corner
67      * points in 3D space.
68      *
69      * <p>The box is axis-aligned and fills the rectangular region between the
70      * two corners. The corner points do not need to be ordered (cornerA can have
71      * larger coordinates than cornerB); the constructor will determine the actual
72      * min/max bounds automatically.</p>
73      *
74      * @param cornerA the first corner point (any of the 8 corners)
75      * @param cornerB the diagonally opposite corner point
76      * @param color   the fill color applied to all 12 triangular polygons
77      */
78     public SolidPolygonRectangularBox(final Point3D cornerA, final Point3D cornerB, final Color color) {
79         super();
80
81         // Determine actual min/max bounds (corners may be in any order)
82         final double minX = Math.min(cornerA.x, cornerB.x);
83         final double maxX = Math.max(cornerA.x, cornerB.x);
84         final double minY = Math.min(cornerA.y, cornerB.y);
85         final double maxY = Math.max(cornerA.y, cornerB.y);
86         final double minZ = Math.min(cornerA.z, cornerB.z);
87         final double maxZ = Math.max(cornerA.z, cornerB.z);
88
89         // Compute all 8 vertices from the bounds
90         // Naming convention: min/max indicates which bound the coordinate uses
91         // minMinMin = (minX, minY, minZ), maxMaxMax = (maxX, maxY, maxZ), etc.
92         final Point3D minMinMin = new Point3D(minX, minY, minZ);
93         final Point3D maxMinMin = new Point3D(maxX, minY, minZ);
94         final Point3D maxMinMax = new Point3D(maxX, minY, maxZ);
95         final Point3D minMinMax = new Point3D(minX, minY, maxZ);
96
97         final Point3D minMaxMin = new Point3D(minX, maxY, minZ);
98         final Point3D maxMaxMin = new Point3D(maxX, maxY, minZ);
99         final Point3D minMaxMax = new Point3D(minX, maxY, maxZ);
100         final Point3D maxMaxMax = new Point3D(maxX, maxY, maxZ);
101
102         // Bottom face (y = minY)
103         addShape(new SolidPolygon(minMinMin, maxMinMin, maxMinMax, color));
104         addShape(new SolidPolygon(minMinMin, maxMinMax, minMinMax, color));
105
106         // Top face (y = maxY)
107         addShape(new SolidPolygon(minMaxMin, minMaxMax, maxMaxMax, color));
108         addShape(new SolidPolygon(minMaxMin, maxMaxMax, maxMaxMin, color));
109
110         // Front face (z = minZ)
111         addShape(new SolidPolygon(minMinMin, minMaxMin, maxMaxMin, color));
112         addShape(new SolidPolygon(minMinMin, maxMaxMin, maxMinMin, color));
113
114         // Back face (z = maxZ)
115         addShape(new SolidPolygon(maxMinMax, maxMaxMax, minMaxMax, color));
116         addShape(new SolidPolygon(maxMinMax, minMaxMax, minMinMax, color));
117
118         // Left face (x = minX)
119         addShape(new SolidPolygon(minMinMin, minMinMax, minMaxMax, color));
120         addShape(new SolidPolygon(minMinMin, minMaxMax, minMaxMin, color));
121
122         // Right face (x = maxX)
123         addShape(new SolidPolygon(maxMinMin, maxMaxMin, maxMaxMax, color));
124         addShape(new SolidPolygon(maxMinMin, maxMaxMax, maxMinMax, color));
125
126         setBackfaceCulling(true);
127     }
128 }