159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer in the
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   documentation and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   may be used to endorse or promote products derived from this software
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   without specific prior written permission.
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.effect;
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.FastMath;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Matrix3f;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f;
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.Camera;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Format;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Usage;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils;
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.SortUtil;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.ByteBuffer;
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.FloatBuffer;
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.ShortBuffer;
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class ParticleTriMesh extends ParticleMesh {
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int imagesX = 1;
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int imagesY = 1;
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private boolean uniqueTexCoords = false;
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private ParticleComparator comparator = new ParticleComparator();
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private ParticleEmitter emitter;
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Particle[] particlesCopy;
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void initParticleData(ParticleEmitter emitter, int numParticles) {
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setMode(Mode.Triangles);
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.emitter = emitter;
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        particlesCopy = new Particle[numParticles];
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // set positions
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FloatBuffer pb = BufferUtils.createVector3Buffer(numParticles * 4);
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer pvb = new VertexBuffer(VertexBuffer.Type.Position);
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        pvb.setupData(Usage.Stream, 3, Format.Float, pb);
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //if the buffer is already set only update the data
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer buf = getBuffer(VertexBuffer.Type.Position);
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (buf != null) {
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            buf.updateData(pb);
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            setBuffer(pvb);
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // set colors
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ByteBuffer cb = BufferUtils.createByteBuffer(numParticles * 4 * 4);
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer cvb = new VertexBuffer(VertexBuffer.Type.Color);
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        cvb.setupData(Usage.Stream, 4, Format.UnsignedByte, cb);
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        cvb.setNormalized(true);
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        buf = getBuffer(VertexBuffer.Type.Color);
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (buf != null) {
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            buf.updateData(cb);
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            setBuffer(cvb);
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // set texcoords
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer tvb = new VertexBuffer(VertexBuffer.Type.TexCoord);
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FloatBuffer tb = BufferUtils.createVector2Buffer(numParticles * 4);
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        uniqueTexCoords = false;
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < numParticles; i++){
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            tb.put(0f).put(1f);
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            tb.put(1f).put(1f);
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            tb.put(0f).put(0f);
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            tb.put(1f).put(0f);
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        tb.flip();
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        tvb.setupData(Usage.Static, 2, Format.Float, tb);
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        buf = getBuffer(VertexBuffer.Type.TexCoord);
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (buf != null) {
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            buf.updateData(tb);
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            setBuffer(tvb);
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // set indices
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ShortBuffer ib = BufferUtils.createShortBuffer(numParticles * 6);
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < numParticles; i++){
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int startIdx = (i * 4);
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // triangle 1
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            ib.put((short)(startIdx + 1))
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta              .put((short)(startIdx + 0))
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta              .put((short)(startIdx + 2));
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // triangle 2
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            ib.put((short)(startIdx + 1))
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta              .put((short)(startIdx + 2))
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta              .put((short)(startIdx + 3));
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ib.flip();
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer ivb = new VertexBuffer(VertexBuffer.Type.Index);
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ivb.setupData(Usage.Static, 3, Format.UnsignedShort, ib);
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        buf = getBuffer(VertexBuffer.Type.Index);
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (buf != null) {
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            buf.updateData(ib);
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            setBuffer(ivb);
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setImagesXY(int imagesX, int imagesY) {
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.imagesX = imagesX;
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.imagesY = imagesY;
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (imagesX != 1 || imagesY != 1){
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            uniqueTexCoords = true;
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            getBuffer(VertexBuffer.Type.TexCoord).setUsage(Usage.Stream);
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateParticleData(Particle[] particles, Camera cam, Matrix3f inverseRotation) {
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.arraycopy(particles, 0, particlesCopy, 0, particlesCopy.length);
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        comparator.setCamera(cam);
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        Arrays.sort(particlesCopy, comparator);
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        SortUtil.qsort(particlesCopy, comparator);
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        SortUtil.msort(particles, particlesCopy, comparator);
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        particles = particlesCopy;
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer pvb = getBuffer(VertexBuffer.Type.Position);
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FloatBuffer positions = (FloatBuffer) pvb.getData();
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer cvb = getBuffer(VertexBuffer.Type.Color);
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ByteBuffer colors = (ByteBuffer) cvb.getData();
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer tvb = getBuffer(VertexBuffer.Type.TexCoord);
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FloatBuffer texcoords = (FloatBuffer) tvb.getData();
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f camUp   = cam.getUp();
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f camLeft = cam.getLeft();
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f camDir  = cam.getDirection();
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        inverseRotation.multLocal(camUp);
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        inverseRotation.multLocal(camLeft);
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        inverseRotation.multLocal(camDir);
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean facingVelocity = emitter.isFacingVelocity();
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f up = new Vector3f(),
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                 left = new Vector3f();
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!facingVelocity){
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            up.set(camUp);
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            left.set(camLeft);
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // update data in vertex buffers
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        positions.clear();
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        colors.clear();
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        texcoords.clear();
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f faceNormal = emitter.getFaceNormal();
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < particles.length; i++){
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Particle p = particles[i];
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            boolean dead = p.life == 0;
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (dead){
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                positions.put(0).put(0).put(0);
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                positions.put(0).put(0).put(0);
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                positions.put(0).put(0).put(0);
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                positions.put(0).put(0).put(0);
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                continue;
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (facingVelocity){
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                left.set(p.velocity).normalizeLocal();
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                camDir.cross(left, up);
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                up.multLocal(p.size);
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                left.multLocal(p.size);
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else if (faceNormal != null){
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                up.set(faceNormal).crossLocal(Vector3f.UNIT_X);
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                faceNormal.cross(up, left);
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                up.multLocal(p.size);
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                left.multLocal(p.size);
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else if (p.angle != 0){
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float cos = FastMath.cos(p.angle) * p.size;
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float sin = FastMath.sin(p.angle) * p.size;
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                left.x = camLeft.x * cos + camUp.x * sin;
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                left.y = camLeft.y * cos + camUp.y * sin;
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                left.z = camLeft.z * cos + camUp.z * sin;
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                up.x = camLeft.x * -sin + camUp.x * cos;
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                up.y = camLeft.y * -sin + camUp.y * cos;
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                up.z = camLeft.z * -sin + camUp.z * cos;
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else{
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                up.set(camUp);
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                left.set(camLeft);
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                up.multLocal(p.size);
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                left.multLocal(p.size);
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            positions.put(p.position.x + left.x + up.x)
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                     .put(p.position.y + left.y + up.y)
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                     .put(p.position.z + left.z + up.z);
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            positions.put(p.position.x - left.x + up.x)
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                     .put(p.position.y - left.y + up.y)
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                     .put(p.position.z - left.z + up.z);
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            positions.put(p.position.x + left.x - up.x)
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                     .put(p.position.y + left.y - up.y)
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                     .put(p.position.z + left.z - up.z);
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            positions.put(p.position.x - left.x - up.x)
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                     .put(p.position.y - left.y - up.y)
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                     .put(p.position.z - left.z - up.z);
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (uniqueTexCoords){
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                int imgX = p.imageIndex % imagesX;
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                int imgY = (p.imageIndex - imgX) / imagesY;
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float startX = ((float) imgX) / imagesX;
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float startY = ((float) imgY) / imagesY;
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float endX   = startX + (1f / imagesX);
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float endY   = startY + (1f / imagesY);
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                texcoords.put(startX).put(endY);
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                texcoords.put(endX).put(endY);
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                texcoords.put(startX).put(startY);
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                texcoords.put(endX).put(startY);
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int abgr = p.color.asIntABGR();
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            colors.putInt(abgr);
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            colors.putInt(abgr);
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            colors.putInt(abgr);
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            colors.putInt(abgr);
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        positions.clear();
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        colors.clear();
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!uniqueTexCoords)
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texcoords.clear();
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        else{
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texcoords.clear();
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            tvb.updateData(texcoords);
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // force renderer to re-send data to GPU
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        pvb.updateData(positions);
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        cvb.updateData(colors);
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
285