• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2010 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.jme3.effect;
34 
35 import com.jme3.math.FastMath;
36 import com.jme3.math.Matrix3f;
37 import com.jme3.math.Vector3f;
38 import com.jme3.renderer.Camera;
39 import com.jme3.scene.VertexBuffer;
40 import com.jme3.scene.VertexBuffer.Format;
41 import com.jme3.scene.VertexBuffer.Usage;
42 import com.jme3.util.BufferUtils;
43 import com.jme3.util.SortUtil;
44 import java.nio.ByteBuffer;
45 import java.nio.FloatBuffer;
46 import java.nio.ShortBuffer;
47 
48 public class ParticleTriMesh extends ParticleMesh {
49 
50     private int imagesX = 1;
51     private int imagesY = 1;
52     private boolean uniqueTexCoords = false;
53     private ParticleComparator comparator = new ParticleComparator();
54     private ParticleEmitter emitter;
55     private Particle[] particlesCopy;
56 
57     @Override
initParticleData(ParticleEmitter emitter, int numParticles)58     public void initParticleData(ParticleEmitter emitter, int numParticles) {
59         setMode(Mode.Triangles);
60 
61         this.emitter = emitter;
62 
63         particlesCopy = new Particle[numParticles];
64 
65         // set positions
66         FloatBuffer pb = BufferUtils.createVector3Buffer(numParticles * 4);
67         VertexBuffer pvb = new VertexBuffer(VertexBuffer.Type.Position);
68         pvb.setupData(Usage.Stream, 3, Format.Float, pb);
69 
70         //if the buffer is already set only update the data
71         VertexBuffer buf = getBuffer(VertexBuffer.Type.Position);
72         if (buf != null) {
73             buf.updateData(pb);
74         } else {
75             setBuffer(pvb);
76         }
77 
78         // set colors
79         ByteBuffer cb = BufferUtils.createByteBuffer(numParticles * 4 * 4);
80         VertexBuffer cvb = new VertexBuffer(VertexBuffer.Type.Color);
81         cvb.setupData(Usage.Stream, 4, Format.UnsignedByte, cb);
82         cvb.setNormalized(true);
83 
84         buf = getBuffer(VertexBuffer.Type.Color);
85         if (buf != null) {
86             buf.updateData(cb);
87         } else {
88             setBuffer(cvb);
89         }
90 
91         // set texcoords
92         VertexBuffer tvb = new VertexBuffer(VertexBuffer.Type.TexCoord);
93         FloatBuffer tb = BufferUtils.createVector2Buffer(numParticles * 4);
94 
95         uniqueTexCoords = false;
96         for (int i = 0; i < numParticles; i++){
97             tb.put(0f).put(1f);
98             tb.put(1f).put(1f);
99             tb.put(0f).put(0f);
100             tb.put(1f).put(0f);
101         }
102         tb.flip();
103         tvb.setupData(Usage.Static, 2, Format.Float, tb);
104 
105         buf = getBuffer(VertexBuffer.Type.TexCoord);
106         if (buf != null) {
107             buf.updateData(tb);
108         } else {
109             setBuffer(tvb);
110         }
111 
112         // set indices
113         ShortBuffer ib = BufferUtils.createShortBuffer(numParticles * 6);
114         for (int i = 0; i < numParticles; i++){
115             int startIdx = (i * 4);
116 
117             // triangle 1
118             ib.put((short)(startIdx + 1))
119               .put((short)(startIdx + 0))
120               .put((short)(startIdx + 2));
121 
122             // triangle 2
123             ib.put((short)(startIdx + 1))
124               .put((short)(startIdx + 2))
125               .put((short)(startIdx + 3));
126         }
127         ib.flip();
128 
129         VertexBuffer ivb = new VertexBuffer(VertexBuffer.Type.Index);
130         ivb.setupData(Usage.Static, 3, Format.UnsignedShort, ib);
131 
132         buf = getBuffer(VertexBuffer.Type.Index);
133         if (buf != null) {
134             buf.updateData(ib);
135         } else {
136             setBuffer(ivb);
137         }
138 
139     }
140 
141     @Override
setImagesXY(int imagesX, int imagesY)142     public void setImagesXY(int imagesX, int imagesY) {
143         this.imagesX = imagesX;
144         this.imagesY = imagesY;
145         if (imagesX != 1 || imagesY != 1){
146             uniqueTexCoords = true;
147             getBuffer(VertexBuffer.Type.TexCoord).setUsage(Usage.Stream);
148         }
149     }
150 
151     @Override
updateParticleData(Particle[] particles, Camera cam, Matrix3f inverseRotation)152     public void updateParticleData(Particle[] particles, Camera cam, Matrix3f inverseRotation) {
153         System.arraycopy(particles, 0, particlesCopy, 0, particlesCopy.length);
154         comparator.setCamera(cam);
155 //        Arrays.sort(particlesCopy, comparator);
156 //        SortUtil.qsort(particlesCopy, comparator);
157         SortUtil.msort(particles, particlesCopy, comparator);
158         particles = particlesCopy;
159 
160         VertexBuffer pvb = getBuffer(VertexBuffer.Type.Position);
161         FloatBuffer positions = (FloatBuffer) pvb.getData();
162 
163         VertexBuffer cvb = getBuffer(VertexBuffer.Type.Color);
164         ByteBuffer colors = (ByteBuffer) cvb.getData();
165 
166         VertexBuffer tvb = getBuffer(VertexBuffer.Type.TexCoord);
167         FloatBuffer texcoords = (FloatBuffer) tvb.getData();
168 
169         Vector3f camUp   = cam.getUp();
170         Vector3f camLeft = cam.getLeft();
171         Vector3f camDir  = cam.getDirection();
172 
173         inverseRotation.multLocal(camUp);
174         inverseRotation.multLocal(camLeft);
175         inverseRotation.multLocal(camDir);
176 
177         boolean facingVelocity = emitter.isFacingVelocity();
178 
179         Vector3f up = new Vector3f(),
180                  left = new Vector3f();
181 
182         if (!facingVelocity){
183             up.set(camUp);
184             left.set(camLeft);
185         }
186 
187         // update data in vertex buffers
188         positions.clear();
189         colors.clear();
190         texcoords.clear();
191         Vector3f faceNormal = emitter.getFaceNormal();
192 
193         for (int i = 0; i < particles.length; i++){
194             Particle p = particles[i];
195             boolean dead = p.life == 0;
196             if (dead){
197                 positions.put(0).put(0).put(0);
198                 positions.put(0).put(0).put(0);
199                 positions.put(0).put(0).put(0);
200                 positions.put(0).put(0).put(0);
201                 continue;
202             }
203 
204             if (facingVelocity){
205                 left.set(p.velocity).normalizeLocal();
206                 camDir.cross(left, up);
207                 up.multLocal(p.size);
208                 left.multLocal(p.size);
209             }else if (faceNormal != null){
210                 up.set(faceNormal).crossLocal(Vector3f.UNIT_X);
211                 faceNormal.cross(up, left);
212                 up.multLocal(p.size);
213                 left.multLocal(p.size);
214             }else if (p.angle != 0){
215                 float cos = FastMath.cos(p.angle) * p.size;
216                 float sin = FastMath.sin(p.angle) * p.size;
217 
218                 left.x = camLeft.x * cos + camUp.x * sin;
219                 left.y = camLeft.y * cos + camUp.y * sin;
220                 left.z = camLeft.z * cos + camUp.z * sin;
221 
222                 up.x = camLeft.x * -sin + camUp.x * cos;
223                 up.y = camLeft.y * -sin + camUp.y * cos;
224                 up.z = camLeft.z * -sin + camUp.z * cos;
225             }else{
226                 up.set(camUp);
227                 left.set(camLeft);
228                 up.multLocal(p.size);
229                 left.multLocal(p.size);
230             }
231 
232             positions.put(p.position.x + left.x + up.x)
233                      .put(p.position.y + left.y + up.y)
234                      .put(p.position.z + left.z + up.z);
235 
236             positions.put(p.position.x - left.x + up.x)
237                      .put(p.position.y - left.y + up.y)
238                      .put(p.position.z - left.z + up.z);
239 
240             positions.put(p.position.x + left.x - up.x)
241                      .put(p.position.y + left.y - up.y)
242                      .put(p.position.z + left.z - up.z);
243 
244             positions.put(p.position.x - left.x - up.x)
245                      .put(p.position.y - left.y - up.y)
246                      .put(p.position.z - left.z - up.z);
247 
248             if (uniqueTexCoords){
249                 int imgX = p.imageIndex % imagesX;
250                 int imgY = (p.imageIndex - imgX) / imagesY;
251 
252                 float startX = ((float) imgX) / imagesX;
253                 float startY = ((float) imgY) / imagesY;
254                 float endX   = startX + (1f / imagesX);
255                 float endY   = startY + (1f / imagesY);
256 
257                 texcoords.put(startX).put(endY);
258                 texcoords.put(endX).put(endY);
259                 texcoords.put(startX).put(startY);
260                 texcoords.put(endX).put(startY);
261             }
262 
263             int abgr = p.color.asIntABGR();
264             colors.putInt(abgr);
265             colors.putInt(abgr);
266             colors.putInt(abgr);
267             colors.putInt(abgr);
268         }
269 
270         positions.clear();
271         colors.clear();
272         if (!uniqueTexCoords)
273             texcoords.clear();
274         else{
275             texcoords.clear();
276             tvb.updateData(texcoords);
277         }
278 
279         // force renderer to re-send data to GPU
280         pvb.updateData(positions);
281         cvb.updateData(colors);
282     }
283 
284 }
285