OSDN Git Service

b6182a7b16eddc83eb5483e42c2d4d6aa73c6757
[mikumikustudio/MikuMikuStudio.git] / src / com / jmex / effects / particles / SimpleParticleInfluenceFactory.java
1 /*
2  * Copyright (c) 2003-2009 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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.
31  */
32
33 package com.jmex.effects.particles;
34
35 import java.io.IOException;
36
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;
45
46 /**
47  * <code>SimpleParticleForceFactory</code>
48  * @author Joshua Slack
49  * @version $Id: SimpleParticleInfluenceFactory.java,v 1.7 2007/09/21 15:45:32 nca Exp $
50  */
51 public final class SimpleParticleInfluenceFactory {
52
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(); 
58         
59         public BasicWind() {
60         }
61         
62         public BasicWind(float windStr, Vector3f windDir, boolean addRandom,
63             boolean rotateWithScene) {
64             strength = windStr;
65             windDirection = windDir;
66             random = addRandom;
67             this.rotateWithScene = rotateWithScene;
68         }
69         
70         public float getStrength() {
71             return strength;
72         }
73         
74         public void setStrength(float windStr) {
75             strength = windStr;
76         }
77         
78         public Vector3f getWindDirection() {
79             return windDirection;
80         }
81         
82         public void setWindDirection(Vector3f windDir) {
83             windDirection = windDir;
84         }
85
86         public boolean isRandom() {
87             return random;
88         }
89         
90         public void setRandom(boolean addRandom) {
91             random = addRandom;
92         }
93         
94         public boolean isRotateWithScene() {
95             return rotateWithScene;
96         }
97         
98         public void setRotateWithScene(boolean rotateWithScene) {
99             this.rotateWithScene = rotateWithScene;
100         }
101         
102         public void prepare(ParticleSystem system) {
103             vector.set(windDirection);
104             if (rotateWithScene) {
105                 system.getEmitterTransform().multNormal(vector);
106             }
107         }
108         
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());
112         }
113         
114         public void write(JMEExporter e) throws IOException {
115             super.write(e);
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);
121         }
122
123         public void read(JMEImporter e) throws IOException {
124             super.read(e);
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);
131         }
132
133         public Class getClassTag() {
134             return this.getClass();
135         }
136     }
137     
138     public static class BasicGravity extends ParticleInfluence {
139         private Vector3f gravity;
140         private boolean rotateWithScene;
141         private Vector3f vector = new Vector3f();
142         
143         public BasicGravity() {
144         }
145         
146         public BasicGravity(Vector3f gravForce, boolean rotateWithScene) {
147             gravity = new Vector3f(gravForce);
148             this.rotateWithScene = rotateWithScene;
149         }
150         
151         public Vector3f getGravityForce() {
152             return gravity;
153         }
154         
155         public void setGravityForce(Vector3f gravForce) {
156             gravity = gravForce;
157         }
158         
159         public boolean isRotateWithScene() {
160             return rotateWithScene;
161         }
162         
163         public void setRotateWithScene(boolean rotateWithScene) {
164             this.rotateWithScene = rotateWithScene;
165         }
166         
167         public void prepare(ParticleSystem system) {
168             vector.set(gravity);
169             if (rotateWithScene) {
170                 system.getEmitterTransform().multNormal(vector);
171             }
172         }
173         
174         public void apply(float dt, Particle p, int index) {
175             p.getVelocity().scaleAdd(dt, vector, p.getVelocity());
176         }
177     
178         public void write(JMEExporter e) throws IOException {
179             super.write(e);
180             OutputCapsule capsule = e.getCapsule(this);
181             capsule.write(gravity, "gravity", Vector3f.ZERO);
182             capsule.write(rotateWithScene, "rotateWithScene", true);
183         }
184
185         public void read(JMEImporter e) throws IOException {
186             super.read(e);
187             InputCapsule capsule = e.getCapsule(this);
188             gravity = (Vector3f)capsule.readSavable("gravity",
189                 Vector3f.ZERO.clone());
190             rotateWithScene = capsule.readBoolean("rotateWithScene", true);
191         }
192         
193         public Class getClassTag() {
194             return this.getClass();
195         }
196     }
197     
198     public static class BasicDrag extends ParticleInfluence {
199         private Vector3f velocity = new Vector3f();
200         private float dragCoefficient;
201         
202         public BasicDrag() {
203         }
204         
205         public BasicDrag(float dragCoef) {
206             dragCoefficient = dragCoef;
207         }
208         
209         public float getDragCoefficient() {
210             return dragCoefficient;
211         }
212         
213         public void setDragCoefficient(float dragCoef) {
214             dragCoefficient = dragCoef;
215         }
216         
217         public void apply(float dt, Particle p, int index) {
218             // viscous drag
219             velocity.set(p.getVelocity());
220             p.getVelocity().addLocal(velocity.multLocal(-dragCoefficient * dt * p.getInvMass()));
221         }
222     
223         public void write(JMEExporter e) throws IOException {
224             super.write(e);
225             OutputCapsule capsule = e.getCapsule(this);
226             capsule.write(dragCoefficient, "dragCoefficient", 1f);
227         }
228
229         public void read(JMEImporter e) throws IOException {
230             super.read(e);
231             InputCapsule capsule = e.getCapsule(this);
232             dragCoefficient = capsule.readFloat("dragCoefficient", 1f);
233         }
234         
235         public Class getClassTag() {
236             return this.getClass();
237         }
238     }
239     
240     public static class BasicVortex extends ParticleInfluence {
241     
242         public static final int VT_CYLINDER = 0;
243         public static final int VT_TORUS = 1;
244         
245         private int type = VT_CYLINDER;
246         private float strength, divergence, height, radius;
247         private Line axis;
248         private boolean random, transformWithScene;
249         private Vector3f v1 = new Vector3f(), v2 = new Vector3f(),
250             v3 = new Vector3f();
251         private Quaternion rot = new Quaternion();
252         private Line line = new Line();
253         
254         public BasicVortex() {
255         }
256         
257         public BasicVortex(float strength, float divergence, Line axis,
258             boolean random, boolean transformWithScene) {
259             this.strength = strength;
260             this.divergence = divergence;
261             this.axis = axis;
262             this.height = 0f;
263             this.radius = 1f;
264             this.random = random;
265             this.transformWithScene = transformWithScene;
266         }
267         
268         public int getType() {
269             return type;
270         }
271         
272         public void setType(int type) {
273             this.type = type;
274         }
275         
276         public float getStrength() {
277             return strength;
278         }
279         
280         public void setStrength(float strength) {
281             this.strength = strength;
282         }
283         
284         public float getDivergence() {
285             return divergence;
286         }
287         
288         public void setDivergence(float divergence) {
289             this.divergence = divergence;            
290         }
291         
292         public Line getAxis() {
293             return axis;
294         }
295         
296         public void setAxis(Line axis) {
297             this.axis = axis;
298         }
299         
300         public float getHeight() {
301             return height;
302         }
303         
304         public void setHeight(float height) {
305             this.height = height;
306         }
307         
308         public float getRadius() {
309             return radius;
310         }
311         
312         public void setRadius(float radius) {
313             this.radius = radius;
314         }
315         
316         public boolean isRandom() {
317             return random;
318         }
319         
320         public void setRandom(boolean random) {
321             this.random = random;
322         }
323         
324         public boolean isTransformWithScene() {
325             return transformWithScene;
326         }
327         
328         public void setTransformWithScene(boolean transformWithScene) {
329             this.transformWithScene = transformWithScene;
330         }
331         
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());
338             }
339             if (type == VT_CYLINDER) {
340                 rot.fromAngleAxis(-divergence, line.getDirection());
341             }
342         }
343         
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
350                 return;
351             }
352             v2.normalizeLocal();
353             if (type == VT_CYLINDER) {
354                 rot.multLocal(v2);
355                 p.getVelocity().scaleAdd(dtStr, v2, p.getVelocity());
356                 return;
357             }
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
364                 return;
365             }
366             v1.normalizeLocal();
367             v1.cross(v2, v3);
368             rot.fromAngleAxis(-divergence, v2);
369             rot.multLocal(v3);
370             p.getVelocity().scaleAdd(dtStr, v3, p.getVelocity());
371         }
372     
373         public void write(JMEExporter e) throws IOException {
374             super.write(e);
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);
385         }
386
387         public void read(JMEImporter e) throws IOException {
388             super.read(e);
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);
399         }
400         
401         public Class getClassTag() {
402             return this.getClass();
403         }
404     }
405     
406     /**
407      * Not used.
408      */
409     private SimpleParticleInfluenceFactory() {
410     }
411
412     /**
413      * Creates a basic wind that always blows in a single direction.
414      * 
415      * @param windStr
416      *            Max strength of wind.
417      * @param windDir
418      *            Direction wind should blow.
419      * @param addRandom
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
424      */
425     public static ParticleInfluence createBasicWind(float windStr,
426         Vector3f windDir, boolean addRandom, boolean rotateWithScene) {
427         return new BasicWind(windStr, windDir, addRandom, rotateWithScene);
428     }
429
430     /**
431      * Create a basic gravitational force.
432      *
433      * @param rotateWithScene
434      *            rotate the gravity vector with the particle system
435      * @return ParticleInfluence
436      */
437     public static ParticleInfluence createBasicGravity(Vector3f gravForce,
438         boolean rotateWithScene) {
439         return new BasicGravity(gravForce, rotateWithScene);
440     }
441
442     /**
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.
446      * 
447      * @param dragCoef
448      *            Should be positive. Larger values mean more drag but possibly
449      *            more instability.
450      * @return ParticleInfluence
451      */
452     public static ParticleInfluence createBasicDrag(float dragCoef) {
453         return new BasicDrag(dragCoef);
454     }
455     
456     /**
457      * Creates a basic vortex.
458      * 
459      * @param strength
460      *            Max strength of vortex.
461      * @param divergence
462      *            The divergence in radians from the tangent vector
463      * @param axis
464      *            The center of the vortex.
465      * @param random
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
470      */
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,
475             transformWithScene);
476     }
477 }