Selection Box

Is there any easy way to show a selection box around an object?

Like maybe displaying the bounding box or simaliar?

A question to the code above:

TexCoords , why is this class missing (in my jme) :?



LightCombineMode.Off ;Mode.Strip,this.setVertexBuffer,this.setColorBuffer etc didn't work either



i have got the cvs jme2 version of cvs.dev.java.net









@problem above: i do it with  find pick:


         PickResults results = new BoundingPickResults();
        results.setCheckDistance(true);
        //scene: nodes where all the selectable things hang on
        scene.findPick(ray,results);

        if(results.getNumber() > 0) {
           int i = 0;
               float distance=results.getPickData(i).getDistance();
               if(distance<110) {
                         //cast to my own node
                  CreatureModel creature= (CreatureModel) results.getPickData(i).getTargetMesh().getParentGeom().getParent().getParent().getParent();
                  //tell the node it is selected, there you can add bloom effect, lights, boxes, texts, etc.
                      creature.setSelected(true);
                       //change cursor
                  cursor=cursor0;cursorType=CursorType.FIGHT;}
   
        }

You mean once you've clicked on a selectable object, like an enemy?

yes

I have no clue. When you find out, tell me. I'll be needing that rather soon!  :smiley:

Without attaching any geometry, you could use another renderpass to render the object in a way to indicate it is selected. I guess you could render the bounding box in the pass. I haven't done that exactly, but Scene Monitor uses a render pass to highlight items in the scene that have been selected. Its a place to start at least.

What would be awesome (but not compatible on low-end machines) is to bloom the selected object. Make it really intense, so it's glowing. That would be sweet…

Ahh… finally found TerrainMarker. It’s from MonkeyWorld3d

http://monkeyworld3d.cvs.sourceforge.net/checkout/monkeyworld3d/monkeyworld3d/src/com/mw3d/core/spatial/TerrainMarker.java?revision=1.2





Here is the code modified to work with jME2.0



EDIT: I don’t think its working…



EDIT: Okay it compiles now, but the highlighting is a little funky - need to fix it…



EDIT: Works now, just forgot to set it to a triangle strip



/*
* Copyright (c) 2005 MonkeyWorld3d - Monkey World 3d
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Monkey World 3d, MW3D, MonkeyWorld3d, nor the
*    names of its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import com.jme.math.FastMath;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.TexCoords;
import com.jme.scene.TriMesh;
import com.jme.util.geom.BufferUtils;
import com.jmex.terrain.TerrainPage;

/**
 * This is a class which will be used to mark the terrain cursor position.
 * I will try to create a circle with some radius.
 *
 * @author ndebruyn
 * Created on May 31, 2005
 */
public class TerrainMarker extends TriMesh {

   private static final long serialVersionUID = 1L;
   private int radialSamples;
   private float radius;
   private float ringWidth;
   private ColorRGBA colorRGBA;
   private Vector3f[] vertex;
   private Vector3f[] normal;
   private ColorRGBA[] color;
   private Vector2f[][] texture;
   private int[] indices;


   public TerrainMarker(String name, int radialSamples, float radius, float ringWidth, ColorRGBA colorRGBA) {
      super(name);

      this.radialSamples = radialSamples;
      this.radius = radius;
      this.ringWidth = ringWidth;
      this.colorRGBA = colorRGBA;

      texture = new Vector2f[1][];
      // allocate vertices
      int quantity = ((radialSamples+1) * 2);
      vertex = new Vector3f[quantity];
      normal = new Vector3f[quantity];
      color = new ColorRGBA[quantity];
      texture[0] = new Vector2f[quantity];
      
      int indexQuantity = radialSamples * (6);
      indices = new int[indexQuantity];

      setGeometryData();
      setColorData();
      setIndexData();
      this.setLightCombineMode(LightCombineMode.Off);
      this.setTextureCombineMode(TextureCombineMode.Off);
      
      this.setMode(Mode.Strip);
   }

