added contents
This commit is contained in:
229
Projekte/jme-common/src/main/java/pp/graphics/Draw.java
Normal file
229
Projekte/jme-common/src/main/java/pp/graphics/Draw.java
Normal file
@@ -0,0 +1,229 @@
|
||||
////////////////////////////////////////
|
||||
// Programming project code
|
||||
// UniBw M, 2022, 2023, 2024
|
||||
// www.unibw.de/inf2
|
||||
// (c) Mark Minas (mark.minas@unibw.de)
|
||||
////////////////////////////////////////
|
||||
|
||||
package pp.graphics;
|
||||
|
||||
import com.jme3.asset.AssetManager;
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.material.RenderState;
|
||||
import com.jme3.material.RenderState.BlendMode;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.VertexBuffer;
|
||||
import com.jme3.scene.shape.Quad;
|
||||
import pp.util.Position;
|
||||
import pp.util.SegmentLike;
|
||||
|
||||
import java.lang.System.Logger;
|
||||
import java.lang.System.Logger.Level;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static pp.util.FloatMath.FLT_EPSILON;
|
||||
import static pp.util.FloatMath.TWO_PI;
|
||||
import static pp.util.FloatMath.cos;
|
||||
import static pp.util.FloatMath.sin;
|
||||
import static pp.util.FloatMath.sqr;
|
||||
import static pp.util.FloatMath.sqrt;
|
||||
|
||||
/**
|
||||
* Class for creating graphical primitives.
|
||||
*/
|
||||
public class Draw {
|
||||
private static final Logger LOGGER = System.getLogger(Draw.class.getName());
|
||||
private static final int NUM = 10;
|
||||
private static final String UNSHADED = "Common/MatDefs/Misc/Unshaded.j3md"; //NON-NLS
|
||||
private static final String COLOR = "Color"; //NON-NLS
|
||||
private final AssetManager am;
|
||||
private final Map<ColorRGBA, Geometry> lineMap = new HashMap<>();
|
||||
private final Map<ColorRGBA, Geometry> rectangleMap = new HashMap<>();
|
||||
private final Map<ColorRGBA, Geometry> circleMap = new HashMap<>();
|
||||
private Mesh lineMesh;
|
||||
private Mesh circleMesh;
|
||||
|
||||
/**
|
||||
* Creates an in stance of the Draw class with the specified
|
||||
* asset manager.
|
||||
*
|
||||
* @param assetManager the specified asset manager
|
||||
*/
|
||||
public Draw(AssetManager assetManager) {
|
||||
am = assetManager;
|
||||
}
|
||||
|
||||
private Geometry makeLine(ColorRGBA color) {
|
||||
LOGGER.log(Level.DEBUG, "create line with color {0}", color); //NON-NLS
|
||||
if (lineMesh == null) {
|
||||
lineMesh = new Mesh();
|
||||
lineMesh.setMode(Mesh.Mode.Lines);
|
||||
lineMesh.setBuffer(VertexBuffer.Type.Position, 3, new float[]{0, 0, 0, 0, 1, 0});
|
||||
lineMesh.setBuffer(VertexBuffer.Type.Index, 2, new short[]{0, 1});
|
||||
}
|
||||
final Geometry lineGeom = new Geometry("lineMesh", lineMesh.clone());
|
||||
Material matWireframe = new Material(am, UNSHADED); //NON-NLS
|
||||
matWireframe.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
|
||||
matWireframe.setColor(COLOR, color); //NON-NLS
|
||||
lineGeom.setMaterial(matWireframe);
|
||||
|
||||
return lineGeom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a line for the specified segment.
|
||||
*
|
||||
* @param segment the segment with its start and end point
|
||||
* @param z depth information
|
||||
* @param color line color
|
||||
*/
|
||||
public Geometry makeLine(SegmentLike segment, float z, ColorRGBA color) {
|
||||
return makeLine(segment.from(), segment.to(), z, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a straight line between the specified points with the specified color.
|
||||
*
|
||||
* @param p1 start point
|
||||
* @param p2 end point
|
||||
* @param z depth information
|
||||
* @param color line color
|
||||
*/
|
||||
public Geometry makeLine(Position p1, Position p2, float z, ColorRGBA color) {
|
||||
return makeLine(p1.getX(), p1.getY(), p2.getX(), p2.getY(), z, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a straight line between the specified points with the specified color.
|
||||
*
|
||||
* @param x1 x-coordinate of the start point
|
||||
* @param y1 y-coordinate of the start point
|
||||
* @param x2 x-coordinate of the end point
|
||||
* @param y2 y-coordinate of the end point
|
||||
* @param z depth information
|
||||
* @param color line color
|
||||
*/
|
||||
public Geometry makeLine(float x1, float y1, float x2, float y2, float z, ColorRGBA color) {
|
||||
final Geometry line = lineMap.computeIfAbsent(color, this::makeLine).clone();
|
||||
line.lookAt(Vector3f.UNIT_Z, new Vector3f(x2 - x1, y2 - y1, 0));
|
||||
line.setLocalScale(sqrt(sqr(x2 - x1) + sqr(y2 - y1)));
|
||||
line.setLocalTranslation(x1, y1, z);
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a straight line between the specified points with the specified width and color.
|
||||
*
|
||||
* @param p1 start point
|
||||
* @param p2 end point
|
||||
* @param z depth information
|
||||
* @param color line color
|
||||
* @param width width of the line
|
||||
*/
|
||||
public Geometry makeFatLine(Position p1, Position p2, float z, ColorRGBA color, float width) {
|
||||
return makeFatLine(p1.getX(), p1.getY(), p2.getX(), p2.getY(), z, color, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a straight line between the specified points with the specified width and color.
|
||||
*
|
||||
* @param x1 x-coordinate of the start point
|
||||
* @param y1 y-coordinate of the start point
|
||||
* @param x2 x-coordinate of the end point
|
||||
* @param y2 y-coordinate of the end point
|
||||
* @param z depth information
|
||||
* @param color line color
|
||||
* @param width width of the line
|
||||
*/
|
||||
public Geometry makeFatLine(float x1, float y1, float x2, float y2, float z, ColorRGBA color, float width) {
|
||||
final Geometry line = rectangleMap.computeIfAbsent(color, this::makeRectangle).clone();
|
||||
final float dx = x2 - x1;
|
||||
final float dy = y2 - y1;
|
||||
final float len = sqrt(dx * dx + dy * dy);
|
||||
line.setLocalScale(width, len + width, 1f);
|
||||
if (len <= FLT_EPSILON)
|
||||
line.setLocalTranslation(x1 - 0.5f * width, y1 - 0.5f * width, z);
|
||||
else {
|
||||
final float f = 0.5f * width / len;
|
||||
line.setLocalTranslation(x1 - f * (dy + dx), y1 - f * (dy - dx), z);
|
||||
line.getLocalRotation().lookAt(Vector3f.UNIT_Z, new Vector3f(dx, dy, 0f));
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
private Geometry makeRectangle(ColorRGBA color) {
|
||||
final Mesh quad = new Quad(1f, 1f);
|
||||
final Geometry rectangle = new Geometry("quad", quad); //NON-NLS
|
||||
Material mat = new Material(am, UNSHADED); //NON-NLS
|
||||
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
|
||||
mat.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
|
||||
mat.setColor(COLOR, color); //NON-NLS
|
||||
rectangle.setMaterial(mat);
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an axis-parallel rectangle with the specified color.
|
||||
*
|
||||
* @param x x-coordinate of the bottom-left corner
|
||||
* @param y y-coordinate of the bottom-left corner
|
||||
* @param w width of the rectangle
|
||||
* @param h height of the rectangle
|
||||
* @param z depth information
|
||||
* @param color line color
|
||||
*/
|
||||
public Geometry makeRectangle(float x, float y, float z, float w, float h, ColorRGBA color) {
|
||||
final Geometry rectangle = rectangleMap.computeIfAbsent(color, this::makeRectangle).clone();
|
||||
rectangle.setLocalScale(w, h, 1f);
|
||||
rectangle.setLocalTranslation(x, y, z);
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
private Geometry makeCircle(ColorRGBA color) {
|
||||
if (circleMesh == null) {
|
||||
circleMesh = new Mesh();
|
||||
circleMesh.setMode(Mesh.Mode.LineLoop);
|
||||
final float[] pointBuffer = new float[3 * NUM];
|
||||
final short[] indexBuffer = new short[NUM];
|
||||
int j = 0;
|
||||
for (short i = 0; i < NUM; i++) {
|
||||
final float a = TWO_PI / NUM * i;
|
||||
pointBuffer[j++] = 0.5f * cos(a);
|
||||
pointBuffer[j++] = 0.5f * sin(a);
|
||||
pointBuffer[j++] = 0f;
|
||||
indexBuffer[i] = i;
|
||||
}
|
||||
circleMesh.setBuffer(VertexBuffer.Type.Position, 3, pointBuffer);
|
||||
circleMesh.setBuffer(VertexBuffer.Type.Index, 2, indexBuffer);
|
||||
}
|
||||
|
||||
final Geometry circle = new Geometry("circleMesh", circleMesh.clone());
|
||||
Material matWireframe = new Material(am, UNSHADED); //NON-NLS
|
||||
matWireframe.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
|
||||
matWireframe.setColor(COLOR, color); //NON-NLS
|
||||
circle.setMaterial(matWireframe);
|
||||
|
||||
return circle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ellipse with the specified color.
|
||||
*
|
||||
* @param x x-coordinate of the center point
|
||||
* @param y y-coordinate of the center point
|
||||
* @param w width of the ellipse
|
||||
* @param h height of the ellipse
|
||||
* @param z depth information
|
||||
* @param color line color
|
||||
*/
|
||||
public Geometry makeEllipse(float x, float y, float z, float w, float h, ColorRGBA color) {
|
||||
final Geometry ellipse = circleMap.computeIfAbsent(color, this::makeCircle).clone();
|
||||
ellipse.setLocalScale(w, h, 1f);
|
||||
ellipse.setLocalTranslation(x, y, z);
|
||||
return ellipse;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user