Lines and trails

If your texture has alpha in it then you will need to properly setup for transparency by setting the blend mode, putting it in the transparent bucket, etc…

Thanks I’ll give that a try. I just played with the start/end size to get it too look better for now.

@cvlad I love this implementation and I got it to work in a test app. However, my application requires the node to be cloned. When I try to clone the node, I get a null pointer exception! When the function LineControl.cloneForSpatial(spatial) runs, it executes clone.set(this.points,this.halfWidths) when the Mesh of the clone is still null! I tried adding a line of code beforehand that instantiates the mesh for the clone, and that got rid of the exception, but then no trail shows up. What can I do?

Thanks,

Andy

Anyone has succeeded in having trails at a point anywhere else than the model’s (geometry) origin? Every attempt I have made always placed the trail at the origin.

Also, another weird thing is the trail will, 99% of the time, only be visible after I zoom the camera extremely far from the model. So far it only appeared once at normal viewing distance. Once the zooming out made the trail appear I can zoom back in. It will work as it should.

Finally I tried doing it from the scene composer but it seems there are things incompatible with that as I’m getting errors. Either ‘can’t instantiate class’ or other errors (after I tried fixing the instantiation error) It’s actually as Andy above noted.

If @cvlad could visit and review the potential problems and/or fix the issues it would be very much appreciated.

Alternatively, if there is no resolution maybe an official post stating the brokenness of this code and warning users not to use it. (Or, better yet, someone could fix it?)

Goal:

Model with two exhausts where each have a node. By attaching the trails to those nodes I want to have trails seemingly coming out of the exhaust.

EDIT
Ok, it seems I was able to fix the instantiation issue, but for some reason I had to reload the whole model and even wait for a while before it worked. I guess it was kept in memory and that’s why I was continuing to get the message. At least that’s that. Anyway, it’s not displaying, but at least I can go from there… Hopefully I can make this work. Still, if someone has a suggestion, please feel free to help. :slight_smile:

ok, i tried this and here are my conclusions :

first of all, about the cloning thing (yeah, i need to clone it too), it’s because the trailcontrol assert that the line control is on the same spatial. And this is not true. In the given example, the linecontrol is attached to a geometry (an immobile geometry) and the trailcontrol is attached to an other geometry which move. It seems that you can attach the trail geometry and the line geometry on the same spatial but you get strange results (the queue of the trail moves too)

If somebody wants to clone it, i found a “simple” way to do that : a delayed creation.

i.e.

[java]
/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package real.client.controllers.trail;

import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.material.RenderState.FaceCullMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.shape.Box;
import kapplication.Initializable;
import real.client.RealClient;

/**
*

  • @author Bubuche
    */
    public class DelayedTrailCreation extends AbstractControl implements Initializable<RealClient>, Cloneable
    {
    private RealClient application;

@Override
protected void controlUpdate(float tpf)
{
createTrail();

spatial.removeControl(this);

}

@Override
protected void controlRender(RenderManager rm, ViewPort vp)
{
}

private void createTrail()
{
AssetManager assetManager = application.getAssetManager();

Box b = new Box(Vector3f.ZERO, 1, 1, 1);
Spatial geom = spatial;

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);

//geom.setMaterial(mat);
mat.setTexture(“ColorMap”, assetManager.loadTexture(“Textures/F3Fb0.png”));

Geometry trailGeometry = new Geometry();
LineControl line = new LineControl(new LineControl.Algo1CamDirBB(), true);
trailGeometry.addControl(line);
TrailControl trailControl = new TrailControl(line);
geom.addControl(trailControl);

//rootNode.attachChild(trail); // either attach the trail geometry node to the root…

trailGeometry.setIgnoreTransform(true); // or set ignore transform to true. this should be most useful when attaching nodes in the editor
Node test = new Node();
test.attachChild(trailGeometry);
test.setLocalTranslation(new Vector3f(0, 2, 0));  // without ignore transform this would offset the trail
application.getRootNode().attachChild(test);

mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
trailGeometry.setMaterial(mat);

}

