Package de.venjinx.editor.debug

Source Code of de.venjinx.editor.debug.DebugNode$Voxel

package de.venjinx.editor.debug;

import java.nio.FloatBuffer;
import java.util.HashSet;

import jme3tools.optimize.GeometryBatchFactory;

import com.jme3.bounding.BoundingBox;
import com.jme3.bounding.BoundingSphere;
import com.jme3.bounding.BoundingVolume;
import com.jme3.font.BitmapText;
import com.jme3.math.Triangle;
import com.jme3.math.Vector3f;
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.VertexBuffer.Type;
import com.jme3.scene.debug.Arrow;
import com.jme3.scene.shape.Line;
import com.jme3.scene.shape.Sphere;

import de.venjinx.core.VoxelQuadTree;
import de.venjinx.core.VoxelQuadTree.QuadCases;
import de.venjinx.jme3.VoxelObjectNode;
import de.venjinx.jme3.scenegraph.ScenegraphNode;
import de.venjinx.util.Util;

public class DebugNode extends ScenegraphNode {
    private static class Voxel extends Geometry {
        private float voxelValue;
        private Vector3f position;
        private BitmapText valueText;

        public Voxel(Vector3f pos, float value, float radius) {
            super("VoxelGeometry" + pos + " " + value);
            voxelValue = value;
            position = pos;
            mesh = new Sphere(4, 4, radius);
            if (value < 0)
                setMaterial(DebugMaterials.blackMat);
            else setMaterial(DebugMaterials.whiteMat);
            setLocalTranslation(pos);

            valueText = new BitmapText(DebugMaterials.guiFont, false);
            valueText.setName(pos.toString());
            valueText.setSize(radius);
            int lvl = 0;
            while ((value % Math.pow(2, lvl)) != 0)
                lvl--;
            valueText.setText((int) (value / Math.pow(2, lvl)) + "x2^" + lvl);
            valueText.addControl(DebugMaterials.bc.cloneForSpatial(valueText));
            valueText.setLocalTranslation(pos.add(0, radius * 2, 0));
        }

