Home | History | Annotate | Download | only in effect
      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
     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
    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
    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