@author Naas
*/
public class ObjectPixelProcessor implements SceneProcessor, CameraChangedListener {
private FrameBuffer tempBuffer;
private ViewPort viewPort;
private Renderer renderer;
private RenderManager renderManager;
private ByteBuffer copyBuffer;
private byte[] copyArray;
private final static int waitUpdateMillis = 100;
private long markOutdatedTime = 0;
private boolean forceUpdate = false;
private Texture2D offTex;
private int width;
private int height;
private boolean selectionEnabled;
private ColorRGBA tempColor = new ColorRGBA();
/**
- Start Value 1 makes sure that id 0 can be used to ignore all unselectable
- Objects
*/
private int highestFreeId = 1;
private Queue freeIds = new LinkedList();
private Map selectableIdGeometryMap = new HashMap();
private Map selectableGeometryIdMap = new HashMap();
private Set unSelectableGeometries = new HashSet();
private Material idMaterial;
//private Main main;
/**
- Adds a Geometry which can be selected if the Geometry is already added as
- Unselectable Geometry it is removed from the Unselectable Geometries List
-
-
@param e
*/
public void addSelectableGeometry(Geometry e) {
if (!selectableGeometryIdMap.containsKey(e)) {
if (unSelectableGeometries.contains(e)) {
unSelectableGeometries.remove(e);
}
int id = createId();
selectableIdGeometryMap.put(id, e);
selectableGeometryIdMap.put(e, id);
}
}
public void removeSelectableGeometry(Geometry o) {
int id = selectableGeometryIdMap.get(o);
selectableGeometryIdMap.remove(o);
selectableIdGeometryMap.remove(id);
destroyId(id);
}
private int createId() {
if (!freeIds.isEmpty()) {
return freeIds.poll();
} else {
highestFreeId++;
return highestFreeId - 1;
}
}
private void destroyId(int id) {
if (id == highestFreeId - 1 && id > 1) {
highestFreeId–;
} else {
freeIds.add(id);
}
}
/**
- Adds a Geometry as Unselectable which means it cannot be selected and it
- prevents other Geometries from being selected if they are behind of this
- Geometry if the Geometry is already added as selectable Geometry it is
- removed from the selectable Geometries List
-
-
@param e
*/
public void addUnSelectableGeometry(Geometry e) {
if (!unSelectableGeometries.contains(e)) {
if (selectableGeometryIdMap.containsKey(e)) {
removeSelectableGeometry(e);
}
unSelectableGeometries.add(e);
}
}
public void removeUnSelectableGeometry(Geometry o) {
unSelectableGeometries.remove(o);
}
public ObjectPixelProcessor(RenderManager rm, Renderer renderer, ViewPort viewPort, AssetManager assetManager) {
this.renderManager = rm;
this.renderer = renderer;
this.viewPort = viewPort;
viewPort.addProcessor(this);
idMaterial = new Material(assetManager, "MatDefs/Colorid.j3md");
}
public boolean isNeedUpdate() {
return (markOutdatedTime > 0 ? (System.currentTimeMillis() - markOutdatedTime > waitUpdateMillis && selectionEnabled) : false) || forceUpdate;
}
public void initialize(RenderManager rm, ViewPort vp) {
}
public void reshape(ViewPort vp, int w, int h) {
reshape(vp);
}
public void reshape(ViewPort vp) {
this.viewPort = vp;
height = vp.getCamera().getHeight();
width = vp.getCamera().getWidth();
copyBuffer = BufferUtils.createByteBuffer(width * height * 4);
copyArray = new byte[width * height * 4];
tempBuffer = new FrameBuffer(width, height, 0);
tempBuffer.setDepthBuffer(Image.Format.Depth);
tempBuffer.setColorBuffer(Image.Format.RGBA8);
offTex = new Texture2D(width, height, Image.Format.RGBA8);
offTex.setMinFilter(Texture.MinFilter.Trilinear);
offTex.setMagFilter(Texture.MagFilter.Bilinear);
tempBuffer.setDepthBuffer(Image.Format.Depth);
tempBuffer.setColorTexture(offTex);
}
public boolean isInitialized() {
return true;
}
public void preFrame(float tpf) {
}
/**
*Call when Scene or Camera has changed
*/
public void markAsOutdated() {
markOutdatedTime = System.currentTimeMillis();
}
public void postQueue(RenderQueue rq) {
if (isNeedUpdate()) {
renderManager.getRenderer().setBackgroundColor(ColorRGBA.BlackNoAlpha);
renderManager.getRenderer().setFrameBuffer(tempBuffer);
renderManager.getRenderer().clearBuffers(true, true, true);
Material tempMat;
for (Iterator it = this.selectableGeometryIdMap.keySet().iterator(); it.hasNext();) {
Geometry selectableGeometry = it.next();
int selectableGeometryId = selectableGeometryIdMap.get(selectableGeometry);
tempMat = selectableGeometry.getMaterial();
if (tempMat.getAdditionalRenderState().isWireframe()) {
idMaterial.getAdditionalRenderState().setWireframe(true);
} else {
idMaterial.getAdditionalRenderState().setWireframe(false);
}
selectableGeometry.setMaterial(idMaterial);
tempColor.fromIntRGBA(selectableGeometryId);
idMaterial.setColor("objectIdColor", tempColor);
renderManager.renderGeometry(selectableGeometry);
selectableGeometry.setMaterial(tempMat);
}
tempColor.fromIntRGBA(0);
idMaterial.setColor("objectIdColor", tempColor);
for (Iterator it = this.unSelectableGeometries.iterator(); it.hasNext();) {
Geometry unselectableGeometry = it.next();
tempMat = unselectableGeometry.getMaterial();
if (tempMat.getAdditionalRenderState().isWireframe()) {
idMaterial.getAdditionalRenderState().setWireframe(true);
} else {
idMaterial.getAdditionalRenderState().setWireframe(false);
}
unselectableGeometry.setMaterial(idMaterial);
renderManager.renderGeometry(unselectableGeometry);
unselectableGeometry.setMaterial(tempMat);
}
renderManager.getRenderer().setFrameBuffer(this.viewPort.getOutputFrameBuffer());
renderer.readFrameBuffer(tempBuffer, copyBuffer);
copyBuffer.get(copyArray);
copyBuffer.clear();
markOutdatedTime = 0;
forceUpdate = false;
}
}
public void forceUpdate() {
forceUpdate = true;
}
public void postFrame(FrameBuffer out) {
}
public Geometry getGeometryAt(int x, int y) {
int id = getIdAt(x, y);
if (id == 0) {
return null;
} else {
Geometry geom = selectableIdGeometryMap.get(id);
if (geom != null) {
return geom;
} else {
throw new UnsupportedOperationException("There is no Geometry with id '" + id + "'");
}
}
}
private int getIdAt(int x, int y) {
if ((x >= 0 && x = 0 && y < height)) {
int index = 4 * (y * width + x);
int id = ((copyArray[index + 2] & 0xFF) << 24)
| ((copyArray[index + 1] & 0xFF) << 16)
| ((copyArray[index + 0] & 0xFF) << 8)
| ((copyArray[index + 3] & 0xFF));
return id;
} else {
throw new UnsupportedOperationException("Pixel Coordinates ("+x+","+y+") are out of Bounds ("+width+","+height+") viewPort:'"+viewPort+"'");
}
}
public void getPixelColor(int x, int y) {
}
public void cleanup() {
}
public void onCameraChanged() {
this.markAsOutdated();
}
public boolean isSelectionEnabled() {
return selectionEnabled;
}
public void setSelectionEnabled(boolean selectionEnabled) {
this.selectionEnabled = selectionEnabled;
}
}
[/java]