Thanks for the suggestion. I tried it out and I still get a crash. Here's a complete program for anyone out there willing to try it. I'd at least like to know if you are getting a crash or not. If you know what I can do to actually fix the problem and post it here, that would be great. In the mean, time, I hope the code is helpful to someone out there.
package jmestuff;
import static java.lang.Math.*;
import java.util.concurrent.Callable;
import com.jme.app.SimplePassGame;
import com.jme.bounding.BoundingSphere;
import com.jme.image.Texture;
import com.jme.input.*;
import com.jme.input.action.*;
import com.jme.intersection.*;
import com.jme.light.PointLight;
import com.jme.math.*;
import com.jme.renderer.*;
import com.jme.renderer.pass.*;
import com.jme.scene.*;
import com.jme.scene.batch.GeomBatch;
import com.jme.scene.shape.*;
import com.jme.scene.state.*;
import com.jme.system.DisplaySystem;
import com.jme.util.*;
public class OccluderAdder extends SimplePassGame
{
private RenderPass renderPass = new RenderPass();
private ShadowedRenderPass shadowPass = new ShadowedRenderPass();
private AbsoluteMouse mouse;
public static void main(String[] args)
{
OccluderAdder app = new OccluderAdder();
app.start();
}
public OccluderAdder()
{
stencilBits = 8;
}
@Override
protected void simpleInitGame()
{
input = new InputHandler();
setupMouse();
//Place 4 tiles here to be our pick targets
for(int i = 0; i < 4; i++)
{
MaterialState mat = DisplaySystem.getDisplaySystem().getRenderer()
.createMaterialState();
mat.setDiffuse(new ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f));
Spatial hex = new Hexagon("HEX_" + i, 1.0f);
hex.setLocalTranslation((float) sin(i * PI * 0.5f), (float) cos(i * PI * 0.5f), 0);
hex.setLocalScale(0.9f);
hex.setRenderState(mat);
hex.setModelBound(new BoundingSphere());
hex.updateModelBound();
rootNode.attachChild(hex);
}
renderPass.add(rootNode);
shadowPass.add(rootNode);
shadowPass.setRenderShadows(true);
shadowPass.setLightingMethod(ShadowedRenderPass.ADDITIVE);
pManager.add(renderPass);
pManager.add(shadowPass);
RenderPass rPass = new RenderPass();
rPass.add(fpsNode);
pManager.add(rPass);
addCube(0.0f, 0.0f);
setupLights();
Vector3f loc = new Vector3f(10, 0, 10);
Vector3f dir = new Vector3f(loc);
dir.negate();
dir.normalize();
Vector3f up = new Vector3f(0, 0, 1);
Vector3f l = up.cross(dir);
l.normalize();
up = dir.cross(l);
cam.setLocation(loc);
cam.setAxes(l, up, dir);
cam.update();
Vector3f lookAt = new Vector3f(2, 0, 0);
cam.setLocation(loc);
cam.lookAt(lookAt, new Vector3f(0, 0, 1));
cam.update();
InputAction clickAction = new InputAction()
{
public void performAction(InputActionEvent evt)
{
// Is button 0 down? Button 0 is left click
if(MouseInput.get().isButtonDown(0))
{
Vector2f screenPos = new Vector2f();
// Get the position that the mouse is pointing to
screenPos.set(mouse.getHotSpotPosition().x, mouse
.getHotSpotPosition().y);
// Get the world location of that X,Y value
Vector3f worldCoords = display.getWorldCoordinates(screenPos, 1.0f);
// Create a ray starting from the camera, and going in the direction
// of the mouse's location
final Ray mouseRay = new Ray(cam.getLocation(), worldCoords
.subtractLocal(cam.getLocation()));
mouseRay.getDirection().normalizeLocal();
pick(mouseRay);
}
}
};
input.addAction(clickAction, InputHandler.DEVICE_MOUSE,
InputHandler.BUTTON_ALL, InputHandler.AXIS_ALL, false);
}
private void setupLights()
{
lightState.detachAll();
PointLight light = new PointLight();
light.setAmbient(new ColorRGBA(0f, 0f, 0f, 1.0f));
light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
light.setEnabled(true);
light.setLocation(new Vector3f(10, 10, 10));
light.setShadowCaster(true);
lightState.attach(light);
light = new PointLight();
light.setAmbient(new ColorRGBA(0f, 0f, 0f, 1.0f));
light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
light.setEnabled(true);
light.setLocation(new Vector3f(-7, -5, 20));
light.setShadowCaster(true);
lightState.attach(light);
lightState.setGlobalAmbient(new ColorRGBA(0.4f, 0.4f, 0.4f, 1.0f));
}
private void addCubeCallable(final float x, final float y)
{
System.out.println("Attempting to add an item centered at " + x + ", " + y + ", 0.5f.");
Callable<?> exe = new Callable() {
public Object call() {
Spatial b = new Box("BOX", new Vector3f(-1, -1, -1), new Vector3f(1, 1, 1));
b.setLocalScale(0.25f);
b.setLocalTranslation(x, y, 0.5f);
b.setModelBound(new BoundingSphere());
b.updateModelBound();
rootNode.attachChild(b);
shadowPass.addOccluder(b);
return null;
}
};
GameTaskQueueManager.getManager()
.getQueue(GameTaskQueue.RENDER).enqueue(exe);
}
private void addCube(float x, float y)
{
Spatial b = new Box("BOX", new Vector3f(-1, -1, -1), new Vector3f(1, 1, 1));
b.setLocalScale(0.25f);
b.setLocalTranslation(x, y, 0.5f);
b.setModelBound(new BoundingSphere());
b.updateModelBound();
rootNode.attachChild(b);
shadowPass.addOccluder(b);
}
private void setupMouse()
{
// Setup software mouse
mouse = new AbsoluteMouse("Mouse Input", display.getWidth(), display
.getHeight());
//mouse.registerWithInputHandler(input);
TextureState cursor = display.getRenderer().createTextureState();
cursor.setTexture(TextureManager.loadTexture(JmeHexViewer.class
.getClassLoader().getResource("textures/cursor1.png"),
Texture.MM_LINEAR, Texture.FM_LINEAR));
mouse.setRenderState(cursor);
AlphaState as1 = display.getRenderer().createAlphaState();
as1.setBlendEnabled(true);
as1.setSrcFunction(AlphaState.SB_SRC_ALPHA);
as1.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
as1.setTestEnabled(true);
as1.setTestFunction(AlphaState.TF_GREATER);
mouse.setRenderState(as1);
mouse.setCullMode(Spatial.CULL_ALWAYS);
MouseInput.get().setHardwareCursor(
JmeHexViewer.class.getClassLoader().getResource(
"textures/cursor1.png"));
// correction due to different hotspot positions between
// hardware/software. not needed when using only hardware etc.
MouseInput.get()
.setCursorPosition(
(int) mouse.getLocalTranslation().x
- mouse.getImageWidth() / 2,
(int) mouse.getLocalTranslation().y
+ mouse.getImageHeight() / 2);
mouse.registerWithInputHandler(input);
rootNode.attachChild(mouse);
}
private void pick(Ray ray)
{
PickResults results = new TrianglePickResults();
results.setCheckDistance(true);
rootNode.findPick(ray, results);
if (results.getNumber() > 0)
{
PickData data = results.getPickData(0);
GeomBatch mesh = data.getTargetMesh();
String name = mesh.getName();
if (name == null && mesh.getParentGeom() != null)
name = mesh.getParentGeom().getName();
System.out.println("Clicked on " + name);
if (name != null)
{
String[] s = name.split("_");
if (s.length == 2)
{
int i= Integer.parseInt(s[1]);
float dx = (float) sin(i * PI * 0.5f);
float dy = (float) cos(i * PI * 0.5f);
addCubeCallable((float) dx, (float) dy);
}
}
}
else
{
System.out.println("Didn't click on anything.");
}
}
@Override
protected void cleanup()
{
super.cleanup();
if ( input != null ) {
input.clearActions();
}
}
}