@Override
public void init(RealClient application)
{
this.application = application;
}
}
[/java]

This is directly copy past from my program, so you’ll need to clean it. I give it like this cause i want to make sure that people will understand that the delayed controls need to have a reference to the assetmanager, or a way to access it. Why ? Because the only job done by this control is to “copy past” the “example” code. so, you don’t really clone the trail, you create a new instance (but you can clone the instance creator, i.e. this control).
it’s ugly but it works.
I have a way through my “init” method, but you need to find your own. Keep in mind that if you give a reference once (for example you can have 2 constructors for the control and one that take the assetManager as parameter) the reference will be clone when you’ll call the “clone” method (its the default comportement). So, you just need to ensure that your base item (the item you’ll clone over and over again) has a valid reference.
Or you can find an other way, of course :wink:

In the code i gave, you still need to add a way to clean things when the trail is over. I’ll investigate on a good way to do this (cause i added a node an a control on it, they’ll stay in the scene if you don’t remove them)

However … the trail itself has a problem (besides the fact that it is opaque) : when you don’t look at it from a side, when you look at it from behind or front, you will not see it, and you’ll even see how “plan” it is. I am not sure why i have this, as for me the geometry that need the control should be used to give a 3d view of the trail in such case, but i have this comportement. So, i am still looking for a way to create 3D trail.

(p.s. i want to achieve a visual effect close to this one http://image.jeuxvideo.com/images/pc/t/i/tiocpc001_m.jpg )

sorry for pulling up that old topic but i don’t get this to work right, spend some time in debugging but got stuck now :confused:

Initialization looks good, but the lines don’t show up. They only pop up when i turn the camera in a specific angle (space-sim, rotating chasecam). After that i can rotate the camera freely and they are fine, updated correctly and all that.

in my game i got a salvo missle launcher, so when i turn the camera right, all missile trails turn up and keep running correct but as soon as i rotate away the next salvo won’t get trails.

I tracked the issue back to “runControlRender” of the Trailgeometry, which is not fired when the camera is wrong. As far as i can tell this is directly fired by the renderManager - which i could not replace with a debugging-class.

any ideas? / thanks

` public void addTrail(Node s, float endwidth, float length)
{
Box b = new Box(new Vector3f(-0.5f,-0.5f,-0.5f), new Vector3f(0.5f,0.5f,0.5f));
Geometry geom = new Geometry(“Box”, b);
geom.setCullHint(Spatial.CullHint.Always);

    if(mat == null) // static material for now
    {
        mat = new Material(OR.clientapp.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", new ColorRGBA(0.40f,0.50f,0.9f,0.9f));
        mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Additive);
        mat.setTexture("ColorMap",OR.clientapp.getAssetManager().loadTexture("Textures/Trail.png"));
        mat.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
    }
    geom.setMaterial(mat);
    
    if(s.getUserData("length") != null) length = s.getUserData("length");
    if(s.getUserData("startsize") != null) endwidth = (Float) s.getUserData("startsize");
    if(endwidth &lt;= 0 || Float.isNaN(endwidth)) endwidth = 0.5f;

    DebugGeometry trailGeometry = new DebugGeometry(); // just Geometry with "runControlRender"-override

    LineControl line = new LineControl(new Algo1CamDirBB(), true);
    trailGeometry.addControl(line);
    TrailControl trailControl = new TrailControl(line);
    trailControl.setStartWidth(0.1f);
    trailControl.setEndWidth(endwidth);
    trailControl.setLifeSpan(length);
    geom.addControl(trailControl);

    OR.clientapp.currentRegion.attachChild(trailGeometry);

    trailGeometry.setIgnoreTransform(true);

    trailGeometry.setMaterial(mat);
    s.setUserData("trail", geom);
    s.setUserData("linecontrol", line);
    s.setUserData("trailgeom", trailGeometry);
    s.attachChild(geom);
}