   private void setGeometryData() {
      // generate geometry
      float f1 = 1.0F / (float)radialSamples;
      int c = 0;
      for (int r=0; r<radialSamples+1; r++) {
   
         float f2 = FastMath.TWO_PI * (f1 * (float)r);
         if (r == radialSamples) {
            f2 = FastMath.TWO_PI * (f1 * (float)0);
         }
         //Outsize
         float x = radius * FastMath.cos(f2);
         float z = radius * FastMath.sin(f2);
         float y = 0.0F;
         Vector3f vector3f2out = new Vector3f(x, y, z);
         
         //Insize
         x = (radius-(ringWidth)) * FastMath.cos(f2);
         z = (radius-(ringWidth)) * FastMath.sin(f2);
         y = 0.0F;
         Vector3f vector3f2in = new Vector3f(x, y, z);
         vertex[c] = vector3f2out;
         c++;
         vertex[c] = vector3f2in;
         c++;
      }       
      this.setVertexBuffer(BufferUtils.createFloatBuffer(vertex));
      this.setColorBuffer(BufferUtils.createFloatBuffer(color));
      this.setVertexBuffer(BufferUtils.createFloatBuffer(normal));
      this.setTextureCoords(new TexCoords(BufferUtils.createFloatBuffer(texture[0]), 0));
   }

   private void setIndexData() {
      // generate connectivity
       int c = 0;
       int t = 0;
      for (; t < indices.length; t=t+3) {
          indices[t] = c;
          indices[t+1] = c+1;
          indices[t+2] = c+2;
          c++;
      }
      this.setIndexBuffer(BufferUtils.createIntBuffer(indices));
   }

   private void setColorData() {
      for (int x = 0; x < color.length; x++) {
         color[x] = colorRGBA;
      }
      this.setColorBuffer(BufferUtils.createFloatBuffer(color));
   }
    
    /**
     * We need to update the marker position.
     */
    public void update(Vector3f midPoint, TerrainPage page) {
        setLocalTranslation(midPoint);        
        float x = getLocalTranslation().x;
        float y = getLocalTranslation().y;
        float z = getLocalTranslation().z;
        float newY;
        float incrMent = 0.3F;
        float oldY = 0.0F;
        
        for (int t=0; t<vertex.length; t++) {
            newY = page.getHeight(x+vertex[t].x, z+vertex[t].z);
            //I the value is a NaN set it to be 0.0F
            if (Float.isNaN(newY) || newY > radius+y) {
                vertex[t].y = (oldY-y) + incrMent;
           } else {
                vertex[t].y = (newY-y) + incrMent;
                oldY = newY;
            }
        }
        reconstruct(vertex, normal, color, texture[0]);
        updateGeometricState(0.0F, true);
    }
    
    private void reconstruct(Vector3f[] vertex2, Vector3f[] normal2,
         ColorRGBA[] color2, Vector2f[] vector2fs) {
      // TODO Auto-generated method stub
      super.reconstruct(BufferUtils.createFloatBuffer(vertex),
            BufferUtils.createFloatBuffer(normal),
            BufferUtils.createFloatBuffer(color),
            new TexCoords(BufferUtils.createFloatBuffer(texture[0]), 0));
   }

   public void reset(ColorRGBA colorRGBA, float radius) {
        if (colorRGBA != null)
            this.colorRGBA = colorRGBA;
        
        this.radius = radius;
        setGeometryData();
        setColorData();
        reconstruct(vertex, normal, color, texture[0]);
        updateGeometricState(0.0F, true);
    }
    public float getRadius() {
        return radius;
    }
}



and a test:



import java.util.HashMap;

import javax.swing.ImageIcon;

import jmetest.input.TestThirdPersonController;
import jmetest.terrain.TestTerrain;

import com.jme.app.SimpleGame;
import com.jme.app.AbstractGame.ConfigShowMode;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.ChaseCamera;
import com.jme.input.ThirdPersonHandler;
import com.jme.light.DirectionalLight;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.RenderPass;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.state.CullState;
import com.jme.scene.state.FogState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.FaultFractalHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;

