Package de.venjinx.core

Source Code of de.venjinx.core.CubicalMarchingSquares

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;
    }
}
TOP

Related Classes of de.venjinx.core.CubicalMarchingSquares

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.