Putting a particle effect at a given location and using point lights

I apologize in advance for a basic question, this is day 2 of my efforts with JME. I have taken the particle tutorials and converted them to produce a fire with white smoke and red flames. I’ve drawn a green box to sit the fire on. (I haven’t added the logs yet). My problem is that my particle emitters are always at the origin (I mean 0,0,0). My ground is at -1.8y so so I need to move the effect down to about -1.6y. Calling smoke.setLocalTranslation(new Vector3f(0, -1.6f, 0)) does not move the effect at all.



I have also places a point light inside the fire but it does not illuminate my ground. I have placed a shiny ball above the fire and it reflects the light correctly, but the ground does not cooperate.



Any suggestions would be appreciated - here is my code (I hacked the moving particle sample):



[java]

public class TestMovingParticle extends SimpleApplication {



private ParticleEmitter smoke;

private ParticleEmitter glow;

private ParticleEmitter fog;

private float angle = 0;

private Geometry lightMdl;

PointLight fireLight;



public static void main(String[] args) {

TestMovingParticle app = new TestMovingParticle();

app.start();

}



@Override

public void simpleInitApp() {

smoke = createSmokeEffect();

smoke.setLocalTranslation(new Vector3f(0, -1.6f, 0));

glow = createGlowEffect();

smoke.setLocalTranslation(new Vector3f(0, -1.6f, 0));



Box b = new Box(new Vector3f(0f, -4.5f, 0f), 40f, 4f, 40f);

Geometry geom = new Geometry(“Box”, b);

TangentBinormalGenerator.generate(geom);

Material mat = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”); //mat.setColor(“Color”, ColorRGBA.Green);

mat.setTexture(“DiffuseMap”, assetManager.loadTexture(“Textures/Terrain/splat/grass.jpg”));

mat.getTextureParam(“DiffuseMap”).getTextureValue().setWrap(WrapMode.Repeat);

mat.setBoolean(“UseMaterialColors”,true);

mat.setColor(“Specular”,ColorRGBA.White);

mat.setColor(“Diffuse”,ColorRGBA.White);

mat.setColor(“Ambient”,ColorRGBA.White);

mat.setFloat(“Shininess”, 101f); // [1,128]

geom.setMaterial(mat);

geom.setLocalTranslation(0,-1.8f,-2); // Move it a bit

rootNode.attachChild(geom);



rootNode.attachChild(smoke);

rootNode.attachChild(glow);



/** A bumpy rock with a shiny light effect /

Sphere rock = new Sphere(32,32, 2f);

Geometry shiny_rock = new Geometry(“Shiny rock”, rock);

rock.setTextureMode(Sphere.TextureMode.Projected); // better quality on spheres

TangentBinormalGenerator.generate(rock); // for lighting effect

Material mat_lit = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);

mat_lit.setTexture(“DiffuseMap”, assetManager.loadTexture(“Textures/Terrain/Pond/Pond.jpg”));

mat_lit.setTexture(“NormalMap”, assetManager.loadTexture(“Textures/Terrain/Pond/Pond_normal.png”));

mat_lit.setBoolean(“UseMaterialColors”,true);

mat_lit.setColor(“Specular”,ColorRGBA.White);

mat_lit.setColor(“Diffuse”,ColorRGBA.White);

mat_lit.setFloat(“Shininess”, 1f); // [1,128]

shiny_rock.setMaterial(mat_lit);

shiny_rock.setLocalTranslation(0,8,-2); // Move it a bit

shiny_rock.rotate(1.6f, 0, 0); // Rotate it a bit

rootNode.attachChild(shiny_rock);



lightMdl = new Geometry(“Light”, new Sphere(10, 10, 0.1f));

lightMdl.setMaterial(assetManager.loadMaterial(“Common/Materials/RedColor.j3m”));

rootNode.attachChild(lightMdl);



/
* Must add a light to make the lit object visible! */

DirectionalLight moon = new DirectionalLight();

moon.setDirection(new Vector3f(0f,-3.0f,0f).normalizeLocal());

moon.setColor(new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f));

fireLight = new PointLight();

fireLight.setColor(ColorRGBA.Yellow);

