Problem drawing a path with images

I’m trying to draw a footsteps path between a npc and a target point.
Instead of re eventing the wheel I’m using some of the Virtualmat code from Arthur since he already implemented this feature successfully.
The path is not being drawn correctly here is a video:
[video]http://youtu.be/OqgZwLpWMbY[/video]

Here is the code:

[java]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package net.medievalsoul.marker;

import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import medievalsoul.GameManager;
import net.medievalsoul.utils.SquareQuad;
import java.lang.Math;
import java.util.ArrayList;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;

/**
*

  • @author User
    */
    public class Marker
    {
    private GameManager gm;
    private Collection<SingleSquareMarker> markers = new ArrayList<SingleSquareMarker>();
    private IdentityHashMap<SingleSquareMarker, SingleSquareMarker> squareMarkers = new IdentityHashMap<SingleSquareMarker, SingleSquareMarker>();
    private List<Vector2f> currentPath = new ArrayList<Vector2f>();

    public Marker(GameManager gm)
    {
    this.gm = gm;
    }

    public void createPath(Vector3f origin, Vector3f destination)
    {
    Vector2f location = new Vector2f(origin.x,origin.z);
    Vector2f coord = new Vector2f(destination.x,destination.z);
    markPath(findPath(location, coord));
    }

    public List<Vector2f> findPath(Vector2f location, Vector2f coord)
    {
    float x = location.x;
    float y = location.y;
    float xdiff = coord.x - x;
    float ydiff = coord.y - y;
    int xsign = (int) Math.signum(xdiff);
    int ysign = (int) Math.signum(ydiff);

        int steps = (int) Math.max(Math.abs(xdiff), Math.abs(ydiff));
        List&lt;Vector2f&gt; path = new ArrayList&lt;Vector2f&gt;(steps);
        for (int i = 0; i &lt; steps - 1; i++) 
        {
                x = x + xsign;
                y = y + ysign;
                xdiff = xdiff - xsign;
                ydiff = ydiff - ysign;
                if (xdiff == 0) 
                    xsign = 0;
    
                if (ydiff == 0) 
                   ysign = 0;
    
                path.add(new Vector2f(x, y));
        }
        return path;
    

    }

    public void markPath(List<Vector2f> path)
    {

     if ( currentPath.equals(path)) 
         return;
    
    
     for (SingleSquareMarker stm : markers) 
     {
             removeSquareMarker(stm);
     }
     markers.clear();
    
     Vector2f previousTc = null;
     for (Vector2f tc : path) 
     {
         float rotation = 0;
         if ( previousTc != null ) 
         {
             /*int dx = (int) (tc.x - previousTc.x);
             int dy = (int) (tc.y - previousTc.y);
             Vector2f v = new Vector2f(dx,dy);
             rotation = -v.angleBetween(Vector2f.UNIT_XY)/(FastMath.DEG_TO_RAD * 90);
             rotation -= 0.125f;*/
             SingleSquareMarker marker = addSquareMarker(tc, null, "Textures/footsteps.png", 2.0f, rotation);
             markers.add(marker);
         }
    
         previousTc = tc;
     }
    
     currentPath = path;
    

    }

    public SingleSquareMarker addSquareMarker(Vector2f coord, ColorRGBA color, String texture, float scale, float rotation)
    {
    Mesh markerMesh = SquareQuad.createMesh();
    Geometry geo = new Geometry(“Marker”,markerMesh);
    geo.scale(scale);
    geo.rotate(FastMath.DEG_TO_RAD * 90 ,rotation,0);
    Vector3f position = new Vector3f(coord.x,0.6f,coord.y);
    //position.y += 0.03f;
    geo.setLocalTranslation(position);
    SingleSquareMarker stm = new SingleSquareMarker(coord,color,geo);

     Material mat = new Material(gm.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
     
     if ( texture != null ) {
             mat.setTexture("ColorMap", gm.getAssetManager().loadTexture(texture));
     }
    
     if ( color != null ) {
             mat.setColor("Color", color);
     }
    
     mat.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
     mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
     mat.getAdditionalRenderState().setDepthWrite(false);
     geo.setMaterial(mat);
     geo.setQueueBucket(RenderQueue.Bucket.Transparent);
     addSquareMarker(stm);
     
     return stm;
    

    }

    private void addSquareMarker(SingleSquareMarker stm)
    {
    gm.getRootNode().attachChild(stm.getQuad());
    squareMarkers.put(stm, stm);
    }

    public void removeSquareMarker(SingleSquareMarker stm)
    {
    gm.getRootNode().detachChild(stm.getQuad());
    squareMarkers.remove(stm);
    }

}
[/java]

And here is where I’m calling it:

[java]public void onAction(String name, boolean isPressed, float tpf)
{
int press = isPressed ? 1 : 0;

    if ( name.contains("WHEEL") ) 
    {
        return;
    }
    if (name.equals("ACTION") &amp;&amp; !isPressed) 
    {
        // 1. Reset results list.
        CollisionResults results = new CollisionResults();
        // 2. Aim the ray from cam loc to cam direction.
        Ray ray = new Ray(cam.getLocation(), cam.getDirection());
        // 3. Collect intersections between Ray and Shootables in results list.
        rootNode.collideWith(ray, results);
        // 4. Print the results
        System.out.println("----- Collisions? " + results.size() + "-----");
        for (int i = 0; i &lt; results.size(); i++) 
        {
            // For each hit, we know distance, impact point, name of geometry.
            float dist = results.getCollision(i).getDistance();
            Vector3f pt = results.getCollision(i).getContactPoint();
            String hit = results.getCollision(i).getGeometry().getName();
            System.out.println("* Collision #" + i);
            System.out.println("  You shot " + hit + " at " + pt + ", " + dist + " wu away.");
        }
        // 5. Use the results (we mark the hit object)
        if (results.size() &gt; 0) 
        {
            // The closest collision point is what was truly hit:
            CollisionResult closest = results.getClosestCollision();
            mark.setLocalTranslation(closest.getContactPoint());
            rootNode.attachChild(mark);
            origin = avatar.getNode().getLocalTranslation();
            destination = closest.getContactPoint();
            Vector3f delta = destination.subtract(origin);
            delta.y = 0.0f;
            avatar.setDestinationPoint(destination);
            // Let's interact - we mark the hit with a red dot.
            avatar.setViewDirection(delta.normalizeLocal());
            avatar.setWalkDirection(delta.normalizeLocal().multLocal(10.0f));
            marker.createPath(origin, destination);
        } 
        else 
        {
            rootNode.detachChild(mark);
        } 
    }

    char sign = name.charAt(0);
    if ( sign == '-') 
    {
        press = -press;
    } 
    else if (sign != '+') 
    {
        return;
    }

    DoF deg = DoF.valueOf(name.substring(1));
    direction[deg.ordinal()] = press;
}[/java] 

I already spent a lot of time trying to solve this but I don’t know what I’m doing wrong.
Please help.
Thanks in advance!

Can you please elaborate on what the problem is/are. I can see several things that might be wrong:

  1. Only one segment of the path is drawn at one time.
  2. Segments don’t have the correct rotation.

The code handling the rotation seems to be commented out? Is it the same as in the example video?

Try changing the bucket to opaque (to test) to see if that makes all the footsteps show.

1 Like

Hi Rickard thanks for your reply.
The problem is a rotation of the segments.
The segments should draw in the correct direction without the rotation code i think.

Finally i solved the problem!
I replaced the find path code by the Bresenham’s algorithm with some small changes to handle the distance between images.
Here is the final result and code:

[video]http://youtu.be/Po99xeIZ-ms[/video]

Code:

[java]public List<Vector2f> findPath(Vector2f location, Vector2f coord, int distBetweenPoints)
{
List<Vector2f> path = new ArrayList<Vector2f>();
int w = (int) (coord.x - location.x) ;
int h = (int) (coord.y - location.y) ;
int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0 ;
if (w<0) dx1 = -1 ; else if (w>0) dx1 = 1 ;
if (h<0) dy1 = -1 ; else if (h>0) dy1 = 1 ;
if (w<0) dx2 = -1 ; else if (w>0) dx2 = 1 ;
int longest = Math.abs(w) ;
int shortest = Math.abs(h) ;
if (!(longest>shortest))
{
longest = Math.abs(h) ;
shortest = Math.abs(w) ;
if (h<0) dy2 = -1 ; else if (h>0) dy2 = 1 ;
dx2 = 0 ;
}
int numerator = longest >> 1 ;
for (int i=0; i<= longest / distBetweenPoints; i++)
{
path.add(new Vector2f(location.x, location.y));
numerator += shortest ;
if (!(numerator<longest))
{
numerator -= longest ;
location.x += dx1 * distBetweenPoints;
location.y += dy1 * distBetweenPoints;
}
else
{
location.x += dx2 * distBetweenPoints;
location.y += dy2 * distBetweenPoints;
}
}
return path;
}[/java]

I hope it helps someone else.