package net.cis.client.game.model;
import java.util.ArrayList;
import net.cis.client.game.common.model.co.AbstractControlledObject;
import net.cis.client.game.common.util.GlobalObjectStore;
import com.jme3.asset.AssetManager;
import com.jme3.bounding.BoundingBox;
import com.jme3.bounding.BoundingSphere;
import com.jme3.bounding.BoundingVolume;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapFont.Align;
import com.jme3.font.BitmapFont.VAlign;
import com.jme3.font.BitmapText;
import com.jme3.font.Rectangle;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.Camera.FrustumIntersect;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Line;
public class DebugNode extends Node
{
private final AbstractControlledObject<?, ?> co;
private final BoundingVolume bv;
private final Camera cam;
protected final static float updateTime = 1/60f;
float lastUpdate = 2;
private BitmapText t;
private Line top, bottom, left, right;
private Vector3f bl= new Vector3f(), br= new Vector3f(), tl= new Vector3f(), tr= new Vector3f();
private final Material lineMaterial;
private ArrayList<Vector3f> points = new ArrayList<Vector3f>(8);
private Vector3f extend = new Vector3f(), center = new Vector3f();
public DebugNode(Camera cam, AbstractControlledObject<?, ?> co, BoundingVolume bv)
{
super("DebugNode-"+co);
this.cam = cam;
this.co = co;
this.bv = bv;
lineMaterial= new Material(GlobalObjectStore.<AssetManager>getObject(AssetManager.class), "Common/MatDefs/Misc/Unshaded.j3md");
lineMaterial.setColor("Color", ColorRGBA.Green);
top = createLine(tl, tr, true);
left = createLine(tl, bl, true);
right = createLine(tr, br, true);
bottom = createLine(br, bl, true);
BitmapFont myFont = GlobalObjectStore.<AssetManager>getObject(AssetManager.class).loadFont("Interface/Fonts/Console.fnt");
t = new BitmapText(myFont, false);
t.setColor(ColorRGBA.Pink);
t.setBox(new Rectangle(0, 0, 100, 100));
t.setAlignment(Align.Left);
t.setVerticalAlignment(VAlign.Top);
t.setLocalTranslation(0, 0, 2);
this.attachChild(createLineGeometry(top));
this.attachChild(createLineGeometry(left));
this.attachChild(createLineGeometry(right));
this.attachChild(createLineGeometry(bottom));
this.attachChild(t);
}
protected void addLine(Vector3f start, Vector3f end)
{
addLine(start, end, true);
}
protected void addLine(Vector3f start, Vector3f end, boolean isGlobal)
{
this.attachChild(createLineGeometry(createLine(start, end, isGlobal)));
}
protected Line createLine(Vector3f start, Vector3f end, boolean isGlobal)
{
Line l = new Line(isGlobal ? cam.getScreenCoordinates(start) : start, isGlobal ? cam.getScreenCoordinates(end) : end);
l.setLineWidth(2);
return l;
}
protected Geometry createLineGeometry(Line l)
{
Geometry g = new Geometry("DebugLine", l);
g.setMaterial(lineMaterial);
return g;
}
@Override
public void updateLogicalState(float tpf)
{
lastUpdate -= tpf;
if(lastUpdate > 0)
return;
lastUpdate += updateTime;
if (cam.contains(bv) == FrustumIntersect.Outside)
{
this.setCullHint(CullHint.Always);
return;
}
this.setCullHint(CullHint.Inherit);
bv.getCenter(center);
switch (bv.getType())
{
case OBB:
case AABB:
BoundingBox aabb = (BoundingBox)bv;
aabb.getExtent(extend);
break;
case Sphere:
BoundingSphere bs = (BoundingSphere)bv;
float f = bs.getRadius();
extend.set(f, f, f);
break;
default:
extend.set(1f,1f,1f);
}
points.clear();
points.add(cam.getScreenCoordinates(new Vector3f(center.x + extend.x, center.y + extend.y, center.z + extend.z)));
points.add(cam.getScreenCoordinates(new Vector3f(center.x + extend.x, center.y - extend.y, center.z + extend.z)));
points.add(cam.getScreenCoordinates(new Vector3f(center.x - extend.x, center.y + extend.y, center.z + extend.z)));
points.add(cam.getScreenCoordinates(new Vector3f(center.x - extend.x, center.y - extend.y, center.z + extend.z)));
points.add(cam.getScreenCoordinates(new Vector3f(center.x + extend.x, center.y + extend.y, center.z - extend.z)));
points.add(cam.getScreenCoordinates(new Vector3f(center.x + extend.x, center.y - extend.y, center.z - extend.z)));
points.add(cam.getScreenCoordinates(new Vector3f(center.x - extend.x, center.y + extend.y, center.z - extend.z)));
points.add(cam.getScreenCoordinates(new Vector3f(center.x - extend.x, center.y - extend.y, center.z - extend.z)));
float xMin = Float.MAX_VALUE, xMax = Float.MIN_VALUE, yMin = Float.MAX_VALUE, yMax = Float.MIN_VALUE;
for(Vector3f p : points)
{
xMin = Math.min(xMin, p.x);
xMax = Math.max(xMax, p.x);
yMin = Math.min(yMin, p.y);
yMax = Math.max(yMax, p.y);
}
tl.x = xMin; tl.y = yMax;
tr.x = xMax; tr.y = yMax;
bl.x = xMin; bl.y = yMin;
br.x = xMax; br.y = yMin;
top.updatePoints(tl, tr);
left.updatePoints(tl, bl);
right.updatePoints(tr, br);
bottom.updatePoints(bl, br);
// draw frame only
// detachAllChildren();
// addLine(new Vector3f(xMin, yMin, 1), new Vector3f(xMax, yMin, 1), false);
// addLine(new Vector3f(xMin, yMin, 1), new Vector3f(xMin, yMax, 1), false);
// addLine(new Vector3f(xMax, yMax, 1), new Vector3f(xMax, yMin, 1), false);
// addLine(new Vector3f(xMax, yMax, 1), new Vector3f(xMin, yMax, 1), false);
// draw bounding box
// detachAllChildren();
// addLine(new Vector3f(center.x + extend.x, center.y + extend.y, center.z + extend.z), new Vector3f(center.x - extend.x, center.y + extend.y, center.z + extend.z));
// addLine(new Vector3f(center.x + extend.x, center.y + extend.y, center.z + extend.z), new Vector3f(center.x + extend.x, center.y - extend.y, center.z + extend.z));
// addLine(new Vector3f(center.x + extend.x, center.y + extend.y, center.z + extend.z), new Vector3f(center.x + extend.x, center.y + extend.y, center.z - extend.z));
//
// addLine(new Vector3f(center.x - extend.x, center.y - extend.y, center.z + extend.z), new Vector3f(center.x + extend.x, center.y - extend.y, center.z + extend.z));
// addLine(new Vector3f(center.x - extend.x, center.y - extend.y, center.z + extend.z), new Vector3f(center.x - extend.x, center.y + extend.y, center.z + extend.z));
// addLine(new Vector3f(center.x - extend.x, center.y - extend.y, center.z + extend.z), new Vector3f(center.x - extend.x, center.y - extend.y, center.z - extend.z));
//
// addLine(new Vector3f(center.x - extend.x, center.y + extend.y, center.z - extend.z), new Vector3f(center.x + extend.x, center.y + extend.y, center.z - extend.z));
// addLine(new Vector3f(center.x - extend.x, center.y + extend.y, center.z - extend.z), new Vector3f(center.x - extend.x, center.y - extend.y, center.z - extend.z));
// addLine(new Vector3f(center.x - extend.x, center.y + extend.y, center.z - extend.z), new Vector3f(center.x - extend.x, center.y + extend.y, center.z + extend.z));
//
// addLine(new Vector3f(center.x + extend.x, center.y - extend.y, center.z - extend.z), new Vector3f(center.x - extend.x, center.y - extend.y, center.z - extend.z));
// addLine(new Vector3f(center.x + extend.x, center.y - extend.y, center.z - extend.z), new Vector3f(center.x + extend.x, center.y + extend.y, center.z - extend.z));
// addLine(new Vector3f(center.x + extend.x, center.y - extend.y, center.z - extend.z), new Vector3f(center.x + extend.x, center.y - extend.y, center.z + extend.z));
String text = co.getDebugDisplay();
float width = Math.min(tr.x, cam.getWidth())-Math.max(tl.x, 0);
if(width < 5 * text.length() && width < 50)
t.setCullHint(CullHint.Always);
else
{
t.setCullHint(CullHint.Inherit);
t.setBox(new Rectangle((int)Math.max(tl.x, 0), (int)tl.y + 25, width, 25));
t.setText(text);
}
super.updateLogicalState(tpf);
}
}