fireLight.setRadius(8f);

fireLight.setPosition(new Vector3f(0, 3, 0));

lightMdl.setLocalTranslation(fireLight.getPosition());

rootNode.addLight(moon);

rootNode.addLight(fireLight);



inputManager.addMapping(“setNum”, new KeyTrigger(KeyInput.KEY_SPACE));

}



private ParticleEmitter createSmokeEffect() {

smoke = new ParticleEmitter(“Emitter”, Type.Triangle, 300);

smoke.setGravity(1, -1, 0);

smoke.getParticleInfluencer().setVelocityVariation(1.5f);

smoke.setLowLife(4);

smoke.setHighLife(5);

smoke.getParticleInfluencer().setInitialVelocity(new Vector3f(0, .5f, 0));

smoke.setImagesX(15);

Material mat = new Material(assetManager, “Common/MatDefs/Misc/Particle.j3md”);

mat.setTexture(“Texture”, assetManager.loadTexture(“Effects/Smoke/Smoke.png”));

smoke.setMaterial(mat);

return smoke;

}



private ParticleEmitter createGlowEffect() {

ParticleEmitter fire =

new ParticleEmitter(“Emitter”, ParticleMesh.Type.Triangle, 30);

Material mat_red = new Material(assetManager,

“Common/MatDefs/Misc/Particle.j3md”);

mat_red.setTexture(“Texture”, assetManager.loadTexture(

“Effects/Explosion/flame.png”));

fire.setMaterial(mat_red);

fire.setImagesX(2);

fire.setImagesY(2); // 2x2 texture animation

fire.setEndColor( new ColorRGBA(1f, 0f, 0f, 0.5f)); // red

fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow

fire.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 3, 0));

fire.setStartSize(1.0f);

fire.setEndSize(0.05f);

fire.setGravity(0, 0, 0);

fire.setLowLife(1f);

fire.setHighLife(1.3f);

fire.getParticleInfluencer().setVelocityVariation(0.3f);

return fire;

}



@Override

public void simpleUpdate(float tpf) {

angle += tpf;

angle %= FastMath.TWO_PI;

float x = FastMath.cos(angle) * 2;

float y = FastMath.sin(angle) * 2;

smoke.setLocalTranslation(0, 0, 0);

fireLight.setPosition(new Vector3f(0, 1, 0));

lightMdl.setLocalTranslation(fireLight.getPosition());

}

}



[/java]

I am using the shiny spheres to give me a fix on the light. As the light is yellow (and now it flickers like real firelight) it is easy to see the light shining on the shiny spheres. I have placed spheres all around the light and it seems to be shining in every direction. But if I change my sphere code into box code, the object no longer reacts to the light. So I think there is something wrong with the way I am creating boxes:



[java] Box b = new Box(new Vector3f(0f, -4.5f, 0f), 40f, 4f, 40f);

Geometry geom = new Geometry(“Box”, b);

TangentBinormalGenerator.generate(geom);

Material mat = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);

//mat.setColor(“Color”, ColorRGBA.Green);

mat.setTexture(“DiffuseMap”, assetManager.loadTexture(“Textures/Terrain/splat/grass.jpg”));

mat.getTextureParam(“DiffuseMap”).getTextureValue().setWrap(WrapMode.Repeat);

mat.setTexture(“NormalMap”, assetManager.loadTexture(“Textures/Terrain/Pond/Pond_normal.png”));

mat.setBoolean(“UseMaterialColors”, true);

mat.setColor(“Specular”, ColorRGBA.Black);

mat.setColor(“Diffuse”, ColorRGBA.White);

mat.setColor(“Ambient”, ColorRGBA.White);

mat.setFloat(“Shininess”, 1f); // [1,128]

geom.setMaterial(mat);

[/java]



Removing the textures doesn’t help either. I’ve also tried generating the binormals for the box (b) and the geometry (geom) and played with the order of the method calls but nothing seems to work.

I used your code and made the changes I stated above and I get the effect you want.



You can also remove all of this:

[java]mat.setBoolean("UseMaterialColors", true);

mat.setColor("Specular", ColorRGBA.Black);