public class TerrainMarkerTest extends SimpleGame{

    private Node m_character;

    private ChaseCamera chaser;

    private TerrainPage page;
    private TerrainMarker characterMarker;

    public static void main(String[] args) {
       TerrainMarkerTest app = new TerrainMarkerTest();
        app.setConfigShowMode(ConfigShowMode.AlwaysShow);
        app.start();
    }
    
   @Override
   protected void simpleInitGame() {
      // TODO Auto-generated method stub
        setupCharacter();
        setupTerrain();
        setupChaseCamera();
        setupInput();
        
        characterMarker = new TerrainMarker("charMarker", 5,
              10f,//((BoundingBox)m_character.getWorldBound()).xExtent,
              2f, ColorRGBA.green);
        rootNode.attachChild(characterMarker);
        //setupJoystick();
   }
   protected void simpleUpdate() {
        chaser.update(tpf);
        float camMinHeight = page.getHeight(cam.getLocation()) + 2f;
        if (!Float.isInfinite(camMinHeight) && !Float.isNaN(camMinHeight)
                && cam.getLocation().y <= camMinHeight) {
            cam.getLocation().y = camMinHeight;
            cam.update();
        }

        float characterMinHeight = page.getHeight(m_character
                .getLocalTranslation())+((BoundingBox)m_character.getWorldBound()).yExtent;
        if (!Float.isInfinite(characterMinHeight) && !Float.isNaN(characterMinHeight)) {
            m_character.getLocalTranslation().y = characterMinHeight;
        }
        characterMarker.update(m_character.getWorldTranslation(), page);
    }

