Markers/highlights under player units

Hi all,



Can someone point me in the right direction for doing what must be a pretty common effect with textures? I think is typical in RTS and RPG games to indicate selected players/units/vehicles with a highlight or circle under them. Sometimes other power-up effects or status are also indicated with an animated highlight like a rotating or pulsing circle or pattern.  So, for example, suppose I wanted to add such an effect to FlagRush, where there's a terrain and a player moving around on the terrain…  how might I get a small circle texture to overlay on the terrain under the vehicle position (but a method that also works in an RTS type thing where there are dozens of highlighted units)?



I suppose the same effect could also be used for other decal things that are temporarily painted on the terrain, like tire tracks, footprints, scorch marks, etc. I think this has got to be pretty common, so I'm hoping someone has a code fragment or a link to docs about how this might be done (fairly easily :slight_smile: ).



TIA

The quick approach would surely be just adding a Quad around the feet of the units with a nice semi-transparent selection texture…

Hi,



But if the unit was on uneven ground a simple quad would look crappy  :stuck_out_tongue:




  • Chris

You just need to obtain the image created for the terrain and do the equivelant of a texture splat.



Make sure you can translate the location of the model to the position on the texture image and just use the standard java image api to write the pixels from the circle image to the texture

Hi,



Havin thought about this a little, couldn't you use MrCoder's projected texture and just project the circle directly down where ever the player is?




  • Chris

yeah you could, but it wouldnt be very efficient, especially if you need several circles for different players/npc's etc…i've seen people project the quad geometry instead though, which could be the way to go

Or easier would be to use the Line class and make your circle with X number of points (64 works well)  Update the position of the points when the circle moves using the getheight method of the terrain (you might also use a slight offset up or zbuffer options to ensure it doesn’t zfight the ground.)



Eg:

Thanks for these suggestions.



Yeah, I first tried quads under the player units, but like Gent Hal said, on uneven ground it doesn't look so hot. Then tried just lines - better, but not quite what I was looking for. The texture splat idea sounds more promising. I'll experiment with that. I'm overdue to make an effort at learning more than just the basics for texture handeling.



ty

use a simple quadarray with 4x4 tiles an texture it with a nice texture as marker. update the heights of any vertex in this quadarray based on the terrainheight + 0.1 while moving.


the tought thing is that these methods will be hard to get to work with any object/structure on the terrain, like when walking on a house/bridge etc…except for the projected texture, but that'll give other anomalities

it's the same problem, when using a single quad. or not. but over a terrain it looks good

You can also use and adapt the TerrainMarker class from MonkeyWorld3D. It's a "circle" that is pressed on the terrain and it looks really nice.

I changed it to an hexagon for my own project and here is how it looks :

http://sanctuaireone.free.fr/screens/06jan-trooper.jpg



code is available of course (both MonkeyWorld and mine)

the link of your screenshot is broken

Fixed it, thx :slight_smile:

joshua calvert would never run around with a gun :stuck_out_tongue:

:slight_smile: Wait until you see Louise :wink:



(but of course the model featured on the screenshot is not supposed to be Calvert…)

That’s what I have with lines :







My code :



public void createSelectionShape() {
   BoundingVolume vol = getBoundingBox();

   float radius = 0;

   if (vol.getType() == BoundingVolume.BOUNDING_SPHERE) {
      radius = ((BoundingSphere)vol).radius;
   } else if (vol.getType() == BoundingVolume.BOUNDING_BOX) {
      Vector3f extent = new Vector3f();
      ((BoundingBox)vol).getExtent(extent);
      if (extent.x >= extent.z) {
         radius = extent.x ;
      } else {
         radius = extent.z;
      }
   } else {
      LOG.error("BOUNDING VOLUME NOT MANAGED");
      return;
   }
   
   float delta = FastMath.PI / 12;
   Vector3f vec;

   Vector3f[] points = new Vector3f[24];
   ColorRGBA[] colors = new ColorRGBA[24];
      
   for (int i = 0; i < 24; i++) {
      vec = TerrainTools.getTerrainPosition(
         new Vector3f(node.getWorldTranslation().x + radius * FastMath.cos(delta * i),
         1000,
         node.getWorldTranslation().z + radius * FastMath.sin(delta * i))
      );
      points[i] = vec.add(0, 0.05f, 0);
      colors[i] = new ColorRGBA(0,1,0,1);
   }

   selectionShape = new Line("selection "+node.getName(), points, null, colors, null);
   selectionShape.setMode(Line.LOOP);
   selectionShape.setLineWidth(1);
   selectionShape.setLightCombineMode(LightState.OFF);
      
   selectionShape.updateRenderState();

   ManagerProvider.getRenderManager().addSpatial(selectionShape);
}



For static objects (house, ...), I planned to use rectangles.

Perhaps it can help ...

the code doesn't render anything for me. no lines, no bounding box (worldbound is 0,0,0/0,0,0)

this is my code:

public class ProjectedCrosshair extends VisualDecoratorBase {
  private Vector3f[] m_points;
  private static final float DELTA = FastMath.PI / 12;
  private Line m_selectionShape;

  public void firstRun(final float p_timePerFrame, final AbstractEntity p_ae) {
    super.firstRun(p_timePerFrame, p_ae);

    m_points = new Vector3f[24];
    final ColorRGBA[] colors = new ColorRGBA[24];

    final ColorRGBA l_rgba = new ColorRGBA(1.0F, 1.0F, 1.0F, 1.0F);
    for (int i = 0; i < 24; i++) {
      m_points[i] = new Vector3f();
      colors[i] = l_rgba;
    }

    m_selectionShape = new Line("CrosshairPoint", m_points, null, colors, null);
    m_selectionShape.setAntialiased(true);
    m_selectionShape.setMode(Line.LOOP);
    m_selectionShape.setLineWidth(4);
    m_selectionShape.setLightCombineMode(LightState.OFF);
    m_selectionShape.updateRenderState();
    m_selectionShape.setModelBound(new BoundingBox());
    m_selectionShape.updateModelBound();
    p_ae.getEngine().getRootNode().attachChild(m_selectionShape);
  }

  public void apply(final float p_timePerFrame, final AbstractEntity p_ae) {
    final Vector3f l_rayContact = p_ae.getFirstRayContact();
    if (l_rayContact != null) {
      m_selectionShape.setCullMode(Node.CULL_NEVER);
      final int radius = 1;
      for (int i = 0; i < 24; i++) {
        final float l_x = l_rayContact.x + radius * FastMath.cos(DELTA * i);
        final float l_z = l_rayContact.z + radius * FastMath.sin(DELTA * i);
        final float l_height = p_ae.getEngine().getCurrentTerrain().getHeight(l_x,
           l_z);
        m_points[i].set(l_x, l_height + 0.05f, l_z);
      }
    } else {
      //m_selectionShape.setCullMode(Node.CULL_ALWAYS);
    }
    m_selectionShape.updateGeometricState(0.0F, false);
    m_selectionShape.updateWorldBound();
  }
}



if i use a sphere, it works. something is wrong with the line
MrCoder said:

the tought thing is that these methods will be hard to get to work with any object/structure on the terrain, like when walking on a house/bridge etc...except for the projected texture, but that'll give other anomalities


I would like to try it out (the projected texture) but I have no idea how to do it. Could you provide a simple code snippet, just to give me the right directions, please?

Thanks.
Filip

jmetest.effects.TestProjectedTexture  is the demo for projected textures