mat.setColor("Diffuse", ColorRGBA.White);

mat.setColor("Ambient", ColorRGBA.White);[/java]

OK, I have used the changes you suggest and still see nothing - the rocks display correctly but nada for the ground. It might be an issue with my graphics card - I will try this code on my other computer.

This is the exact file I used:



[java]public class TestBox extends SimpleApplication {



private ParticleEmitter smoke;

private ParticleEmitter glow;

private ParticleEmitter fog;

private float angle = 0;

private Geometry lightMdl;

PointLight fireLight;



public static void main(String[] args) {

TestBox app = new TestBox();

app.start();

}



@Override

public void simpleInitApp() {

smoke = createSmokeEffect();

smoke.setLocalTranslation(new Vector3f(0, -1.6f, 0));

glow = createGlowEffect();

smoke.setLocalTranslation(new Vector3f(0, -1.6f, 0));



Box b = new Box(new Vector3f(0f, -4.5f, 0f), 40f, 4f, 40f);

Geometry geom = new Geometry("Box", b);

//TangentBinormalGenerator.generate(geom);

Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); //mat.setColor("Color", ColorRGBA.Green);

mat.setTexture("DiffuseMap", assetManager.loadTexture("Textures/Terrain/splat/grass.jpg"));

mat.getTextureParam("DiffuseMap").getTextureValue().setWrap(WrapMode.Repeat);

//mat.setBoolean("UseMaterialColors",true);

//mat.setColor("Specular",ColorRGBA.White);

//mat.setColor("Diffuse",ColorRGBA.White);

//mat.setColor("Ambient",ColorRGBA.White);

//mat.setFloat("Shininess", 101f); // [1,128]

geom.setMaterial(mat);

geom.setLocalTranslation(0,-1.8f,-2); // Move it a bit

rootNode.attachChild(geom);



rootNode.attachChild(smoke);

rootNode.attachChild(glow);



/** A bumpy rock with a shiny light effect /

Sphere rock = new Sphere(32,32, 2f);

Geometry shiny_rock = new Geometry("Shiny rock", rock);

rock.setTextureMode(Sphere.TextureMode.Projected); // better quality on spheres

TangentBinormalGenerator.generate(rock); // for lighting effect

Material mat_lit = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");

mat_lit.setTexture("DiffuseMap", assetManager.loadTexture("Textures/Terrain/Pond/Pond.jpg"));

mat_lit.setTexture("NormalMap", assetManager.loadTexture("Textures/Terrain/Pond/Pond_normal.png"));

mat_lit.setBoolean("UseMaterialColors",true);

mat_lit.setColor("Specular",ColorRGBA.White);

mat_lit.setColor("Diffuse",ColorRGBA.White);

mat_lit.setFloat("Shininess", 1f); // [1,128]

shiny_rock.setMaterial(mat_lit);

shiny_rock.setLocalTranslation(0,8,-2); // Move it a bit

shiny_rock.rotate(1.6f, 0, 0); // Rotate it a bit

rootNode.attachChild(shiny_rock);



lightMdl = new Geometry("Light", new Sphere(10, 10, 0.1f));

lightMdl.setMaterial(assetManager.loadMaterial("Common/Materials/RedColor.j3m"));

rootNode.attachChild(lightMdl);



/
* Must add a light to make the lit object visible! */

DirectionalLight moon = new DirectionalLight();

moon.setDirection(new Vector3f(0f,-3.0f,0f).normalizeLocal());

moon.setColor(new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f));

fireLight = new PointLight();

fireLight.setColor(ColorRGBA.Yellow);

fireLight.setRadius(200f);

fireLight.setPosition(new Vector3f(4, 8, 0));

lightMdl.setLocalTranslation(fireLight.getPosition());

rootNode.addLight(moon);

rootNode.addLight(fireLight);



inputManager.addMapping("setNum", new KeyTrigger(KeyInput.KEY_SPACE));



getFlyByCamera().setMoveSpeed(200);

}