    private void setupCharacter() {
        Box b = new Box("box", new Vector3f(), 5,5,5);
        b.setModelBound(new BoundingBox());
        b.updateModelBound();
        m_character = new Node("char node");
        rootNode.attachChild(m_character);
        m_character.attachChild(b);
        m_character.updateWorldBound(); // We do this to allow the camera setup access to the world bound in our setup code.

        TextureState ts = display.getRenderer().createTextureState();
        ts.setEnabled(true);
        ts.setTexture(
            TextureManager.loadTexture(
            TestThirdPersonController.class.getClassLoader().getResource(
            "jmetest/data/images/Monkey.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear));
        m_character.setRenderState(ts);
    }
    
    private void setupTerrain() {
        rootNode.setRenderQueueMode(Renderer.QUEUE_OPAQUE);

        display.getRenderer().setBackgroundColor(
                new ColorRGBA(0.5f, 0.5f, 0.5f, 1));

        DirectionalLight dr = new DirectionalLight();
        dr.setEnabled(true);
        dr.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        dr.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
        dr.setDirection(new Vector3f(0.5f, -0.5f, 0));

        CullState cs = display.getRenderer().createCullState();
        cs.setCullFace(CullState.Face.Back);
        cs.setEnabled(true);
        rootNode.setRenderState(cs);

        lightState.detachAll();
        lightState.attach(dr);

        FaultFractalHeightMap heightMap = new FaultFractalHeightMap(257, 32, 0,
                255, 0.75f);
        Vector3f terrainScale = new Vector3f(10, 1, 10);
        heightMap.setHeightScale(0.001f);
        page = new TerrainPage("Terrain", 33, heightMap.getSize(),
                terrainScale, heightMap.getHeightMap(), false);

        page.setDetailTexture(1, 16);
        rootNode.attachChild(page);

        ProceduralTextureGenerator pt = new ProceduralTextureGenerator(
                heightMap);
        pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
                .getResource("jmetest/data/texture/grassb.png")), -128, 0, 128);
        pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
                .getResource("jmetest/data/texture/dirt.jpg")), 0, 128, 255);
        pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
                .getResource("jmetest/data/texture/highest.jpg")), 128, 255,
                384);

        pt.createTexture(512);

        TextureState ts = display.getRenderer().createTextureState();
        ts.setEnabled(true);
        Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(),
                Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
        ts.setTexture(t1, 0);

        Texture t2 = TextureManager.loadTexture(TestThirdPersonController.class
                .getClassLoader()
                .getResource("jmetest/data/texture/Detail.jpg"),
                Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear);
        ts.setTexture(t2, 1);
        t2.setWrap(Texture.WrapMode.Repeat);

        t1.setApply(Texture.ApplyMode.Combine);
        t1.setCombineFuncRGB(Texture.CombinerFunctionRGB.Modulate);
        t1.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
        t1.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
        t1.setCombineSrc1RGB(Texture.CombinerSource.PrimaryColor);
        t1.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);

        t2.setApply(Texture.ApplyMode.Combine);
        t2.setCombineFuncRGB(Texture.CombinerFunctionRGB.AddSigned);
        t2.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
        t2.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
        t2.setCombineSrc1RGB(Texture.CombinerSource.Previous);
        t2.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
        rootNode.setRenderState(ts);

        FogState fs = display.getRenderer().createFogState();
        fs.setDensity(0.5f);
        fs.setEnabled(true);
        fs.setColor(new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f));
        fs.setEnd(1000);
        fs.setStart(500);
        fs.setDensityFunction(FogState.DensityFunction.Linear);
        fs.setQuality(FogState.Quality.PerVertex);
        rootNode.setRenderState(fs);
    }

    private void setupChaseCamera() {
        Vector3f targetOffset = new Vector3f();
        targetOffset.y = ((BoundingBox) m_character.getWorldBound()).yExtent * 1.5f;
        chaser = new ChaseCamera(cam, m_character);
        chaser.setTargetOffset(targetOffset);
    }

    private void setupInput() {
        HashMap<String, Object> handlerProps = new HashMap<String, Object>();
        handlerProps.put(ThirdPersonHandler.PROP_DOGRADUAL, "true");
        handlerProps.put(ThirdPersonHandler.PROP_TURNSPEED, ""+(1.0f * FastMath.PI));
        handlerProps.put(ThirdPersonHandler.PROP_LOCKBACKWARDS, "false");
        handlerProps.put(ThirdPersonHandler.PROP_CAMERAALIGNEDMOVE, "true");
        input = new ThirdPersonHandler(m_character, cam, handlerProps);
        input.setActionSpeed(100f);
    }
}

TerrainMaker has highlighting or…?



I know a very used way today is by having a shader do a line draw around a selected object - if you get your hand on Rendermonkey the code seems pretty straight forward : ) Look under Non-photorealistic renders… and let us know how it goes hehe



EDIT: Found this in a different subject, where MrCoder mentions the shader in question (sorta) and there is a link at the top of the page http://www.jmonkeyengine.com/jmeforum/index.php?topic=8446.15

As far as i know jme2 is not on  cvs.dev.java.net but on googlecode svn http://jmonkeyengine.googlecode.com/svn/trunk/  that would explain why you are missing some classes.



Hellmaster

now i got the svn version , I was years behind all the time  XD  and I didnt noticed it (damn jme wiki!)

New Problems followed:

anyone know why I can’t resolve javax.media?  Do i have to use Eclipse RCP ? [solved]



and why does jme physics2  doesnt work with that jme version XD



“no lwjgl in java.library.path” (I added all libs and all of the lwjgl dir), I could cry  :’(

(and I did:…Expand lwjgl.jar → Native Library Location → Edit → Workspace

The native libs are not directly in the "/lib" folder like the old messy 1.0.  They are under separate folder underneath lib.  For example, my mac has lwjgl's native lib set to: jme_SVN/lib/lwjgl/native/macosx  (jme_SVN is just what I called my eclipse project.)

oh thxs , dummy me :slight_smile:

There is also a new physics version for jme2 which can be checked out at http://jmephysics.googlecode.com/svn/trunk



Hellmaster

thank you, now I am finally on the newest standards (hopefully :slight_smile: