package de.venjinx.core;
import java.util.ArrayList;
import com.jme3.bounding.BoundingBox;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.material.Material;
import com.jme3.math.Ray;
import com.jme3.math.Triangle;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.util.BufferUtils;
public class CubicalMarchingSquares {
// 2---------------6
// /| 6 /|
// 9/ | 3/ |
// / | 7 / |
// 3---------------7 |4
// | | 0 | |
// | | | |
// 10 0-----------|---4
// | / 8 1| /
// | /11 | /5
// |/ 2 |/
// 1---------------5
public static int[][] fVerts = new int[][] { { 1, 5, 3, 7 }, // front
{ 0, 4, 2, 6 }, // back
{ 0, 1, 2, 3 }, // left
{ 4, 5, 6, 7 }, // right
{ 0, 4, 1, 5 }, // bottom
{ 2, 6, 3, 7 } }; // top
// public static int[][] edges = new int[][] { { 3, 7 }, { 7, 5 }, { 5, 1 },
// { 7, 6 }, { 6, 4 }, { 4, 5 },
// { 6, 2 }, { 2, 0 }, { 0, 4 },
// { 2, 3 }, { 3, 1 }, { 1, 0 } };
public static Vector3f[] rDirections = new Vector3f[] { new Vector3f(0, 0, 1),
new Vector3f(0, 0, -1),
new Vector3f(1, 0, 0),
new Vector3f(-1, 0, 0),
new Vector3f(0, 1, 0),
new Vector3f(0, -1, 0),
// new Vector3f(1, 0, 1),
// new Vector3f(1, 0, -1),
// new Vector3f(-1, 0, -1),
// new Vector3f(-1, 0, 1),
//
// new Vector3f(0, 1, 1),
// new Vector3f(1, 1, 0),
// new Vector3f(0, 1, -1),
// new Vector3f(-1, 1, 0),
//
// new Vector3f(0, -1, 1),
// new Vector3f(1, -1, 0),
// new Vector3f(0, -1, -1),
// new Vector3f(-1, -1, 0),
//
// new Vector3f(1, 1, 1),
// new Vector3f(1, 1, -1),
// new Vector3f(-1, 1, -1),
// new Vector3f(-1, 1, 1),
//
// new Vector3f(1, -1, 1),
// new Vector3f(1, -1, -1),
// new Vector3f(-1, -1, -1),
// new Vector3f(-1, -1, 1)
};
private int[][] fPts = new int[][] {
{}, // 0
{ 0, 1, 0, 2 },
{ 1, 3, 0, 1 },
{ 1, 3, 0, 2 },
{ 2, 3, 1, 3 }, // 4
{ 0, 1, 0, 2, 2, 3, 1, 3 },
{ 2, 3, 0, 1 },
{ 2, 3, 0, 2 },
{ 0, 2, 2, 3 }, // 8
{ 0, 1, 2, 3 },
{ 1, 3, 0, 1, 0, 2, 2, 3 },
{ 1, 3, 2, 3 },
{ 0, 2, 1, 3 }, // 12
{ 0, 1, 1, 3 },
{ 0, 2, 0, 1 },
{} };
private float[] cellVerts = new float[24];
private float[] cellData = new float[8];
private ArrayList<Float> segs = new ArrayList<>();
private ArrayList<ArrayList<Float>> components = new ArrayList<>();
private boolean cCompleted = false;
private ArrayList<Float> vertList = new ArrayList<>();
private ArrayList<Vector3f> normList = new ArrayList<>();
private ArrayList<Integer> indexList = new ArrayList<>();
private Vector3f normal = new Vector3f();
private Vector3f pt1 = new Vector3f();
private Vector3f pt2 = new Vector3f();
private Vector3f pt3 = new Vector3f();
int[] faceCount = new int[6];
int[] faceCases = new int[16];
int vertCount = 0;
float threshold = .5f;
public Geometry cubicalMarchingSquares(float[][][] data, boolean calcExact,
boolean filterDoubles) {
int xDim = data.length - 1;
int yDim = data[0].length - 1;
int zDim = data[0][0].length - 1;
int cCase;
for (int x = 0; x < xDim; x++)
for (int y = 0; y < yDim; y++)
for (int z = 0; z < zDim; z++) {
getVoxelData(x, y, z, data);
cCase = getCellCase();
if ((cCase > 0) && (cCase < 255)) {
getCellVerts(x, y, z);
generateCellSegments(calcExact);
formComponents();
}
}
triangulate(filterDoubles);
Vector3f[] vertices = new Vector3f[vertList.size() / 3];
Vector3f[] normals = new Vector3f[normList.size()];
Vector2f[] texCoords = new Vector2f[normList.size()];
int[] indexes = new int[indexList.size()];
for (int i = 0; i < (vertList.size() / 3); i++) {
vertices[i] =
new Vector3f(vertList.get(i * 3), vertList.get((i * 3) + 1),
vertList.get((i * 3) + 2));
texCoords[i] = new Vector2f(vertices[i].x / (xDim + 1), 1 - (vertices[i].z / (zDim + 1)));
normals[i] = normList.get(i).normalize();
}
for (int i = 0; i < indexList.size(); i++)
indexes[i] = indexList.get(i);
vertList.clear();
normList.clear();
indexList.clear();
components.clear();
Mesh m = new Mesh();
m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
m.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoords));
m.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));
m.updateBound();
return new Geometry("Terrain", m);
}
public Geometry cubicalMarchingSquares(AbstractHeightMap heightMap, float scale,
boolean useExact, boolean filterDoubles) {
heightMap.setHeightScale(scale - 1);
float[] b = heightMap.findMinMaxHeights();
// int[] xBound = new int[] { 0, heightMap.getSize() };
int[] yBound = new int[] { 0, (int) Math.ceil(b[1] * (scale)) };
// int[] zBound = new int[] { 0, heightMap.getSize() };
int[] xBound = new int[] { 0, 63 };
// int[] yBound = new int[] { 0, 5 };
int[] zBound = new int[] { 0, 63 };
int cCase;
faceCount = new int[6];
faceCases = new int[16];
for (int x = xBound[0]; x < xBound[1]; x++)
for (int y = yBound[0]; y < yBound[1]; y++)
for (int z = zBound[0]; z < zBound[1]; z++) {
getVoxelData(x, y, z, scale, heightMap);
cCase = getCellCase();
if ((cCase > 0) && (cCase < 255)) {
// System.out.println("block " + "x = " + x + ", y = " + y
// + ", z = " + z + ": case: " + cCase);
// System.out.println();
getCellVerts(x, y, z);
generateCellSegments(useExact);
// System.out.println("----form comps-----");
formComponents();
}
// System.out.println("-----------");
}
// for (int i = 0; i < faceCount.length; i++) {
// System.out.println("Face " + i + ": " + faceCount[i]);
// }
// for (int i = 0; i < faceCases.length; i++) {
// System.out.println("FaceCase " + i + ": " + faceCases[i]);
// }
triangulate(filterDoubles);
Vector3f[] vertices = new Vector3f[vertList.size() / 3];
Vector3f[] normals = new Vector3f[normList.size()];
Vector2f[] texCoords = new Vector2f[normList.size()];
int[] indexes = new int[indexList.size()];
for (int i = 0; i < (vertList.size() / 3); i++) {
vertices[i] =
new Vector3f(vertList.get(i * 3), vertList.get((i * 3) + 1),
vertList.get((i * 3) + 2));
// System.out.println("v " + i + " " + vertices[i]);
texCoords[i] =
new Vector2f(vertices[i].x / xBound[1], 1 - (vertices[i].z
/ zBound[1]));
// texCoords[i] = new Vector2f(vertices[i].x / 1024, 1 - vertices[i].z /
// 1024);
normals[i] = normList.get(i).normalize();
// System.out.println("v" + i + " " + vertices[i].x + ", "
// + vertices[i].y + ", " + vertices[i].z + ": "
// + (heightMap.getInterpolatedHeight(vertices[i].x,
// vertices[i].z) - vertices[i].y));
}
for (int i = 0; i < indexList.size(); i++)
indexes[i] = indexList.get(i);
vertList.clear();
normList.clear();
indexList.clear();
components.clear();
Mesh m = new Mesh();
m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
m.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoords));
m.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));
m.updateCounts();
m.updateBound();
return new Geometry("Terrain", m);
}
private float getIsoLevel(float x, float y, float z, float scale,
AbstractHeightMap heightMap) {
float isoLevel = 0;
isoLevel = heightMap.getInterpolatedHeight(x, z) - y;
// System.out.println("iso: " + isoLevel);
if (isoLevel < -1)
isoLevel -= isoLevel + 1;
if (isoLevel > 1)
isoLevel -= isoLevel - 1;
// System.out.println("true: " + heightMap.getTrueHeightAtPoint((int) x, (int)
// z));
// System.out.println("scaled: "
// + heightMap.getScaledHeightAtPoint((int) x, (int) z));
// System.out.println("inter: " + heightMap.getInterpolatedHeight(x, z));
// System.out.println("iso: " + isoLevel);
// System.out.println("--------------");
return isoLevel;
}
private void triangulate(boolean filterDoubles) {
boolean ptExists = false;
Vector3f cPt = new Vector3f();
for (ArrayList<Float> c : components) {
// System.out.println("---------------triangulate" + c.size()
// + "-----------------");
cPt.set(0, 0, 0);
if ((c.size() / 3) > 4) {
for (int i = 0; i < c.size(); i += 3)
cPt.addLocal(c.get(i), c.get(i + 1), c.get(i + 2));
cPt.divideLocal(c.size() / 3);
c.add(c.get(0));
c.add(c.get(1));
c.add(c.get(2));
c.add(0, cPt.z);
c.add(0, cPt.y);
c.add(0, cPt.x);
}
pt1.x = c.get(0);
pt1.y = c.get(1);
pt1.z = c.get(2);
int pt1ID = -1;
if (filterDoubles) {
ptExists = false;
for (int j = vertList.size() - 3; j >= 0; j -= 3)
if (vertList.get(j).equals(pt1.x))
if (vertList.get(j + 1).equals(pt1.y))
if (vertList.get(j + 2).equals(pt1.z)) {
ptExists = true;
pt1ID = j / 3;
break;
}
if (!ptExists) {
pt1ID = vertList.size() / 3;
vertList.add(pt1.x);
vertList.add(pt1.y);
vertList.add(pt1.z);
normList.add(new Vector3f(0, 0, 0));
}
}
for (int i = 0; i < ((c.size() / 3) - 2); i++) {
pt2.x = c.get((i + 1) * 3);
pt2.y = c.get(((i + 1) * 3) + 1);
pt2.z = c.get(((i + 1) * 3) + 2);
pt3.x = c.get((i + 2) * 3);
pt3.y = c.get(((i + 2) * 3) + 1);
pt3.z = c.get(((i + 2) * 3) + 2);
normal = new Vector3f(0, 0, 0);
Triangle.computeTriangleNormal(pt1, pt2, pt3, normal);
if (filterDoubles) {
normList.get(pt1ID).addLocal(normal);
indexList.add(pt1ID);
ptExists = false;
for (int j = vertList.size() - 3; j >= 0; j -= 3)
if (vertList.get(j).equals(pt2.x))
if (vertList.get(j + 1).equals(pt2.y))
if (vertList.get(j + 2).equals(pt2.z)) {
ptExists = true;
normList.get(j / 3).addLocal(normal);
indexList.add(j / 3);
break;
}
if (!ptExists) {
indexList.add(vertList.size() / 3);
vertList.add(pt2.x);
vertList.add(pt2.y);
vertList.add(pt2.z);
normList.add(new Vector3f(normal));
}
ptExists = false;
for (int j = vertList.size() - 3; j >= 0; j -= 3)
if (vertList.get(j).equals(pt3.x))
if (vertList.get(j + 1).equals(pt3.y))
if (vertList.get(j + 2).equals(pt3.z)) {
ptExists = true;
normList.get(j / 3).addLocal(normal);
indexList.add(j / 3);
break;
}
if (!ptExists) {
indexList.add(vertList.size() / 3);
vertList.add(pt3.x);
vertList.add(pt3.y);
vertList.add(pt3.z);
normList.add(new Vector3f(normal));
}
} else {
indexList.add(vertList.size() / 3);
indexList.add((vertList.size() / 3) + 1);
indexList.add((vertList.size() / 3) + 2);
vertList.add(pt1.x);
vertList.add(pt1.y);
vertList.add(pt1.z);
vertList.add(pt2.x);
vertList.add(pt2.y);
vertList.add(pt2.z);
vertList.add(pt3.x);
vertList.add(pt3.y);
vertList.add(pt3.z);
normList.add(new Vector3f(normal));
normList.add(new Vector3f(normal));
normList.add(new Vector3f(normal));
}
}
}
}
private void formComponents() {
ArrayList<Float> comp = new ArrayList<>();
cCompleted = false;
if (!segs.isEmpty()) {
// System.out.println("---------------form components" + segs.size()
// + "----------------");
// for (int i = 0; i < segs.size(); i += 6) {
// System.out.print("(" + segs.get(i) + ", " + segs.get(i + 1) + ", "
// + segs.get(i + 2) + ") - ");
// System.out.println("(" + segs.get(i + 3) + ", " + segs.get(i + 4) + ", "
// + segs.get(i + 5) + ")");
// }
comp.add(segs.remove(0));
comp.add(segs.remove(0));
comp.add(segs.remove(0));
comp.add(segs.remove(0));
comp.add(segs.remove(0));
comp.add(segs.remove(0));
while (!segs.isEmpty())
for (int i = 0; i < segs.size(); i += 6) {
if (comp.get(comp.size() - 3).equals(segs.get(i))
&& comp.get(comp.size() - 2).equals(segs.get(i + 1))
&& comp.get(comp.size() - 1).equals(segs.get(i + 2))) {
segs.remove(i);
segs.remove(i);
segs.remove(i);
if (comp.get(0).equals(segs.get(i))
&& comp.get(1).equals(segs.get(i + 1))
&& comp.get(2).equals(segs.get(i + 2))) {
cCompleted = true;
segs.remove(i);
segs.remove(i);
segs.remove(i);
} else {
comp.add(segs.remove(i));
comp.add(segs.remove(i));
comp.add(segs.remove(i));
}
i -= 6;
} else
if (comp.get(comp.size() - 3).equals(segs.get(i + 3))
&& comp.get(comp.size() - 2).equals(segs.get(i + 4))
&& comp.get(comp.size() - 1).equals(segs.get(i + 5))) {
segs.remove(i + 3);
segs.remove(i + 3);
segs.remove(i + 3);
if (comp.get(0).equals(segs.get(i))
&& comp.get(1).equals(segs.get(i + 1))
&& comp.get(2).equals(segs.get(i + 2))) {
cCompleted = true;
segs.remove(i);
segs.remove(i);
segs.remove(i);
} else {
comp.add(segs.remove(i));
comp.add(segs.remove(i));
comp.add(segs.remove(i));
}
i -= 6;
}
if (cCompleted) {
components.add(comp);
cCompleted = false;
if (!segs.isEmpty()) {
comp = new ArrayList<>();
comp.add(segs.remove(0));
comp.add(segs.remove(0));
comp.add(segs.remove(0));
comp.add(segs.remove(0));
comp.add(segs.remove(0));
comp.add(segs.remove(0));
}
break;
}
}
}
}
private Vector3f calcIntersection(float[] pts, float[] densities) {
Vector3f intersection = new Vector3f(0, 0, 0);
// float d0 = densities[0], d1 = densities[1];
//
float step = .5f;
// if (d1 >= 0)
// step = d1;
//
// if (d2 >= 0)
// step = .5f + Math.signum(d0) * ((d0 + d1)) / 2;
// System.out.print("step: " + step + ", d0: " + d0 + ", d1: " + d1 + ", ");
// step =
// Math.abs(cellData[pts[1]])
// / Math.abs(cellData[pts[0]] - cellData[pts[1]]);
// System.out.println(", step " + step);
// if (step < .1f)
// step = 0;
// if (step > .9f)
// step = 1;
// System.out.print(" - " + pts[0] + ", " + pts[1] + ", " + pts[2]);
intersection.x = (step * (pts[3] - pts[0])) + pts[0];
intersection.y = (step * (pts[4] - pts[1])) + pts[1];
intersection.z = (step * (pts[5] - pts[2])) + pts[2];
intersection.x = Math.round(intersection.x * 10000f) / 10000f;
intersection.y = Math.round(intersection.y * 10000f) / 10000f;
intersection.z = Math.round(intersection.z * 10000f) / 10000f;
// System.out.println(" intersection " + intersection);
return intersection;
}
public void createFaceOctree(float[] lData, int depth) {
// Geometry refGeom = new Geometry();
// Vector3f pos = new Vector3f();
double d = Math.pow(2, -depth);
float[] data = new float[4];
if (depth > 0)
if (((data[0] % d) != 0) || ((data[1] % d) != 0) || ((data[2] % d) != 0)
|| ((data[3] % d) != 0))
for (int i = 0; i < 4; i++) {
// newData[i] = data[i];
// newData[1] = extractCellData(refGeom, pos);
// createOctree(extractCellData(refGeom, pos), depth - 1, threshold);
}
}
private void generateCellSegments(boolean calcExact) {
int fCase;
// float[] fCenter = new float[] { 0, 0, 0 };
for (int i = 0; i < 6; i++) {
fCase = getFaceCase(i);
// vertIndex = fVerts[i][3] * 3;
// fCenter[0] += cellVerts[fVerts2[i][0] * 3];
// fCenter[1] += cellVerts[fVerts2[i][0] * 3 + 1];
// fCenter[2] += cellVerts[fVerts2[i][0] * 3 + 2];
//
// fCenter[0] += cellVerts[fVerts2[i][1] * 3];
// fCenter[1] += cellVerts[fVerts2[i][1] * 3 + 1];
// fCenter[2] += cellVerts[fVerts2[i][1] * 3 + 2];
//
// fCenter[0] += cellVerts[fVerts2[i][2] * 3];
// fCenter[1] += cellVerts[fVerts2[i][2] * 3 + 1];
// fCenter[2] += cellVerts[fVerts2[i][2] * 3 + 2];
//
// fCenter[0] += cellVerts[fVerts2[i][3] * 3];
// fCenter[1] += cellVerts[fVerts2[i][3] * 3 + 1];
// fCenter[2] += cellVerts[fVerts2[i][3] * 3 + 2];
//
// fCenter[0] /= 4;
// fCenter[1] /= 4;
// fCenter[2] /= 4;
if ((fCase != 0) && (fCase != 15)) {
// System.out.println("------------------Face " + i + " " + fCase
// + "------------------");
Vector3f[] intersection =
new Vector3f[] { new Vector3f(0, 0, 0),
new Vector3f(0, 0, 0) };
faceCases[fCase]++;
faceCount[i]++;
float[] segPts = new float[] { 0, 0, 0, 0, 0, 0 };
int ptID1 = fVerts[i][fPts[fCase][0]];
int ptID2 = fVerts[i][fPts[fCase][1]];
segPts[0] = cellVerts[ptID1 * 3];
segPts[1] = cellVerts[(ptID1 * 3) + 1];
segPts[2] = cellVerts[(ptID1 * 3) + 2];
segPts[3] = cellVerts[ptID2 * 3];
segPts[4] = cellVerts[(ptID2 * 3) + 1];
segPts[5] = cellVerts[(ptID2 * 3) + 2];
intersection[0] = calcIntersection(segPts,
new float[] { cellData[ptID1],
cellData[ptID2] });
// System.out.print("Intersection 0: " + ptID1 + " (" + segPts[0] + ", "
// + segPts[1] + ", " + segPts[2] + ") - ");
// System.out.print(ptID2 + " (" + segPts[3] + ", " + segPts[4] + ", "
// + segPts[5] + ") - ");
// System.out.println(intersection[0]);
ptID1 = fVerts[i][fPts[fCase][2]];
ptID2 = fVerts[i][fPts[fCase][3]];
segPts[0] = cellVerts[ptID1 * 3];
segPts[1] = cellVerts[(ptID1 * 3) + 1];
segPts[2] = cellVerts[(ptID1 * 3) + 2];
segPts[3] = cellVerts[ptID2 * 3];
segPts[4] = cellVerts[(ptID2 * 3) + 1];
segPts[5] = cellVerts[(ptID2 * 3) + 2];
intersection[1] = calcIntersection(segPts,
new float[] { cellData[ptID1],
cellData[ptID2] });
// System.out.print("Intersection 1: " + ptID1 + " (" + segPts[0] + ", "
// + segPts[1] + ", " + segPts[2] + ") - ");
// System.out.print(ptID2 + " (" + segPts[3] + ", " + segPts[4] + ", "
// + segPts[5] + ") - ");
// System.out.println(intersection[1]);
if (!intersection[0].equals(intersection[1])) {
segs.add(intersection[i % 2].x);
segs.add(intersection[i % 2].y);
segs.add(intersection[i % 2].z);
segs.add(intersection[1 - (i % 2)].x);
segs.add(intersection[1 - (i % 2)].y);
segs.add(intersection[1 - (i % 2)].z);
}
if ((fCase == 5) || (fCase == 10)) {
// System.out.println("asdasdasdasdasdasd");
ptID1 = fVerts[i][fPts[fCase][4]];
ptID2 = fVerts[i][fPts[fCase][5]];
segPts[0] = cellVerts[ptID1 * 3];
segPts[1] = cellVerts[(ptID1 * 3) + 1];
segPts[2] = cellVerts[(ptID1 * 3) + 2];
segPts[3] = cellVerts[ptID2 * 3];
segPts[4] = cellVerts[(ptID2 * 3) + 1];
segPts[5] = cellVerts[(ptID2 * 3) + 2];
intersection[0] = calcIntersection(segPts,
new float[] { cellData[ptID1],
cellData[ptID2] });
// System.out.print("Intersection 2: " + ptID1 + " (" + segPts[0] +
// ", "
// + segPts[1] + ", " + segPts[2] + ") - ");
// System.out.print(ptID2 + " (" + segPts[3] + ", " + segPts[4] + ", "
// + segPts[5] + ") - ");
// System.out.println(intersection[0]);
ptID1 = fVerts[i][fPts[fCase][6]];
ptID2 = fVerts[i][fPts[fCase][7]];
segPts[0] = cellVerts[ptID1 * 3];
segPts[1] = cellVerts[(ptID1 * 3) + 1];
segPts[2] = cellVerts[(ptID1 * 3) + 2];
segPts[3] = cellVerts[ptID2 * 3];
segPts[4] = cellVerts[(ptID2 * 3) + 1];
segPts[5] = cellVerts[(ptID2 * 3) + 2];
intersection[1] = calcIntersection(segPts,
new float[] { cellData[ptID1],
cellData[ptID2] });
// System.out.print("Intersection 3: " + ptID1 + "( " + segPts[0] +
// ", "
// + segPts[1] + ", " + segPts[2] + ") - ");
// System.out.print(ptID1 + " (" + segPts[3] + ", " + segPts[4] + ", "
// + segPts[5] + ") - ");
// System.out.println(intersection[1]);
if (!intersection[0].equals(intersection[1])) {
segs.add(intersection[i % 2].x);
segs.add(intersection[i % 2].y);
segs.add(intersection[i % 2].z);
segs.add(intersection[1 - (i % 2)].x);
segs.add(intersection[1 - (i % 2)].y);
segs.add(intersection[1 - (i % 2)].z);
}
}
// System.out.println("------------------face end-------------------");
}
}
}
public float[][][] extractVoxelData(Geometry refGeom) {
float[][][] data;
// float density, angle;
Vector3f extent = new Vector3f();
Vector3f min = new Vector3f(), max = new Vector3f();
// Vector3f start = new Vector3f();
// CollisionResults results = new CollisionResults();
// CollisionResult result;
// Vector3f dir = new Vector3f();
// Vector3f cp = new Vector3f();
BoundingBox bm = (BoundingBox) refGeom.getWorldBound();
bm.getMin(min);
bm.getMax(max);
// min.subtractLocal(1, 1, 1);
// max.addLocal(1, 1, 1);
min.x = (float) Math.floor(min.x);
min.y = (float) Math.floor(min.y);
min.z = (float) Math.floor(min.z);
max.x = (float) Math.ceil(max.x);
max.y = (float) Math.ceil(max.y);
max.z = (float) Math.ceil(max.z);
extent = max.subtract(min);
data = new float[(int) extent.x + 1][(int) extent.y + 1][(int) extent.z + 1];
for (int x = 0; x < (extent.x + 1); x++)
for (int y = 0; y < (extent.y + 1); y++)
for (int z = 0; z < (extent.z + 1); z++) {
data[x][y][z] = extractVoxelData2(refGeom, min.add(x, y, z));
// System.out.println(data[x][y][z]);
if (data[x][y][z] < -1)
data[x][y][z] -= data[x][y][z] + 1;
if (data[x][y][z] > 1)
data[x][y][z] -= data[x][y][z] - 1;
}
return data;
}
// public float extractVoxelData(Geometry refGeom, Vector3f voxelPos) {
// float density = -1, angle;
// CollisionResults results = new CollisionResults();
// Vector3f dir = new Vector3f();
// Vector3f cp = new Vector3f();
//
// results.clear();
// Ray r;
// // System.out.println("Results for " + pos);
// int added = 0;
// CollisionResult closestResult = null;
// float dist = Float.POSITIVE_INFINITY, tmpDist = 0;
// for (Vector3f rDirection : rDirections) {
// r = new Ray(voxelPos, rDirection.normalize());
// // r.setLimit(1);
// added = refGeom.collideWith(r, results);
//
// // if (added > 0) {
// // System.out.println(r.direction + ", " + added);
// // }
// }
//
// // Triangle tri;
// CollisionResult result;
//
// for (int i = 0; i < results.size(); i++) {
// // tri = new Triangle();
// result = results.getCollision(i);
// // result.getTriangle(tri);
// //
// // cp.set(result.getContactPoint());
//
// // System.out.println("tri " + tri.getIndex() + " " + tri.getCenter());
// // System.out.println("hit " + i + ": contact " + cp
// // + ", normal " + result.getContactNormal() + ", distance "
// // + result.getDistance());
// // System.out.println();
//
// tmpDist = result.getTriangle(null).getCenter().distance(voxelPos);
// if (dist > tmpDist) {
// closestResult = result;
// dist = tmpDist;
// }
// }
//
// if (closestResult != null) {
// if (results.getClosestCollision().getDistance() == 0)
// closestResult = results.getClosestCollision();
// // result = results.getClosestCollision();
//
// cp.set(closestResult.getContactPoint());
// // System.out.println("closest " + cp);
//
// dir = cp.subtract(voxelPos).normalize();
//
// angle = (float) Math.toDegrees(closestResult.getTriangle(null)
// .getNormal().angleBetween(dir));
//
// density = cp.distance(voxelPos);
//
// if (angle > 90 && angle < 270) {
// density *= -1;
// }
// }
// // System.out.println("----------------------------------");
// return density;
// }
public float extractVoxelData2(Geometry refGeom, Vector3f voxelPos) {
// float density = -1, angle;
float[] densities0, densities1;
CollisionResults tmpResults = new CollisionResults();
CollisionResults results = new CollisionResults();
// float d0, d1;
// CollisionResult result = null;
CollisionResult r;
// boolean dbl = false;
// float dist = Float.POSITIVE_INFINITY, tmpDist = 0;
Ray ray = new Ray();
ray.setLimit(1);
// int edgeCase = 0;
// int added = 0;
// float d0, d1;
for (Vector3f rDirection : rDirections) {
tmpResults.clear();
ray.setOrigin(voxelPos);
ray.setDirection(rDirection);
// added = refGeom.collideWith(ray, tmpResults);
if (refGeom.collideWith(ray, tmpResults) > 0) {
// d0 = tmpResults.getClosestCollision().getDistance();
ray.setOrigin(voxelPos.add(rDirection));
ray.setDirection(rDirection.negate());
refGeom.collideWith(ray, tmpResults);
// d1 = tmpResults.getFarthestCollision().getDistance();
// edgeCase = Math.abs(d0) - Math.abs(d1);
} else {
}
// if (refGeom.collideWith(ray, tmpResults) > 0) {
// ray.setOrigin(voxelPos.add(rDirection));
// ray.setDirection(rDirection.negate());
// refGeom.collideWith(ray, tmpResults);
// }
for (int i = 0; i < tmpResults.size(); i++) {
r = tmpResults.getCollision(i);
// dbl = false;
// if (results.size() > 0)
// if (r.getContactPoint()
// .equals(results.getCollision(results.size() - 1).getContactPoint())
// && r.getDistance() == results.getCollision(results.size() - 1)
// .getDistance()) {
// dbl = true;
// }
// if (r.getDistance() <= 1 && !dbl) {
results.addCollision(r);
// } else {
// // results.d
// }
}
// if (added > 0) {
//
// for (int i = 0; i < results.size(); i++) {
// tmpResult = results.getCollision(i);
//
// tmpDist = tmpResult.getTriangle(null).getCenter().distance(voxelPos);
// if (dist > tmpDist) {
// result = tmpResult;
// dist = tmpDist;
// }
// }
// }
// if (added > 0) {
//
// for (int i = 0; i < results.size(); i++) {
// tmpResult = results.getCollision(i);
//
// tmpDist = tmpResult.getTriangle(null).getCenter().distance(voxelPos);
// if (dist > tmpDist) {
// result = tmpResult;
// dist = tmpDist;
// }
// }
// d0 = result.getDistance();
//
// angle = (float) Math.toDegrees(result.getTriangle(null)
// .getNormal()
// .angleBetween(rDirection));
//
// if (angle > 90 && angle < 270) {
// d0 *= -1;
// }
//
// results.clear();
// r.setOrigin(voxelPos.add(rDirection));
// r.setDirection(rDirection.negate());
// refGeom.collideWith(r, results);
// for (int i = 0; i < results.size(); i++) {
// tmpResult = results.getCollision(i);
// // System.out.println(tmpResult.getDistance());
//
// if (Math.abs(tmpResult.getDistance()) <= 1) {
// tmpDist = tmpResult.getTriangle(null).getCenter()
// .distance(voxelPos);
// dist = Float.NEGATIVE_INFINITY;
// if (dist < tmpDist) {
// result = tmpResult;
// dist = tmpDist;
// }
// }
// }
// d1 = result.getDistance();
//
// angle = (float) Math.toDegrees(result.getTriangle(null)
// .getNormal()
// .angleBetween(rDirection.negate()));
//
// if (angle > 90 && angle < 270) {
// d1 *= -1;
// }
//
// density = d0 + Math.signum(d0) * ((1 - (d0 + d1)) / 2);
// System.out.println("density: " + density + ", d0: " + d0 + ", d1: " + d1
// + ", ");
// added = -1;
// }
// if (added == -1)
// break;
}
if (results.size() > 0) {
// System.out.println("Results for " + voxelPos);
densities0 = new float[results.size()];
densities1 = new float[results.size()];
for (int i = 0; i < results.size(); i++) {
r = results.getCollision(i);
densities0[0] = r.getDistance();
densities1[0] = r.getDistance();
// tmpDist = tmpResult.getTriangle(null).getCenter().distance(voxelPos);
// if (dist > tmpDist) {
// result = tmpResult;
// dist = tmpDist;
// }
// System.out.println("Result " + i + ": contact " + r.getContactPoint()
// + ",\n normal " + r.getContactNormal()
// + ",\n distance " + r.getDistance()
// + ", triIndex " + r.getTriangleIndex()
// + ", tri distance "
// + r.getTriangle(null).getCenter().distance(voxelPos));
// System.out.println();
}
// System.out.println("----------------------------------");
}
return .5f;
}
public float[][][] extractCellData(Geometry refGeom, Vector3f cellPos) {
float[][][] data = new float[2][2][2];
cellPos.x = (float) Math.floor(cellPos.x);
cellPos.y = (float) Math.floor(cellPos.y);
cellPos.z = (float) Math.floor(cellPos.z);
for (int x = 0; x < 2; x++)
for (int y = 0; y < 2; y++)
for (int z = 0; z < 2; z++)
data[x][y][z] = extractVoxelData2(refGeom, cellPos.add(x, y, z));
// if (data[x][y][z] < -1)
// data[x][y][z] -= data[x][y][z] + 1;
// if (data[x][y][z] > 1)
// data[x][y][z] -= data[x][y][z] - 1;
return data;
}
// public Geometry editGeometry(float value, CollisionResult hit) {
// Geometry g = hit.getGeometry();
// Vector3f cp, cellPos = new Vector3f(), min = new Vector3f();
// int x, y, z;
// float[][][] data;
// if (hit != null && hit.getGeometry().getName().equals("Terrain")) {
// data = extractVoxelData(g);
//
// cp = hit.getContactPoint();
//
// cellPos.set((float) Math.floor(cp.x), (float) Math.floor(cp.y),
// (float) Math.floor(cp.z));
//
// BoundingBox bm = (BoundingBox) g.getWorldBound();
// bm.getMin(min);
// min.x = (float) Math.floor(min.x);
// min.y = (float) Math.floor(min.y);
// min.z = (float) Math.floor(min.z);
// // cp.x = Math.round(cp.x);
// // cp.y = Math.round(cp.y);
// // cp.z = Math.round(cp.z);
//
// x = Math.round(cp.x - min.x);
// y = Math.round(cp.y - min.y);
// z = Math.round(cp.z - min.z);
//
// // cp.subtractLocal(min);
//
// data[x][y][z] += value;
// if (data[x][y][z] < -1)
// data[x][y][z] = -1;
// else
// if (data[x][y][z] > 1)
// data[x][y][z] = 1;
//
// // System.out.println(cp);
// // if (shift_pressed) {
// // data[(int) cp.x][(int) cp.y][(int) cp.z] -= value;
// // if (data[(int) cp.x][(int) cp.y][(int) cp.z] < -1)
// // data[(int) cp.x][(int) cp.y][(int) cp.z] = -1;
// // } else {
// // data[(int) cp.x][(int) cp.y][(int) cp.z] += value;
// // if (data[(int) cp.x][(int) cp.y][(int) cp.z] > 1)
// // data[(int) cp.x][(int) cp.y][(int) cp.z] = 1;
// // }
//
// Material mat = g.getMaterial();
// g.getParent().detachChild(g);
// g = cubicalMarchingSquares(data, true, true);
// g.setMaterial(mat);
// // for lighting effect
// // TangentBinormalGenerator.generate(g.getMesh());
//
// return g;
//
//
// // myApp.getRootNode().detachChild(debug);
// // debug = buildDebugObjects(terrain);
// // myApp.getRootNode().attachChild(debug);
// }
// return null;
// }
public Geometry editGeometry(Geometry g, float value, Vector3f pos) {
int x, y, z;
Vector3f min = new Vector3f();
Node parent = g.getParent();
float[][][] data = extractVoxelData(g);
BoundingBox bm = (BoundingBox) g.getWorldBound();
bm.getMin(min);
min.x = (float) Math.floor(min.x);
min.y = (float) Math.floor(min.y);
min.z = (float) Math.floor(min.z);
// pos.x = Math.round(pos.x);
// pos.y = Math.round(pos.y);
// pos.z = Math.round(pos.z);
// pos.subtractLocal(min);
x = Math.round(pos.x - min.x);
y = Math.round(pos.y - min.y);
z = Math.round(pos.z - min.z);
data[x][y][z] = value;
if (data[x][y][z] < -1)
data[x][y][z] = -1;
else
if (data[x][y][z] > 1)
data[x][y][z] = 1;
// for (int x1 = 0; x1 < 3; x1++) {
// for (int y1 = 0; y1 < 3; y1++) {
// for (int z1 = 0; z1 < 3; z1++) {
// System.out.println(x1 + ", " + y1 + ", " + z1);
// System.out.println(data[x1][y1][z1]);
// }
//
// }
// }
// System.out.println(cp);
// if (shift_pressed) {
// data[(int) pos.x][(int) pos.y][(int) pos.z] = value;
// if (data[(int) pos.x][(int) pos.y][(int) pos.z] < -1)
// data[(int) pos.x][(int) pos.y][(int) pos.z] = -1;
// } else {
// data[(int) pos.x][(int) pos.y][(int) pos.z] = value;
// if (data[(int) pos.x][(int) pos.y][(int) pos.z] > 1)
// data[(int) pos.x][(int) pos.y][(int) pos.z] = 1;
// }
Material mat = g.getMaterial();
if (parent != null) {
parent.detachChild(g);
g = cubicalMarchingSquares(data, true, true);
g.setMaterial(mat);
parent.attachChild(g);
return g;
}
g = cubicalMarchingSquares(data, true, true);
g.setMaterial(mat);
// for lighting effect
// TangentBinormalGenerator.generate(terrain.getMesh());
return g;
// myApp.getRootNode().detachChild(debug);
// debug = buildDebugObjects(terrain);
// myApp.getRootNode().attachChild(debug);
}
private void getCellVerts(float x, float y, float z) {
cellVerts[0] = x;
cellVerts[1] = y;
cellVerts[2] = z;
cellVerts[3] = x;
cellVerts[4] = y;
cellVerts[5] = z + 1;
cellVerts[6] = x;
cellVerts[7] = y + 1;
cellVerts[8] = z;
cellVerts[9] = x;
cellVerts[10] = y + 1;
cellVerts[11] = z + 1;
cellVerts[12] = x + 1;
cellVerts[13] = y;
cellVerts[14] = z;
cellVerts[15] = x + 1;
cellVerts[16] = y;
cellVerts[17] = z + 1;
cellVerts[18] = x + 1;
cellVerts[19] = y + 1;
cellVerts[20] = z;
cellVerts[21] = x + 1;
cellVerts[22] = y + 1;
cellVerts[23] = z + 1;
}
private void getVoxelData(int x, int y, int z, float[][][] data) {
cellData[0] = data[x][y][z];
cellData[1] = data[x][y][z + 1];
cellData[2] = data[x][y + 1][z];
cellData[3] = data[x][y + 1][z + 1];
cellData[4] = data[x + 1][y][z];
cellData[5] = data[x + 1][y][z + 1];
cellData[6] = data[x + 1][y + 1][z];
cellData[7] = data[x + 1][y + 1][z + 1];
// System.out.println("cellData 0: " + data[x][y][z]);
// System.out.println("cellData 1: " + data[x][y][z + 1]);
// System.out.println("cellData 2: " + data[x][y + 1][z]);
// System.out.println("cellData 3: " + data[x][y + 1][z + 1]);
// System.out.println("cellData 4: " + data[x + 1][y][z]);
// System.out.println("cellData 5: " + data[x + 1][y][z + 1]);
// System.out.println("cellData 6: " + data[x + 1][y + 1][z]);
// System.out.println("cellData 7: " + data[x + 1][y + 1][z + 1]);
// for (int f = 0; f < 8; f++) {
// System.out.println("cellData2 " + f + ": " + cellData[f]);
// }
// System.out.println("-------------------");
}
private void getVoxelData(int x, int y, int z, float scale,
AbstractHeightMap heightMap) {
cellData[0] = getIsoLevel(x, y, z, scale, heightMap);
cellData[1] = getIsoLevel(x, y, z + 1, scale, heightMap);
cellData[2] = getIsoLevel(x, y + 1, z, scale, heightMap);
cellData[3] = getIsoLevel(x, y + 1, z + 1, scale, heightMap);
cellData[4] = getIsoLevel(x + 1, y, z, scale, heightMap);
cellData[5] = getIsoLevel(x + 1, y, z + 1, scale, heightMap);
cellData[6] = getIsoLevel(x + 1, y + 1, z, scale, heightMap);
cellData[7] = getIsoLevel(x + 1, y + 1, z + 1, scale, heightMap);
// cellData[0] = heightMap.getScaledHeightAtPoint(x, z) - y;
// cellData[1] = heightMap.getScaledHeightAtPoint(x, z + 1) - y;
// cellData[2] = heightMap.getScaledHeightAtPoint(x, z) - (y + 1);
// cellData[3] = heightMap.getScaledHeightAtPoint(x, z + 1) - (y + 1);
// cellData[4] = heightMap.getScaledHeightAtPoint(x + 1, z) - y;
// cellData[5] = heightMap.getScaledHeightAtPoint(x + 1, z + 1) - y;
// cellData[6] = heightMap.getScaledHeightAtPoint(x + 1, z) - (y + 1);
// cellData[7] =
// heightMap.getScaledHeightAtPoint(x + 1, z + 1)
// - (y + 1);
// cellData[0] = heightMap.getTrueHeightAtPoint(x, z) * y;
// cellData[1] = heightMap.getTrueHeightAtPoint(x, z + 1) * y;
// cellData[2] = heightMap.getTrueHeightAtPoint(x, z) * y;
// cellData[3] = heightMap.getTrueHeightAtPoint(x, z + 1) * y;
// cellData[4] = heightMap.getTrueHeightAtPoint(x + 1, z) * y;
// cellData[5] = heightMap.getTrueHeightAtPoint(x + 1, z + 1) * y;
// cellData[6] = heightMap.getTrueHeightAtPoint(x + 1, z) * y;
// cellData[7] = heightMap.getTrueHeightAtPoint(x + 1, z + 1) * y;
// for (int i = 0; i < 8; i++) {
// System.out.println("cellData " + i + ": " + cellData[i]);
// }
// System.out.println("-------------------");
}
private int getFaceCase(int faceIndex) {
int fCase = 0;
if (cellData[fVerts[faceIndex][0]] < 0)
fCase |= 1;
if (cellData[fVerts[faceIndex][1]] < 0)
fCase |= 2;
if (cellData[fVerts[faceIndex][3]] < 0)
fCase |= 4;
if (cellData[fVerts[faceIndex][2]] < 0)
fCase |= 8;
return fCase;
}
private int getCellCase() {
int cCase = 0;
if (cellData[7] < 0)
cCase |= 1;
if (cellData[6] < 0)
cCase |= 2;
if (cellData[5] < 0)
cCase |= 4;
if (cellData[4] < 0)
cCase |= 8;
if (cellData[3] < 0)
cCase |= 16;
if (cellData[2] < 0)
cCase |= 32;
if (cellData[1] < 0)
cCase |= 64;
if (cellData[0] < 0)
cCase |= 128;
return cCase;
}
}