Skip to content

Commit 2942830

Browse files
authored
added Circle class
1 parent ad1419c commit 2942830

File tree

1 file changed

+181
-0
lines changed
  • jme3-core/src/main/java/com/jme3/environment/util

1 file changed

+181
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
* Copyright (c) 2009-2025 jMonkeyEngine
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
package com.jme3.environment.util;
33+
34+
import com.jme3.asset.AssetManager;
35+
import com.jme3.material.Material;
36+
import com.jme3.material.RenderState;
37+
import com.jme3.math.ColorRGBA;
38+
import com.jme3.math.FastMath;
39+
import com.jme3.renderer.queue.RenderQueue;
40+
import com.jme3.scene.Geometry;
41+
import com.jme3.scene.Mesh;
42+
import com.jme3.scene.VertexBuffer.Type;
43+
import com.jme3.util.BufferUtils;
44+
45+
import java.nio.FloatBuffer;
46+
import java.nio.ShortBuffer;
47+
48+
/**
49+
* <p>A `Circle` is a 2D mesh representing a circular outline (wireframe).
50+
* It's defined by a specified number of radial samples, which determine its smoothness.</p>
51+
*
52+
* <p>The circle is centered at (0,0,0) in its local coordinate space and has a radius of 1.0.</p>
53+
*/
54+
public class Circle extends Mesh {
55+
56+
// The number of segments used to approximate the circle.
57+
protected int radialSamples = 256;
58+
59+
/**
60+
* Creates a new `Circle` mesh.
61+
*/
62+
public Circle() {
63+
setGeometryData();
64+
setIndexData();
65+
}
66+
67+
/**
68+
* Creates a new `Circle` mesh with the specified number of radial samples.
69+
* The circle will be centered at (0,0,0) with a radius of 1.0.
70+
*
71+
* @param radialSamples The number of segments (vertices) to use for the circle's perimeter.
72+
* @throws IllegalArgumentException if `radialSamples` is less than 2.
73+
*/
74+
public Circle(int radialSamples) {
75+
if (radialSamples < 2) {
76+
throw new IllegalArgumentException("radialSamples must be at least 2 for a valid circle.");
77+
}
78+
this.radialSamples = radialSamples;
79+
setGeometryData();
80+
setIndexData();
81+
}
82+
83+
/**
84+
* builds the vertices based on the radius.
85+
*/
86+
private void setGeometryData() {
87+
setMode(Mode.Lines);
88+
89+
FloatBuffer posBuf = BufferUtils.createVector3Buffer((radialSamples + 1));
90+
FloatBuffer colBuf = BufferUtils.createFloatBuffer((radialSamples + 1) * 4);
91+
FloatBuffer texBuf = BufferUtils.createVector2Buffer(radialSamples + 1);
92+
93+
setBuffer(Type.Position, 3, posBuf);
94+
setBuffer(Type.Color, 4, colBuf);
95+
setBuffer(Type.TexCoord, 2, texBuf);
96+
97+
// generate geometry
98+
float fInvRS = 1.0f / radialSamples;
99+
100+
// Generate points on the unit circle to be used in computing the mesh
101+
// points on a sphere slice.
102+
float[] sin = new float[(radialSamples + 1)];
103+
float[] cos = new float[(radialSamples + 1)];
104+
for (int i = 0; i < radialSamples; i++) {
105+
float angle = FastMath.TWO_PI * fInvRS * i;
106+
cos[i] = FastMath.cos(angle);
107+
sin[i] = FastMath.sin(angle);
108+
}
109+
sin[radialSamples] = sin[0];
110+
cos[radialSamples] = cos[0];
111+
112+
ColorRGBA color = ColorRGBA.Orange;
113+
for (int iR = 0; iR <= radialSamples; iR++) {
114+
posBuf.put(cos[iR]).put(sin[iR]).put(0);
115+
colBuf.put(color.r).put(color.g).put(color.b).put(color.a);
116+
texBuf.put(iR % 2f).put(iR % 2f);
117+
}
118+
119+
updateBound();
120+
setStatic();
121+
}
122+
123+
/**
124+
* sets the indices for rendering the circle.
125+
*/
126+
private void setIndexData() {
127+
// allocate connectivity
128+
int nbSegments = (radialSamples);
129+
130+
ShortBuffer idxBuf = BufferUtils.createShortBuffer(2 * nbSegments);
131+
setBuffer(Type.Index, 2, idxBuf);
132+
133+
int idx = 0;
134+
int segDone = 0;
135+
while (segDone < nbSegments) {
136+
idxBuf.put((short) idx);
137+
idxBuf.put((short) (idx + 1));
138+
idx++;
139+
segDone++;
140+
}
141+
}
142+
143+
/**
144+
* Creates a {@link Geometry} object representing a dashed wireframe circle.
145+
*
146+
* @param assetManager The application's AssetManager to load materials.
147+
* @param name The desired name for the Geometry.
148+
* @return A new Geometry instance with a `Circle` mesh.
149+
*/
150+
public static Geometry createShape(AssetManager assetManager, String name) {
151+
return createShape(assetManager, name, 256);
152+
}
153+
154+
/**
155+
* Creates a {@link Geometry} object representing a dashed wireframe circle
156+
* with a specified number of radial samples.
157+
*
158+
* @param assetManager The application's AssetManager to load materials.
159+
* @param name The desired name for the Geometry.
160+
* @param radialSamples The number of segments to use for the circle's perimeter.
161+
* @return A new Geometry instance with a `Circle` mesh.
162+
*/
163+
public static Geometry createShape(AssetManager assetManager, String name, int radialSamples) {
164+
Circle mesh = new Circle(radialSamples);
165+
Geometry geom = new Geometry(name, mesh);
166+
geom.setQueueBucket(RenderQueue.Bucket.Transparent);
167+
168+
Material mat = new Material(assetManager, "Common/MatDefs/Dashed/dashed.j3md");
169+
mat.getAdditionalRenderState().setWireframe(true);
170+
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
171+
mat.getAdditionalRenderState().setDepthWrite(false);
172+
mat.getAdditionalRenderState().setDepthTest(false);
173+
mat.getAdditionalRenderState().setLineWidth(2f);
174+
mat.setColor("Color", ColorRGBA.Orange);
175+
mat.setFloat("DashSize", 0.5f);
176+
geom.setMaterial(mat);
177+
178+
return geom;
179+
}
180+
181+
}

0 commit comments

Comments
 (0)