2 * Copyright (c) 2003-2009 jMonkeyEngine
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 package com.jmex.effects.particles;
35 import java.io.IOException;
37 import com.jme.math.FastMath;
38 import com.jme.math.Line;
39 import com.jme.math.Quaternion;
40 import com.jme.math.Vector3f;
41 import com.jme.util.export.InputCapsule;
42 import com.jme.util.export.JMEExporter;
43 import com.jme.util.export.JMEImporter;
44 import com.jme.util.export.OutputCapsule;
47 * <code>SimpleParticleForceFactory</code>
48 * @author Joshua Slack
49 * @version $Id: SimpleParticleInfluenceFactory.java,v 1.7 2007/09/21 15:45:32 nca Exp $
51 public final class SimpleParticleInfluenceFactory {
53 public static class BasicWind extends ParticleInfluence {
54 private float strength;
55 private Vector3f windDirection;
56 private boolean random, rotateWithScene;
57 private Vector3f vector = new Vector3f();
62 public BasicWind(float windStr, Vector3f windDir, boolean addRandom,
63 boolean rotateWithScene) {
65 windDirection = windDir;
67 this.rotateWithScene = rotateWithScene;
70 public float getStrength() {
74 public void setStrength(float windStr) {
78 public Vector3f getWindDirection() {
82 public void setWindDirection(Vector3f windDir) {
83 windDirection = windDir;
86 public boolean isRandom() {
90 public void setRandom(boolean addRandom) {
94 public boolean isRotateWithScene() {
95 return rotateWithScene;
98 public void setRotateWithScene(boolean rotateWithScene) {
99 this.rotateWithScene = rotateWithScene;
102 public void prepare(ParticleSystem system) {
103 vector.set(windDirection);
104 if (rotateWithScene) {
105 system.getEmitterTransform().multNormal(vector);
109 public void apply(float dt, Particle p, int index) {
110 float tStr = (random ? FastMath.nextRandomFloat() * strength : strength);
111 p.getVelocity().scaleAdd(tStr * dt, vector, p.getVelocity());
114 public void write(JMEExporter e) throws IOException {
116 OutputCapsule capsule = e.getCapsule(this);
117 capsule.write(strength, "strength", 1f);
118 capsule.write(windDirection, "windDirection", Vector3f.UNIT_X);
119 capsule.write(random, "random", false);
120 capsule.write(rotateWithScene, "rotateWithScene", true);
123 public void read(JMEImporter e) throws IOException {
125 InputCapsule capsule = e.getCapsule(this);
126 strength = capsule.readFloat("strength", 1f);
127 windDirection = (Vector3f)capsule.readSavable("windDirection",
128 Vector3f.UNIT_X.clone());
129 random = capsule.readBoolean("random", false);
130 rotateWithScene = capsule.readBoolean("rotateWithScene", true);
133 public Class getClassTag() {
134 return this.getClass();
138 public static class BasicGravity extends ParticleInfluence {
139 private Vector3f gravity;
140 private boolean rotateWithScene;
141 private Vector3f vector = new Vector3f();
143 public BasicGravity() {
146 public BasicGravity(Vector3f gravForce, boolean rotateWithScene) {
147 gravity = new Vector3f(gravForce);
148 this.rotateWithScene = rotateWithScene;
151 public Vector3f getGravityForce() {
155 public void setGravityForce(Vector3f gravForce) {
159 public boolean isRotateWithScene() {
160 return rotateWithScene;
163 public void setRotateWithScene(boolean rotateWithScene) {
164 this.rotateWithScene = rotateWithScene;
167 public void prepare(ParticleSystem system) {
169 if (rotateWithScene) {
170 system.getEmitterTransform().multNormal(vector);
174 public void apply(float dt, Particle p, int index) {
175 p.getVelocity().scaleAdd(dt, vector, p.getVelocity());
178 public void write(JMEExporter e) throws IOException {
180 OutputCapsule capsule = e.getCapsule(this);
181 capsule.write(gravity, "gravity", Vector3f.ZERO);
182 capsule.write(rotateWithScene, "rotateWithScene", true);
185 public void read(JMEImporter e) throws IOException {
187 InputCapsule capsule = e.getCapsule(this);
188 gravity = (Vector3f)capsule.readSavable("gravity",
189 Vector3f.ZERO.clone());
190 rotateWithScene = capsule.readBoolean("rotateWithScene", true);
193 public Class getClassTag() {
194 return this.getClass();
198 public static class BasicDrag extends ParticleInfluence {
199 private Vector3f velocity = new Vector3f();
200 private float dragCoefficient;
205 public BasicDrag(float dragCoef) {
206 dragCoefficient = dragCoef;
209 public float getDragCoefficient() {
210 return dragCoefficient;
213 public void setDragCoefficient(float dragCoef) {
214 dragCoefficient = dragCoef;
217 public void apply(float dt, Particle p, int index) {
219 velocity.set(p.getVelocity());
220 p.getVelocity().addLocal(velocity.multLocal(-dragCoefficient * dt * p.getInvMass()));
223 public void write(JMEExporter e) throws IOException {
225 OutputCapsule capsule = e.getCapsule(this);
226 capsule.write(dragCoefficient, "dragCoefficient", 1f);
229 public void read(JMEImporter e) throws IOException {
231 InputCapsule capsule = e.getCapsule(this);
232 dragCoefficient = capsule.readFloat("dragCoefficient", 1f);
235 public Class getClassTag() {
236 return this.getClass();
240 public static class BasicVortex extends ParticleInfluence {
242 public static final int VT_CYLINDER = 0;
243 public static final int VT_TORUS = 1;
245 private int type = VT_CYLINDER;
246 private float strength, divergence, height, radius;
248 private boolean random, transformWithScene;
249 private Vector3f v1 = new Vector3f(), v2 = new Vector3f(),
251 private Quaternion rot = new Quaternion();
252 private Line line = new Line();
254 public BasicVortex() {
257 public BasicVortex(float strength, float divergence, Line axis,
258 boolean random, boolean transformWithScene) {
259 this.strength = strength;
260 this.divergence = divergence;
264 this.random = random;
265 this.transformWithScene = transformWithScene;
268 public int getType() {
272 public void setType(int type) {
276 public float getStrength() {
280 public void setStrength(float strength) {
281 this.strength = strength;
284 public float getDivergence() {
288 public void setDivergence(float divergence) {
289 this.divergence = divergence;
292 public Line getAxis() {
296 public void setAxis(Line axis) {
300 public float getHeight() {
304 public void setHeight(float height) {
305 this.height = height;
308 public float getRadius() {
312 public void setRadius(float radius) {
313 this.radius = radius;
316 public boolean isRandom() {
320 public void setRandom(boolean random) {
321 this.random = random;
324 public boolean isTransformWithScene() {
325 return transformWithScene;
328 public void setTransformWithScene(boolean transformWithScene) {
329 this.transformWithScene = transformWithScene;
332 public void prepare(ParticleSystem system) {
333 line.getOrigin().set(axis.getOrigin());
334 line.getDirection().set(axis.getDirection());
335 if (transformWithScene) {
336 system.getEmitterTransform().multPoint(line.getOrigin());
337 system.getEmitterTransform().multNormal(line.getDirection());
339 if (type == VT_CYLINDER) {
340 rot.fromAngleAxis(-divergence, line.getDirection());
344 public void apply(float dt, Particle p, int index) {
345 float dtStr = dt * strength *
346 (random ? FastMath.nextRandomFloat() : 1f);
347 p.getPosition().subtract(line.getOrigin(), v1);
348 line.getDirection().cross(v1, v2);
349 if (v2.length() == 0) { // particle is on the axis
353 if (type == VT_CYLINDER) {
355 p.getVelocity().scaleAdd(dtStr, v2, p.getVelocity());
358 v2.cross(line.getDirection(), v1);
359 v1.multLocal(radius);
360 v1.scaleAdd(height, line.getDirection(), v1);
361 v1.addLocal(line.getOrigin());
362 v1.subtractLocal(p.getPosition());
363 if (v1.length() == 0) { // particle is on the ring
368 rot.fromAngleAxis(-divergence, v2);
370 p.getVelocity().scaleAdd(dtStr, v3, p.getVelocity());
373 public void write(JMEExporter e) throws IOException {
375 OutputCapsule capsule = e.getCapsule(this);
376 capsule.write(type, "type", VT_CYLINDER);
377 capsule.write(strength, "strength", 1f);
378 capsule.write(divergence, "divergence", 0f);
379 capsule.write(axis, "axis", new Line(new Vector3f(),
380 new Vector3f(Vector3f.UNIT_Y)));
381 capsule.write(height, "height", 0f);
382 capsule.write(radius, "radius", 1f);
383 capsule.write(random, "random", false);
384 capsule.write(transformWithScene, "transformWithScene", true);
387 public void read(JMEImporter e) throws IOException {
389 InputCapsule capsule = e.getCapsule(this);
390 type = capsule.readInt("type", VT_CYLINDER);
391 strength = capsule.readFloat("strength", 1f);
392 divergence = capsule.readFloat("divergence", 0f);
393 axis = (Line)capsule.readSavable("axis", new Line(new Vector3f(),
394 Vector3f.UNIT_Y.clone()));
395 height = capsule.readFloat("height", 0f);
396 radius = capsule.readFloat("radius", 1f);
397 random = capsule.readBoolean("random", false);
398 transformWithScene = capsule.readBoolean("transformWithScene", true);
401 public Class getClassTag() {
402 return this.getClass();
409 private SimpleParticleInfluenceFactory() {
413 * Creates a basic wind that always blows in a single direction.
416 * Max strength of wind.
418 * Direction wind should blow.
420 * randomly alter the strength of the wind by 0-100%
421 * @param rotateWithScene
422 * rotate the wind direction with the particle system
423 * @return ParticleInfluence
425 public static ParticleInfluence createBasicWind(float windStr,
426 Vector3f windDir, boolean addRandom, boolean rotateWithScene) {
427 return new BasicWind(windStr, windDir, addRandom, rotateWithScene);
431 * Create a basic gravitational force.
433 * @param rotateWithScene
434 * rotate the gravity vector with the particle system
435 * @return ParticleInfluence
437 public static ParticleInfluence createBasicGravity(Vector3f gravForce,
438 boolean rotateWithScene) {
439 return new BasicGravity(gravForce, rotateWithScene);
443 * Create a basic drag force that will use the given drag coefficient. Drag
444 * is determined by figuring the current velocity and reversing it, then
445 * multiplying by the drag coefficient and dividing by the particle mass.
448 * Should be positive. Larger values mean more drag but possibly
450 * @return ParticleInfluence
452 public static ParticleInfluence createBasicDrag(float dragCoef) {
453 return new BasicDrag(dragCoef);
457 * Creates a basic vortex.
460 * Max strength of vortex.
462 * The divergence in radians from the tangent vector
464 * The center of the vortex.
466 * randomly alter the strength of the vortex by 0-100%
467 * @param transformWithScene
468 * transform the axis with the particle system
469 * @return ParticleInfluence
471 public static ParticleInfluence createBasicVortex(float strength,
472 float divergence, Line axis, boolean random,
473 boolean transformWithScene) {
474 return new BasicVortex(strength, divergence, axis, random,