package de.venjinx.util;
import java.awt.MouseInfo;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.opengl.Display;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.material.Material;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Ray;
import com.jme3.math.Triangle;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Mesh.Mode;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.control.BillboardControl;
import com.jme3.scene.debug.Arrow;
import com.jme3.scene.shape.Line;
import com.jme3.scene.shape.Sphere;
import com.jme3.util.BufferUtils;
public final class Util {
// 3---------------2
// | |
// | |
// | |
// | |
// | |
// | |
// 0---------------1
private static final Vector3f[] faceVertices = new Vector3f[]
{ new Vector3f(0, 0, 0),
new Vector3f(1, 0, 0),
new Vector3f(1, 1, 0),
new Vector3f(0, 1, 0) };
private static final Vector3f[] sqrNormals = new Vector3f[]
{ new Vector3f(-1, -1, 0).normalizeLocal(),
new Vector3f(1, -1, 0).normalizeLocal(),
new Vector3f(-1, 1, 0).normalizeLocal(),
new Vector3f(1, 1, 0).normalizeLocal() };
private static final int[] sqrIndexes = new int[] { 0, 1, 1, 3, 3, 2, 2, 0 };
// 2---------------6
// /| 6 /|
// 9/ | 3/ |
// / | 7 / |
// 3---------------7 |4
// | | 0 | |
// | | | |
// 10 0-----------|---4
// | / 8 1| /
// | /11 | /5
// |/ 2 |/
// 1---------------5
private static final Vector3f[] cubeVertices = new Vector3f[] { new Vector3f(0, 0, 0),
new Vector3f(0, 0, 1),
new Vector3f(0, 1, 0),
new Vector3f(0, 1, 1),
new Vector3f(1, 0, 0),
new Vector3f(1, 0, 1),
new Vector3f(1, 1, 0),
new Vector3f(1, 1, 1) };
private static final Vector3f[] normals = new Vector3f[]
{ new Vector3f(-1, -1, -1).normalizeLocal(),
new Vector3f(-1, -1, 1).normalizeLocal(),
new Vector3f(-1, 1, -1).normalizeLocal(),
new Vector3f(-1, 1, 1).normalizeLocal(),
new Vector3f(1, -1, -1).normalizeLocal(),
new Vector3f(1, -1, 1).normalizeLocal(),
new Vector3f(1, 1, -1).normalizeLocal(),
new Vector3f(1, 1, 1).normalizeLocal() };
private static final int[] indexes = new int[] { 1, 5, 5, 7, 7, 3,
5, 4, 4, 6, 6, 7,
4, 0, 0, 2, 2, 6,
0, 1, 1, 3, 3, 2 };
private static final Vector3f eStdBase = new Vector3f(1, 1, 1);
private static final Matrix3f matrix = new Matrix3f();
private static final Vector3f v3f_0 = new Vector3f();
private static final Vector3f v3f_1 = new Vector3f();
private static final Vector3f v3f_2 = new Vector3f();
private static final Vector2f v2f_0 = new Vector2f();
private static final CollisionResults results = new CollisionResults();
private static final Ray ray = new Ray();
private static final Triangle tri = new Triangle();
private static Logger logger = Logger.getLogger("");
public static final String getTreeString(Node node, int depth) {
String str = new String("");
for (int i = 0; i < depth; i++)
str += "--";
str += node.getName() + " childCount: " + node.getChildren().size() + "\n";
for (Spatial sp : node.getChildren())
if (sp instanceof Node)
str += getTreeString((Node) sp, depth + 1);
else {
for (int i = 0; i < (depth + 1); i++)
str += "--";
str += sp.getName() + "\n";
}
return str;
}
public static final float determinant(Vector3f v0, Vector3f v1) {
matrix.setColumn(0, eStdBase);
matrix.setColumn(1, v0);
matrix.setColumn(2, v1);
return matrix.determinant();
}
public static final CollisionResult getClosestMouseHitResult(SimpleApplication app) {
Camera cam = app.getCamera();
CollisionResult result;
ray.setOrigin(cam.getLocation());
ray.setDirection(get3DMousePosition(app, v3f_0).subtractLocal(cam.getLocation()));
results.clear();
app.getRootNode().collideWith(ray, results);
result = results.getClosestCollision();
return result;
}
public static Vector3f get3DMousePosition(Application app, Vector3f store) {
v2f_0.set(app.getInputManager().getCursorPosition());
if (!app.getInputManager().isCursorVisible())
store.set(app.getCamera().getDirection());
else store.set(app.getCamera().getWorldCoordinates(v2f_0, 1f).normalizeLocal());
store.addLocal(app.getCamera().getLocation());
return store;
}
public static final Geometry createPoint(float x, float y, float z, float radius) {
Sphere s = new Sphere(4, 4, radius);
Geometry geom = new Geometry("Point(" + x + ", " + y + ", " + z + "), r = " + radius, s);
geom.setLocalTranslation(x, y, z);
return geom;
}
public static final Geometry createPoint(Vector3f pos, float radius) {
Sphere s = new Sphere(4, 4, radius);
Geometry geom = new Geometry("Point" + pos + ", r = " + radius, s);
geom.setLocalTranslation(pos);
return geom;
}
public static final Geometry createFace(Vector3f extent) {
Mesh m;
Geometry g;
Vector3f[] verts = new Vector3f[] { faceVertices[0],
faceVertices[1].mult(extent),
faceVertices[2].mult(extent),
faceVertices[3].mult(extent) };
m = new Mesh();
m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(verts));
m.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(sqrNormals));
m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(sqrIndexes));
m.setMode(Mode.Lines);
m.updateCounts();
m.updateBound();
g = new Geometry("Face(" + verts[0] + ", " + verts[1]
+ ", " + verts[2] + ", " + verts[3] + ")", m);
g.updateModelBound();
return g;
}
public static final Geometry createBox(float xExtent, float yExtent, float zExtent) {
return createBox(v3f_0.set(xExtent, yExtent, zExtent));
}
public static final Geometry createBox(Vector3f extent) {
Mesh m;
Geometry g;
Vector3f[] vertices = new Vector3f[] { cubeVertices[0],
cubeVertices[1].mult(extent),
cubeVertices[2].mult(extent),
cubeVertices[3].mult(extent),
cubeVertices[4].mult(extent),
cubeVertices[5].mult(extent),
cubeVertices[6].mult(extent),
cubeVertices[7].mult(extent) };
m = new Mesh();
m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
m.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));
m.setMode(Mode.Lines);
m.updateCounts();
m.updateBound();
g = new Geometry("Box" + extent, m);
g.updateModelBound();
return g;
}
public static final Node createPolygon(Vector3f[] vertices, boolean triangulate,
Material mat) {
if (vertices != null) {
int n = vertices.length;
if (n > 2) {
Node node = new Node("Polygon-" + n);
Arrow arrow;
Geometry g;
for (int i = 0; i < n; i++) {
v3f_0.set(vertices[i]);
if ((i + 1) < n)
v3f_1.set(vertices[i + 1]);
else v3f_1.set(vertices[0]);
arrow = new Arrow(v3f_1.subtract(v3f_0));
g = new Geometry("", arrow);
g.setLocalTranslation(v3f_0);
g.setMaterial(mat);
node.attachChild(g);
}
return node;
}
}
return null;
}
public static Node createTriPolygon(ArrayList<Vector2f> vertices, Material mat) {
if ((vertices.size() > 2) && ((vertices.size() % 3) == 0)) {
Node node = new Node("triPolygon");
Line line;
Geometry g;
System.out.println("tri count = " + (vertices.size() / 3));
for (int i = 0; i < vertices.size(); i += 3) {
v3f_0.set(vertices.get(i).x, vertices.get(i).y, 0);
v3f_1.set(vertices.get(i + 1).x, vertices.get(i + 1).y, 0);
v3f_2.set(vertices.get(i + 2).x, vertices.get(i + 2).y, 0);
line = new Line(v3f_0, v3f_1);
g = new Geometry("", line);
g.setMaterial(mat);
node.attachChild(g);
line = new Line(v3f_1, v3f_2);
g = new Geometry("", line);
g.setMaterial(mat);
node.attachChild(g);
line = new Line(v3f_2, v3f_0);
g = new Geometry("", line);
g.setMaterial(mat);
node.attachChild(g);
}
return node;
}
return null;
}
public static Node createTriPolygon3d(ArrayList<Vector3f> vertices, Material mat) {
if ((vertices.size() > 2) && ((vertices.size() % 3) == 0)) {
Node node = new Node("triPolygon");
Line line;
Geometry g;
System.out.println("tri count = " + (vertices.size() / 3));
for (int i = 0; i < vertices.size(); i += 3) {
v3f_0.set(vertices.get(i));
v3f_1.set(vertices.get(i + 1));
v3f_2.set(vertices.get(i + 2));
line = new Line(v3f_0, v3f_1);
g = new Geometry("", line);
g.setMaterial(mat);
node.attachChild(g);
line = new Line(v3f_1, v3f_2);
g = new Geometry("", line);
g.setMaterial(mat);
node.attachChild(g);
line = new Line(v3f_2, v3f_0);
g = new Geometry("", line);
g.setMaterial(mat);
node.attachChild(g);
}
return node;
}
return null;
}
public static Node createVertPolygon(ArrayList<Vector3f> vertices, Material mat) {
if (vertices.size() > 2) {
Node node = new Node("vertPolygon");
Geometry g;
System.out.println("vert count = " + vertices.size());
for (int i = 0; i < vertices.size(); i++) {
g = createPoint(vertices.get(i), .05f);
g.setMaterial(mat);
node.attachChild(g);
}
return node;
}
return null;
}
public static Node createVertIds(Vector3f[] vertices, BitmapFont guiFont) {
if (vertices != null) {
int n = vertices.length;
if (n > 2) {
Node node = new Node("vertIds");
BillboardControl bc;
BitmapText vertId;
for (int i = 0; i < n; i++) {
bc = new BillboardControl();
vertId = new BitmapText(guiFont, false);
vertId.setSize(.1f);
vertId.setText("vert " + i + " " + vertices[i]);
vertId.setLocalTranslation(vertices[i]);
vertId.addControl(bc);
node.attachChild(vertId);
}
return node;
}
}
return null;
}
public static Node createTriIds(ArrayList<Vector2f> vertices, BitmapFont guiFont) {
if ((vertices.size() > 2) && ((vertices.size() % 3) == 0)) {
Node node = new Node("triIds");
BillboardControl bc;
BitmapText vertId;
for (int i = 0; i < vertices.size(); i += 3) {
tri.set(0, vertices.get(i).x, vertices.get(i).y, 0);
tri.set(1, vertices.get(i + 1).x, vertices.get(i + 1).y, 0);
tri.set(2, vertices.get(i + 2).x, vertices.get(i + 2).y, 0);
tri.calculateCenter();
bc = new BillboardControl();
vertId = new BitmapText(guiFont, false);
vertId.setSize(.1f);
vertId.setText("tri " + (i / 3));
vertId.setLocalTranslation(tri.getCenter());
vertId.addControl(bc);
node.attachChild(vertId);
}
return node;
}
return null;
}
public static Node createTriIds3d(ArrayList<Vector3f> vertices, BitmapFont guiFont) {
if ((vertices.size() > 2) && ((vertices.size() % 3) == 0)) {
Node node = new Node("triIds");
BillboardControl bc;
BitmapText vertId;
for (int i = 0; i < vertices.size(); i += 3) {
tri.set1(vertices.get(i));
tri.set2(vertices.get(i + 1));
tri.set3(vertices.get(i + 2));
tri.calculateCenter();
bc = new BillboardControl();
vertId = new BitmapText(guiFont, false);
vertId.setSize(.1f);
vertId.setText("tri " + (i / 3));
vertId.setLocalTranslation(tri.getCenter());
vertId.addControl(bc);
node.attachChild(vertId);
}
return node;
}
return null;
}
public static void printMeshData(Geometry refGeom) {
FloatBuffer vB =
(FloatBuffer) refGeom.getMesh().getBuffer(Type.Position)
.getData();
FloatBuffer nB = (FloatBuffer) refGeom.getMesh()
.getBuffer(Type.Normal).getData();
FloatBuffer tB = (FloatBuffer) refGeom.getMesh()
.getBuffer(Type.Tangent).getData();
FloatBuffer bnB = (FloatBuffer) refGeom.getMesh()
.getBuffer(Type.Binormal).getData();
vB.rewind();
nB.rewind();
tB.rewind();
bnB.rewind();
System.out.println("----------------------MeshData---------------------");
System.out.println("Vertice count = " + refGeom.getVertexCount()
+ ", triangle count = " + refGeom.getTriangleCount());
// int i = 0;
// while (vB.hasRemaining()) {
// System.out.println("-------------- " + i + " ----------------");
// System.out.println("Vertex " + vB.get() + ", "
// + vB.get() + ", " + vB.get());
// System.out.println("Normal " + nB.get() + ", "
// + nB.get() + ", " + nB.get());
// System.out.println("Tangent " + tB.get() + ", "
// + tB.get() + ", " + tB.get() + ", " + tB.get());
// System.out.println("Binormal " + bnB.get() + ", "
// + bnB.get() + ", " + bnB.get());
// i++;
// System.out.println("----------------");
// }
}
public static <T> Set<T> differenceSet(Set<T> setA, Set<T> setB) {
Set<T> tmpSet = new HashSet<>();
tmpSet.addAll(setB); // tmpSet = B
tmpSet.removeAll(setA); // setB = B without A
setA.removeAll(setB); // setA = A without B
setA.addAll(tmpSet); // setA = Difference A, B
return setA;
}
public static int matchPowerOfTwo(int value) {
return (int) Math.pow(2, Math.ceil(Math.log10(value) / Math.log10(2)));
}
public static int log2(int value) {
if (value == 0)
return 0;
return (int) (Math.log10(matchPowerOfTwo(value)) / Math.log10(2));
}
public static Vector2f getFovFar(Camera c, float fovAngle) {
float w = c.getWidth();
float h = c.getHeight();
float fovH = 2f * FastMath.tan(fovAngle / 2) * c.getFrustumFar();
float fovW = fovH * (w / h);
return new Vector2f(fovW, fovH);
}
public static void log(Level level, String msg) {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
String traceLink =
"(" + trace[2].getFileName() + ":" + trace[2].getLineNumber()
+ ")";
String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();
logger.logp(level, methodName, traceLink, msg);
}
public static boolean mouseInWindow() {
int mx = MouseInfo.getPointerInfo().getLocation().x;
int my = MouseInfo.getPointerInfo().getLocation().y;
int minX = Display.getX();
int minY = Display.getY();
int maxX = minX + Display.getWidth();
int maxY = minY + Display.getHeight();
return !((mx < minX) || (mx > maxX) || (my < minY) || (my > maxY));
}
public static void printStackTrace() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
StackTraceElement s;
System.out.println("--------------------Stacktrace--------------------");
for (int i = 1; i < (stackTrace.length - 1); i++) {
s = stackTrace[i];
System.out.print(s.getClassName() + "." + s.getMethodName());
System.out.println("(" + s.getFileName() + ":" + s.getLineNumber() + ")");
}
System.out.println("--------------------End trace---------------------");
}
public static void print2DArray(float[][] floatArray) {
for (int j = floatArray[0].length - 1; j >= 0; j--) {
for (float[] element : floatArray)
System.out.print(element[j] + " ");
System.out.println();
}
}
}