private ParticleEmitter createSmokeEffect() {

smoke = new ParticleEmitter("Emitter", Type.Triangle, 300);

smoke.setGravity(1, -1, 0);

smoke.getParticleInfluencer().setVelocityVariation(1.5f);

smoke.setLowLife(4);

smoke.setHighLife(5);

smoke.getParticleInfluencer().setInitialVelocity(new Vector3f(0, .5f, 0));

smoke.setImagesX(15);

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");

mat.setTexture("Texture", assetManager.loadTexture("Effects/Smoke/Smoke.png"));

smoke.setMaterial(mat);

return smoke;

}



private ParticleEmitter createGlowEffect() {

ParticleEmitter fire =

new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);

Material mat_red = new Material(assetManager,

"Common/MatDefs/Misc/Particle.j3md");

mat_red.setTexture("Texture", assetManager.loadTexture(

"Effects/Explosion/flame.png"));

fire.setMaterial(mat_red);

fire.setImagesX(2);

fire.setImagesY(2); // 2x2 texture animation

fire.setEndColor( new ColorRGBA(1f, 0f, 0f, 0.5f)); // red

fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow

fire.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 3, 0));

fire.setStartSize(1.0f);

fire.setEndSize(0.05f);

fire.setGravity(0, 0, 0);

fire.setLowLife(1f);

fire.setHighLife(1.3f);

fire.getParticleInfluencer().setVelocityVariation(0.3f);

return fire;

}



@Override

public void simpleUpdate(float tpf) {

angle += tpf;

angle %= FastMath.TWO_PI;

float x = FastMath.cos(angle) * 20;

float z = FastMath.sin(angle) * 20;

//smoke.setLocalTranslation(0, 0, 0);

fireLight.setPosition(new Vector3f(x, 8, z));

lightMdl.setLocalTranslation(fireLight.getPosition());

}

}[/java]

1 Like

Thanks so much. I copied everything you have into my file piece by piece, although superficially I couldn’t see any differences in the box construction or lighting setup. But… yes your code works… so I started re-enabling my code to see what was breaking it. My ground stopped glowing when I reinserted my firelight flickering code, specifically this line:



fireLight.setRadius(newRadius);



This flicker code works:



@Override

public void simpleUpdate(float tpf) {

if (Math.random() > 0.9) {

float fireBright = (float) Math.random();

currentFire = (fireBright + (4.0f * currentFire)) / 5.0f;

float r = 0.8f * currentFire;

float g = 0.8f * currentFire;

float b = 0.2f * currentFire;

float a = 1.0f;

ColorRGBA newColor = new ColorRGBA(r, g, b, a);

//float newRadius = 16 * currentFire;

fireLight.setColor(newColor);

//fireLight.setRadius(newRadius);

}

fireLight.setPosition(new Vector3f(0, -0.8f, 0));

lightMdl.setLocalTranslation(fireLight.getPosition());

}



Now that I can see it shining on the ground, I can see I don’t even need to mess with the radius!



Well, I have learned a bit more about debugging GL code - start by commenting out the special effects :slight_smile:



EDIT: Actually, the problem was the radius size: setting the random radius to a larger amount also solves the problem. So everything is working fine, except for my brain. It doesn’t quite make sense to me, because if the rocks are within the smaller radius, why isn’t the ground?

In your simpleUpdate method you call: smoke.setLocalTranslation(0, 0, 0); That means every frame it will be set at 0,0,0

Sorry! I just realized I was setting the location twice - once in the update method, which overrode my init code. Sorry, it’s midnight here, I’ve got flu, I’m a loser. But if anyone could point out my error in the lighting of my ground I would be overjoyed!

hehe no worries.

Try increasing your point light radius to about 200 and raise it up a bit. Also use the generated x/y coordinates in the update method to see it change (or else it is hard to tell if it is doing anything):

[java]@Override

public void simpleUpdate(float tpf) {

angle += tpf;

angle %= FastMath.TWO_PI;

float x = FastMath.cos(angle) * 20;

float z = FastMath.sin(angle) * 20;

//smoke.setLocalTranslation(0, 0, 0);

fireLight.setPosition(new Vector3f(x, 8, z));

lightMdl.setLocalTranslation(fireLight.getPosition());

}[/java]



For really cool light effects you should look at the spotlight tests: TestSpotLight, TestSpotLightTerrain