        @Override
        public int hashCode() {
            int hash = 37;
            hash += (37 * hash) + Float.floatToIntBits(position.x);
            hash += (37 * hash) + Float.floatToIntBits(position.y);
            hash += (37 * hash) + Float.floatToIntBits(position.z);
            hash += (37 * hash) + Float.floatToIntBits(voxelValue);
            return hash;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof Voxel)
                return position.equals(((Voxel) o).position)
                        && (voxelValue == ((Voxel) o).voxelValue);
            else return false;
        }
    }

    private Geometry refGeometry;
    private Mesh refMesh;
    private Node refParent;

    private VoxelObjectNode voxelObject;

    private Geometry bound;
    private ScenegraphNode normals;
    private ScenegraphNode tangents;
    private ScenegraphNode binormals;
    private ScenegraphNode wire;
    private ScenegraphNode voxelGrid;

    private boolean showBound = false;
    private boolean showNormals = false;
    private boolean showWire = false;
    private boolean showVoxelGrid = false;

    public DebugNode(Geometry geometry) {
        setName("Debug '" + geometry.getName() + "'");
        refGeometry = geometry;
        refMesh = geometry.getMesh();
        refParent = geometry.getParent();

        if (geometry.getName().contains("Voxel")) {
            while (!(refParent instanceof VoxelObjectNode))
                refParent = refParent.getParent();
            voxelObject = (VoxelObjectNode) refParent;
        }
    }

    public void showBound() {
        showBound = !showBound;
        if (showBound) {
            if (bound == null)
                bound = buildBound(refGeometry);
            attachChild(bound);
        } else detachChild(bound);
    }

    public void showNormals() {
        showNormals = !showNormals;
        if (showNormals) {
            if (normals == null) {
                if (refMesh.getBuffer(Type.Position) != null) {
                    normals = buildNormals(refGeometry);
                    normals.setLocalTranslation(refGeometry.getLocalTranslation());
                }

                if (refMesh.getBuffer(Type.Tangent) != null) {
                    tangents = buildTangents(refGeometry);
                    tangents.setLocalTranslation(refGeometry.getLocalTranslation());
                }

                if (refMesh.getBuffer(Type.Binormal) != null) {
                    binormals = buildBinormals(refGeometry);
                    binormals.setLocalTranslation(refGeometry.getLocalTranslation());
                }
            }
            attachChild(normals);
            attachChild(tangents);
            attachChild(binormals);
        } else {
            detachChild(normals);
            detachChild(tangents);
            detachChild(binormals);
        }
    }

    public void showWireframe() {
        showWire = !showWire;
        if (showWire) {
            if (wire == null)
                if (refMesh.getMode() == Mode.Triangles) {
                    wire = buildWireframe(refGeometry);
                    wire.setLocalTranslation(refGeometry.getLocalTranslation());
                }
            attachChild(wire);
        } else detachChild(wire);
    }

    public void showVoxelGrid() {
        if (voxelObject != null) {
            showVoxelGrid = !showVoxelGrid;
            if (showVoxelGrid) {
                if (voxelGrid == null) {
                    voxelGrid = buildVoxelGrid(voxelObject);
                    voxelGrid.setLocalTranslation(voxelObject.getLocalTranslation());
                }
                attachChild(voxelGrid);
            } else detachChild(voxelGrid);
        }
    }

    public static ScenegraphNode buildDebugObjects(Geometry refGeom) {
        ScenegraphNode node = new ScenegraphNode("Debug '" + refGeom.getName() + "'");
        ScenegraphNode normals;
        ScenegraphNode tangents;
        ScenegraphNode binormals;
        ScenegraphNode wire;
        ScenegraphNode voxelGrid;

        if ((refGeom != null) && (refGeom.getMesh() != null)) {
            node.attachChild(buildBound(refGeom));

            if (refGeom.getMesh().getBuffer(Type.Position) != null) {
                normals = buildNormals(refGeom);
                normals.setLocalTranslation(refGeom.getLocalTranslation());
                node.attachChild(normals);
            }

            if (refGeom.getMesh().getBuffer(Type.Tangent) != null) {
                tangents = buildTangents(refGeom);
                tangents.setLocalTranslation(refGeom.getLocalTranslation());
                node.attachChild(tangents);
            }

            if (refGeom.getMesh().getBuffer(Type.Binormal) != null) {
                binormals = buildBinormals(refGeom);
                binormals.setLocalTranslation(refGeom.getLocalTranslation());
                node.attachChild(binormals);
            }

            if (refGeom.getMesh().getMode() == Mode.Triangles) {
                wire = buildWireframe(refGeom);
                wire.setLocalTranslation(refGeom.getLocalTranslation());
                node.attachChild(wire);
            }

            if (refGeom.getName().contains("Voxel")) {
                VoxelObjectNode vo;
                Node parent = refGeom.getParent();
                while (!(parent instanceof VoxelObjectNode))
                    parent = parent.getParent();
                vo = (VoxelObjectNode) parent;
                voxelGrid = buildVoxelGrid(vo);
                voxelGrid.setLocalTranslation(vo.getLocalTranslation());
                node.attachChild(voxelGrid);

                vo.showChunkLODs();
                vo.showChunkBounds();
            }
        }
        return node;
    }

    public static Geometry buildBound(Geometry refGeom) {
        BoundingVolume boundVolume = refGeom.getModelBound();
        Geometry g;
        switch (boundVolume.getType()) {
            case AABB:
                BoundingBox bBox = (BoundingBox) boundVolume;
                g = Util.createBox(bBox.getMax(null).subtract(bBox.getMin(null)));
                g.setLocalTranslation(bBox.getMin(null));
                g.setName("Bound");
                g.setMaterial(DebugMaterials.boundMat);
                g.getMesh().setLineWidth(2f);
                return g;
            case Sphere:
                BoundingSphere bSphere = (BoundingSphere) boundVolume;
                Sphere s = new Sphere(8, 8, bSphere.getRadius());
                s.setMode(Mode.Lines);
                g = new Geometry("Bound", s);
                g.setMaterial(DebugMaterials.boundMat);
                g.setLocalRotation(refGeom.getWorldRotation());
                return g;
            default:
                return null;
        }
    }

    public static ScenegraphNode buildNormals(Geometry refGeom) {
        Geometry g;
        Arrow a;
        ScenegraphNode normals = new ScenegraphNode("Normals");
        Vector3f dir = new Vector3f();

        FloatBuffer nB = refGeom.getMesh().getFloatBuffer(Type.Normal);
        FloatBuffer vB = refGeom.getMesh().getFloatBuffer(Type.Position);

        for (int i = 0; i < nB.limit(); i += 3) {
            dir.set(nB.get(i), nB.get(i + 1), nB.get(i + 2));
            a = new Arrow(dir);
            a.setLineWidth(3f);
            g = new Geometry("Normal" + dir, a);
            g.scale(.1f);
            g.setLocalTranslation(vB.get(i), vB.get(i + 1), vB.get(i + 2));
            g.setMaterial(DebugMaterials.normalMat);
            normals.attachChild(g);
        }

        // GeometryBatchFactory.optimize(normals);
        return normals;
    }

    public static ScenegraphNode buildTangents(Geometry refGeom) {
        Geometry g;
        Arrow a;
        ScenegraphNode tangents = new ScenegraphNode("Tangents");
        Vector3f dir = new Vector3f();

        FloatBuffer tB = refGeom.getMesh().getFloatBuffer(Type.Tangent);
        FloatBuffer vB = refGeom.getMesh().getFloatBuffer(Type.Position);

        int posFix = 0;
        for (int i = 0; i < tB.limit(); i += 4) {
            dir.set(tB.get(i), tB.get(i + 1), tB.get(i + 2)).normalizeLocal();
            a = new Arrow(dir);
            a.setLineWidth(2f);
            g = new Geometry("Tangent" + dir, a);
            g.scale(.1f);
            g.setLocalTranslation(vB.get(i - posFix), vB.get((i - posFix) + 1),
                                  vB.get((i - posFix) + 2));
            g.setMaterial(DebugMaterials.tangentMat);
            tangents.attachChild(g);
            posFix++;
        }

        // GeometryBatchFactory.optimize(tangents);
        return tangents;
    }

    public static ScenegraphNode buildBinormals(Geometry refGeom) {
        Geometry g;
        Arrow a;
        ScenegraphNode binormals = new ScenegraphNode("Binormals");
        Vector3f dir = new Vector3f();

        FloatBuffer bnB = refGeom.getMesh().getFloatBuffer(Type.Binormal);
        FloatBuffer vB = refGeom.getMesh().getFloatBuffer(Type.Position);

        for (int i = 0; i < bnB.limit(); i += 3) {
            dir.set(bnB.get(i), bnB.get(i + 1), bnB.get(i + 2));
            a = new Arrow(dir);
            g = new Geometry("Binormal" + dir, a);
            g.scale(.1f);
            g.setLocalTranslation(vB.get(i), vB.get(i + 1), vB.get(i + 2));
            g.setMaterial(DebugMaterials.binormalMat);
            binormals.attachChild(g);
        }

        // GeometryBatchFactory.optimize(binormals);
        return binormals;
    }

    public static ScenegraphNode buildWireframe(Geometry refGeom) {
        Line line;
        Triangle tri;
        Geometry g;
        ScenegraphNode tris = new ScenegraphNode("Wireframe");
        for (int i = 0; i < refGeom.getMesh().getTriangleCount(); i++) {
            tri = new Triangle();
            refGeom.getMesh().getTriangle(i, tri);

            // bc = new BillboardControl();
            // helloText = new BitmapText(guiFont, false);
            // helloText.setSize(.05f);
            // helloText.setText("tri" + i);
            // helloText.setLocalTranslation(tri.getCenter());
            // helloText.addControl(bc);
            // myApp.getRootNode().attachChild(helloText);

            line = new Line(tri.get1(), tri.get2());
            g = new Geometry("Line" + tri.get1() + "->" + tri.get2(), line);
            g.setMaterial(DebugMaterials.wireMat);
            tris.attachChild(g);

            line = new Line(tri.get2(), tri.get3());
            g = new Geometry("Line" + tri.get2() + "->" + tri.get3(), line);
            g.setMaterial(DebugMaterials.wireMat);
            tris.attachChild(g);

            line = new Line(tri.get3(), tri.get1());
            g = new Geometry("Line" + tri.get3() + "->" + tri.get1(), line);
            g.setMaterial(DebugMaterials.wireMat);
            tris.attachChild(g);
        }
        GeometryBatchFactory.optimize(tris);
        return tris;
    }

    public static Node buildVertIds(Geometry refGeom) {
        Node node = new Node("vertIds");
        BitmapText vertId;
        Vector3f pos = new Vector3f();

        FloatBuffer fb = refGeom.getMesh().getFloatBuffer(Type.Position);
        for (int i = 0; i < fb.capacity(); i += 3) {
            pos.set(fb.get(i), fb.get(i + 1), fb.get(i + 2));
            vertId = new BitmapText(DebugMaterials.guiFont);
            vertId.setSize(.1f);
            vertId.setText("v " + (i / 3) + " " + pos);
            vertId.setName("VertID" + (i / 3) + " label - " + pos);
            vertId.setLocalTranslation(pos);
            vertId.addControl(DebugMaterials.bc.cloneForSpatial(vertId));
            node.attachChild(vertId);
        }
        return node;
    }

    public static ScenegraphNode buildVoxelGrid(VoxelObjectNode voxelObjectNode) {
        ScenegraphNode voxelGrid =
                new ScenegraphNode("Voxel grid " + voxelObjectNode.getName());
        ScenegraphNode voxelNode = new ScenegraphNode("Voxels");
        ScenegraphNode labelNode = new ScenegraphNode("Voxel labels");
        float[][][] data = voxelObjectNode.getData();

        HashSet<Voxel> voxels = new HashSet<>();

        // for (long quad : geometry.getFaceIDs()) {
        // // tree = new VoxelQuadTree(quad, geometry.getLOD(),
        // // geometry.getZipKey(), geometry.getVoxelData());
        // tree = new VoxelQuadTree(quad, geometry, data);
        // if ((tree.quadCase > 0) && (tree.quadCase < (QuadCases.caseCount() -
        // 1)))
        // buildTreeVoxels(tree, voxels);
        // }

        for (Voxel v : voxels) {
            voxelNode.attachChild(v);
            labelNode.attachChild(v.valueText);
        }
        GeometryBatchFactory.optimize(voxelNode);

        voxelGrid.attachChild(voxelNode);
        voxelGrid.attachChild(labelNode);
        return voxelGrid;
    }

    private static void buildTreeVoxels(VoxelQuadTree tree, HashSet<Voxel> voxels) {
        if (tree.isLeaf())
            buildLeafVoxels(tree, voxels);
        else {
            buildTreeVoxels(tree.getBottomLeftTree(), voxels);
            buildTreeVoxels(tree.getBottomRightTree(), voxels);
            buildTreeVoxels(tree.getTopRightTree(), voxels);
            buildTreeVoxels(tree.getTopLeftTree(), voxels);
        }
    }

    private static void buildLeafVoxels(VoxelQuadTree leaf, HashSet<Voxel> voxels) {
        float[] data = leaf.getLeafData();
        Vector3f pos = new Vector3f(leaf.getX(), leaf.getY(), leaf.getZ());

        if ((leaf.quadCase > 0) && (leaf.quadCase < (QuadCases.caseCount() - 1))) {
            Voxel voxel = new Voxel(pos.add(0, 0, leaf.size), data[0], leaf.size / 5);
            voxels.add(voxel);
            voxel = new Voxel(pos.add(leaf.size, 0, leaf.size), data[1], leaf.size / 5);
            voxels.add(voxel);
            voxel = new Voxel(pos.add(leaf.size, 0, 0), data[2], leaf.size / 5);
            voxels.add(voxel);
            voxel = new Voxel(pos.add(0, 0, 0), data[3], leaf.size / 5);
            voxels.add(voxel);
        }
    }
}
TOP

Related Classes of de.venjinx.editor.debug.DebugNode$Voxel

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.