Force Particles to face a cetrain direction?! (Bug or Feature?)

Hey Guys…



i was trying to achieve that particle-quads face a certain direction.

I my case i wanted to emit particles, staying in the emitters position and the particle-quads should face +y.

The usecase is to simulate expanding concentric cirles on a water surface of a fountain, as seen in the sceens.



By emp_taskforce at 2008-09-24



By emp_taskforce at 2008-09-24



I wasn’t able to achieve this with the available methods.

The screen where it looks ok, is taken from above and setCameraFacing(true)



My TestCase - feel free trying to achiev the right effect.

package com.pass.vb3d.quickwin.test;

import jmetest.effects.TestBatchParticles;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jmex.effects.particles.ParticleController;
import com.jmex.effects.particles.ParticleFactory;
import com.jmex.effects.particles.ParticleGeometry;
import com.jmex.effects.particles.ParticleInfluence;
import com.jmex.effects.particles.ParticleMesh;
import com.jmex.effects.particles.SimpleParticleInfluenceFactory;

public class TestParticles extends SimpleGame {
   
   

   @Override
   protected void simpleInitGame() {
      //Set up floor and indicators for the axis.
      Box floor = new Box("",Vector3f.ZERO,30,0.2f,30);
      floor.setLocalTranslation(0, -0.4f, 0);
      rootNode.attachChild(floor);
      Box xBox = new Box("",new Vector3f(5,0,0),1,1,1);
      rootNode.attachChild(xBox);
      Sphere zSphere = new Sphere("", new Vector3f(0,0,5),4,4,1);
      rootNode.attachChild(zSphere);
            
      //init the particles
      ParticleMesh particles = ParticleFactory.buildParticles("Fountain", 4, ParticleMesh.PT_QUAD);
      particles.setLocalTranslation(0,0,0);
      particles.setStartColor(ColorRGBA.blue);
      particles.setEndColor(new ColorRGBA(255,0,0,0));
      particles.setStartSize(1.5f);
      particles.setEndSize(3);
      particles.setMinimumLifeTime(500);
      particles.setMaximumLifeTime(800);
      particles.setEmitType(ParticleMesh.ET_POINT);
      particles.setMinimumAngle(0);
      particles.setMaximumAngle(0);
      particles.setInitialVelocity(0.01f);
      particles.setSpeed(0.3f);
      particles.warmUp(1);
      
      //dont want the particles direction to be influenced by velocity or camera
      particles.setCameraFacing(false);
      particles.setVelocityAligned(false);
      
      //**Interesting Part**
      //****Approach I:****
      //try to rotate the particles to be emmited in +y direction and facing +y by
      particles.setEmissionDirection(new Vector3f(0,0,0));
      particles.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.PI/2, Vector3f.UNIT_X));
//      particles.setRotateWithScene(true);
//      particles.setWorldEmit(new Vector3f(0,0,1));
//      particles.setParticleOrientation(FastMath.PI/2);
//      particles.rotateUpTo(Vector3f.UNIT_Y);
//      particles.lookAt(new Vector3f(0,500,0), Vector3f.UNIT_Y);
      
//      ParticleController controller = (ParticleController) particles.getControllers().get(0);
//      controller.getParticles().setLocalRotation(new Quaternion().fromAngleAxis(FastMath.PI/2, Vector3f.UNIT_X));
//      controller.getParticles().lookAt(new Vector3f(0,500,0), Vector3f.UNIT_Y);
      rootNode.attachChild(particles);
         
      //****Approach II:****
      //try to put the particles into a new node and rotate the particles using the nodes translation
//      particles.setLocalRotation(new Quaternion().fromAngleAxis(0, Vector3f.UNIT_X));
//      Node particleNode = new Node();
//      particleNode.attachChild(particles);
//      particleNode.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.PI/2, Vector3f.UNIT_X));
//      rootNode.attachChild(particleNode);
      
      rootNode.updateGeometricState(0, true);
      rootNode.updateRenderState();
   }
      
   //main()
   public static void main(String[] args) {
      TestParticles app = new TestParticles();
      app.start();

   }
}



And although i know that jme1 is no longer updated, i searched for a bug.
I found that in its updateGeometricState() [see com.jmex.effects.particles.ParticleGeometry:996]
the worldTranslation and the worldRotation is set to zero.

commenting out these two lines enables you to freely rotate the particles facing/direction/location.
The test as it is, is working correct then, but i havent tested which results this will cause on other things.
Although it seems strange to me, that the worldTranslation and worldRotation is reset within each updatecycle.

and this is what it should look like…



By emp_taskforce at 2008-09-24



quite some probs with the correct ZBuffer and AlphaState settings.

i tried it but failed miserably :slight_smile:



I guess what you want to achieve is not possible with the current methods.

Maybe you can add support for it by implementing your own Particle class which support setting of the rotation.



Or build the vertices differently in ParticleMesh.initializeParticles()

hm, ok.

i tried to implement my own class, but the prob was, that in the class PerticleGeometry the WoldRotation and WorldTranslation is set to zero within the updateGeometricState().

Thererfore implementing a own class, which extends ParticleGeometry will cause some same problems!!?

When the updates are don in the superclass, what can i do then?



MyClass.updateGeometricState()

– save the current worldRotation/Translation

– call super.updateGeometricState which set the values to sero

– override the zero values with the ones saved bevor

??



I guess it might start flickering or something when i will  do it this way!?.



Right now it seems to work fine for me by commenting out those two lines, which set worldRotation and worldTranslation to zero.

The Test works then fine as well.



and here a final screenshot: