11/*
2- * Copyright (c) 2009-2012 jMonkeyEngine
2+ * Copyright (c) 2009-2025 jMonkeyEngine
33 * All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
3232package com .jme3 .scene .debug ;
3333
3434import com .jme3 .math .Vector3f ;
35+ import com .jme3 .renderer .Camera ;
36+ import com .jme3 .scene .Geometry ;
3537import com .jme3 .scene .Mesh ;
3638import com .jme3 .scene .VertexBuffer ;
3739import com .jme3 .scene .VertexBuffer .Type ;
3840import com .jme3 .scene .VertexBuffer .Usage ;
41+ import com .jme3 .shadow .ShadowUtil ;
3942import com .jme3 .util .BufferUtils ;
4043import java .nio .FloatBuffer ;
4144
45+ /**
46+ * A specialized Mesh that renders a camera frustum as a wireframe.
47+ * This class extends jME3's Mesh and is designed to visually represent
48+ * the viewing volume of a camera, which can be useful for debugging
49+ * or visualization purposes.
50+ * <p>
51+ * The frustum is defined by eight points: four for the near plane
52+ * and four for the far plane. These points are connected by lines
53+ * to form a wireframe cube-like structure.
54+ */
4255public class WireFrustum extends Mesh {
4356
4457 /**
45- * This constructor is for serialization only. Do not use.
58+ * For Serialization only. Do not use.
4659 */
4760 protected WireFrustum () {
4861 }
4962
50- public WireFrustum (Vector3f [] points ){
51- initGeom (this , points );
52- }
53-
54- public static Mesh makeFrustum (Vector3f [] points ){
55- Mesh m = new Mesh ();
56- initGeom (m , points );
57- return m ;
63+ /**
64+ * Constructs a new `WireFrustum` mesh using the specified frustum corner points.
65+ * The points should represent the 8 corners of the frustum.
66+ * The expected order of points is typically:
67+ * 0-3: Near plane (e.g., bottom-left, bottom-right, top-right, top-left)
68+ * 4-7: Far plane (e.g., bottom-left, bottom-right, top-right, top-left)
69+ *
70+ * @param points An array of 8 `Vector3f` objects representing the frustum's corners.
71+ * If the array is null or does not contain 8 points, an
72+ * `IllegalArgumentException` will be thrown.
73+ */
74+ public WireFrustum (Vector3f [] points ) {
75+ if (points == null || points .length != 8 ) {
76+ throw new IllegalArgumentException ("Frustum points array must not be null and must contain 8 points." );
77+ }
78+ setGeometryData (this , points );
5879 }
5980
60- private static void initGeom (Mesh m , Vector3f [] points ) {
61- if (points != null )
62- m .setBuffer (Type .Position , 3 , BufferUtils .createFloatBuffer (points ));
81+ /**
82+ * Initializes the mesh's geometric data, setting up the vertex positions and indices.
83+ * This method is called during the construction of the `WireFrustum`.
84+ *
85+ * @param points The 8 `Vector3f` points defining the frustum's corners.
86+ */
87+ private void setGeometryData (Mesh m , Vector3f [] points ) {
88+ // Set vertex positions
89+ m .setBuffer (Type .Position , 3 , BufferUtils .createFloatBuffer (points ));
6390
91+ // Set indices to draw lines connecting the frustum corners
92+ // The indices define 12 lines: 4 for near plane, 4 for far plane, and 4 connecting near to far.
6493 m .setBuffer (Type .Index , 2 ,
6594 new short []{
95+ // Near plane
6696 0 , 1 ,
6797 1 , 2 ,
6898 2 , 3 ,
6999 3 , 0 ,
70100
101+ // Far plane
71102 4 , 5 ,
72103 5 , 6 ,
73104 6 , 7 ,
74105 7 , 4 ,
75106
107+ // Connecting lines (near to far)
76108 0 , 4 ,
77109 1 , 5 ,
78110 2 , 6 ,
@@ -83,23 +115,76 @@ private static void initGeom(Mesh m, Vector3f[] points) {
83115 m .setMode (Mode .Lines );
84116 }
85117
86- public void update (Vector3f [] points ){
118+ /**
119+ * Updates the vertex positions of the existing `WireFrustum` mesh.
120+ * This is more efficient than creating a new `WireFrustum` instance
121+ * if only the frustum's position or orientation changes.
122+ *
123+ * @param points An array of 8 `Vector3f` objects representing the new frustum's corners.
124+ * If the array is null or does not contain 8 points, an
125+ * `IllegalArgumentException` will be thrown.
126+ */
127+ public void update (Vector3f [] points ) {
128+ if (points == null || points .length != 8 ) {
129+ throw new IllegalArgumentException ("Frustum points array must not be null and must contain 8 points." );
130+ }
131+
87132 VertexBuffer vb = getBuffer (Type .Position );
88- if (vb == null ){
133+ if (vb == null ) {
134+ // If for some reason the position buffer is missing, re-create it.
135+ // This case should ideally not happen if the object is constructed properly.
89136 setBuffer (Type .Position , 3 , BufferUtils .createFloatBuffer (points ));
90137 return ;
91138 }
92139
93- FloatBuffer b = BufferUtils .createFloatBuffer (points );
94- FloatBuffer a = (FloatBuffer ) vb .getData ();
95- b .rewind ();
96- a .rewind ();
97- a .put (b );
98- a .rewind ();
140+ // Create a new FloatBuffer from the updated points
141+ FloatBuffer newBuff = BufferUtils .createFloatBuffer (points );
142+ // Get the existing FloatBuffer from the VertexBuffer
143+ FloatBuffer currBuff = (FloatBuffer ) vb .getData ();
144+
145+ currBuff .clear (); // Clear
146+ currBuff .put (newBuff ); // Copy
147+ currBuff .rewind (); // Rewind
99148
100- vb .updateData (a );
101-
149+ // Update the VertexBuffer with the modified FloatBuffer data
150+ vb .updateData (currBuff );
151+
152+ // Update the mesh's bounding volume to reflect the new vertex positions
102153 updateBound ();
103154 }
104155
156+ /**
157+ * A static factory method to create a new `WireFrustum` mesh.
158+ * This method provides a cleaner way to instantiate a `WireFrustum`.
159+ *
160+ * @param points An array of 8 `Vector3f` objects representing the frustum's corners.
161+ * @return A new `WireFrustum` instance.
162+ */
163+ public static Mesh makeFrustum (Vector3f [] points ) {
164+ return new WireFrustum (points );
165+ }
166+
167+ /**
168+ * Creates a `Geometry` object representing the wireframe frustum of a given camera.
169+ * The frustum points are calculated based on the camera's current view settings.
170+ * The returned `Geometry` can be directly attached to a scene graph.
171+ *
172+ * @param camera The `Camera` whose frustum is to be visualized.
173+ * @return A `Geometry` object containing the `WireFrustum` mesh.
174+ */
175+ public static Geometry makeGeometry (Camera camera ) {
176+ Vector3f [] frustumCorners = new Vector3f [8 ];
177+ for (int i = 0 ; i < 8 ; i ++) {
178+ frustumCorners [i ] = new Vector3f ();
179+ }
180+
181+ Camera tempCam = camera .clone ();
182+ tempCam .setLocation (new Vector3f (0 , 0 , 0 ));
183+ tempCam .lookAt (Vector3f .UNIT_Z , Vector3f .UNIT_Y );
184+ ShadowUtil .updateFrustumPoints2 (tempCam , frustumCorners );
185+
186+ WireFrustum mesh = new WireFrustum (frustumCorners );
187+ return new Geometry ("Viewing Frustum" , mesh );
188+ }
189+
105190}
0 commit comments