diff --git a/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java b/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java index 28bfd595d..396906fa7 100644 --- a/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java +++ b/jme3-core/src/main/java/com/jme3/effect/ParticleEmitter.java @@ -1092,7 +1092,8 @@ public class ParticleEmitter extends Geometry { inverseRotation = this.getWorldRotation().toRotationMatrix(vars.tempMat3).invertLocal(); } - particleMesh.updateParticleData(particles, cam, inverseRotation); + particleMesh.updateParticleData(rm, particles, cam, inverseRotation); + if (!worldSpace) { vars.release(); } @@ -1100,7 +1101,7 @@ public class ParticleEmitter extends Geometry { public void preload(RenderManager rm, ViewPort vp) { this.updateParticleState(0); - particleMesh.updateParticleData(particles, vp.getCamera(), Matrix3f.IDENTITY); + particleMesh.updateParticleData(rm, particles, vp.getCamera(), Matrix3f.IDENTITY); } @Override diff --git a/jme3-core/src/main/java/com/jme3/effect/ParticleMesh.java b/jme3-core/src/main/java/com/jme3/effect/ParticleMesh.java index ed1b80d2a..c1da2aae8 100644 --- a/jme3-core/src/main/java/com/jme3/effect/ParticleMesh.java +++ b/jme3-core/src/main/java/com/jme3/effect/ParticleMesh.java @@ -34,6 +34,7 @@ package com.jme3.effect; import com.jme3.material.RenderState; import com.jme3.math.Matrix3f; import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; import com.jme3.scene.Mesh; /** @@ -80,6 +81,6 @@ public abstract class ParticleMesh extends Mesh { /** * Update the particle visual data. Typically called every frame. */ - public abstract void updateParticleData(Particle[] particles, Camera cam, Matrix3f inverseRotation); + public abstract void updateParticleData(RenderManager rm, Particle[] particles, Camera cam, Matrix3f inverseRotation); } diff --git a/jme3-core/src/main/java/com/jme3/effect/ParticlePointMesh.java b/jme3-core/src/main/java/com/jme3/effect/ParticlePointMesh.java index 3f56e483b..858f4029d 100644 --- a/jme3-core/src/main/java/com/jme3/effect/ParticlePointMesh.java +++ b/jme3-core/src/main/java/com/jme3/effect/ParticlePointMesh.java @@ -33,15 +33,22 @@ package com.jme3.effect; import com.jme3.math.Matrix3f; import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer.Format; import com.jme3.scene.VertexBuffer.Usage; import com.jme3.util.BufferUtils; +import com.jme3.util.TempVars; import java.nio.ByteBuffer; -import java.nio.FloatBuffer; public class ParticlePointMesh extends ParticleMesh { + private static final int POS_SIZE = 3 * 4; + private static final int COLOR_SIZE = 4 * 1; + private static final int SIZE_SIZE = 1 * 4; + private static final int UV_SIZE = 4 * 4; + private static final int TOTAL_SIZE = POS_SIZE + COLOR_SIZE + SIZE_SIZE + UV_SIZE; + private ParticleEmitter emitter; private int imagesX = 1; @@ -59,109 +66,86 @@ public class ParticlePointMesh extends ParticleMesh { this.emitter = emitter; - // set positions - FloatBuffer pb = BufferUtils.createVector3Buffer(numParticles); - - //if the buffer is already set only update the data - VertexBuffer buf = getBuffer(VertexBuffer.Type.Position); - if (buf != null) { - buf.updateData(pb); - } else { - VertexBuffer pvb = new VertexBuffer(VertexBuffer.Type.Position); - pvb.setupData(Usage.Stream, 3, Format.Float, pb); - setBuffer(pvb); - } - - // set colors - ByteBuffer cb = BufferUtils.createByteBuffer(numParticles * 4); - - buf = getBuffer(VertexBuffer.Type.Color); - if (buf != null) { - buf.updateData(cb); - } else { - VertexBuffer cvb = new VertexBuffer(VertexBuffer.Type.Color); - cvb.setupData(Usage.Stream, 4, Format.UnsignedByte, cb); - cvb.setNormalized(true); - setBuffer(cvb); - } + ByteBuffer eb = BufferUtils.createByteBuffer(TOTAL_SIZE * numParticles); + VertexBuffer vb = new VertexBuffer(VertexBuffer.Type.InterleavedData); + vb.setupData(Usage.Stream, 1, Format.Byte, eb); + setBuffer(vb); + + VertexBuffer pb = new VertexBuffer(VertexBuffer.Type.Position); + pb.setupData(Usage.Stream, 3, Format.Float, eb); + pb.updateData(null); + pb.setOffset(0); + pb.setStride(TOTAL_SIZE); + setBuffer(pb); + + VertexBuffer cb = new VertexBuffer(VertexBuffer.Type.Color); + cb.setupData(Usage.Stream, 4, Format.UnsignedByte, eb); + cb.updateData(null); + cb.setNormalized(true); + cb.setOffset(POS_SIZE); + cb.setStride(TOTAL_SIZE); + setBuffer(cb); + + VertexBuffer sb = new VertexBuffer(VertexBuffer.Type.Size); + sb.setupData(Usage.Stream, 1, Format.Float, eb); + sb.updateData(null); + sb.setOffset(POS_SIZE + COLOR_SIZE); + sb.setStride(TOTAL_SIZE); + setBuffer(sb); + + VertexBuffer tb = new VertexBuffer(VertexBuffer.Type.TexCoord); + tb.setupData(Usage.Stream, 4, Format.Float, eb); + tb.updateData(null); + tb.setOffset(POS_SIZE + COLOR_SIZE + SIZE_SIZE); + tb.setStride(TOTAL_SIZE); + setBuffer(tb); - // set sizes - FloatBuffer sb = BufferUtils.createFloatBuffer(numParticles); - - buf = getBuffer(VertexBuffer.Type.Size); - if (buf != null) { - buf.updateData(sb); - } else { - VertexBuffer svb = new VertexBuffer(VertexBuffer.Type.Size); - svb.setupData(Usage.Stream, 1, Format.Float, sb); - setBuffer(svb); - } - - // set UV-scale - FloatBuffer tb = BufferUtils.createFloatBuffer(numParticles*4); - - buf = getBuffer(VertexBuffer.Type.TexCoord); - if (buf != null) { - buf.updateData(tb); - } else { - VertexBuffer tvb = new VertexBuffer(VertexBuffer.Type.TexCoord); - tvb.setupData(Usage.Stream, 4, Format.Float, tb); - setBuffer(tvb); - } - updateCounts(); } @Override - public void updateParticleData(Particle[] particles, Camera cam, Matrix3f inverseRotation) { - VertexBuffer pvb = getBuffer(VertexBuffer.Type.Position); - FloatBuffer positions = (FloatBuffer) pvb.getData(); + public void updateParticleData(RenderManager rm, Particle[] particles, Camera cam, Matrix3f inverseRotation) { + VertexBuffer eb = getBuffer(VertexBuffer.Type.InterleavedData); + ByteBuffer elements = (ByteBuffer) eb.getData(); - VertexBuffer cvb = getBuffer(VertexBuffer.Type.Color); - ByteBuffer colors = (ByteBuffer) cvb.getData(); + float sizeScale = emitter.getWorldScale().x; - VertexBuffer svb = getBuffer(VertexBuffer.Type.Size); - FloatBuffer sizes = (FloatBuffer) svb.getData(); + TempVars vars = TempVars.get(); + try { + float[] temp = vars.skinTangents; + int index = 0; - VertexBuffer tvb = getBuffer(VertexBuffer.Type.TexCoord); - FloatBuffer texcoords = (FloatBuffer) tvb.getData(); + for (int i = 0; i < particles.length; i++) { + Particle p = particles[i]; - float sizeScale = emitter.getWorldScale().x; + temp[index++] = p.position.x; + temp[index++] = p.position.y; + temp[index++] = p.position.z; + temp[index++] = Float.intBitsToFloat(p.color.asIntABGR()); + temp[index++] = p.size * sizeScale; + + int imgX = p.imageIndex % imagesX; + int imgY = (p.imageIndex - imgX) / imagesY; + + float startX = ((float) imgX) / imagesX; + float startY = ((float) imgY) / imagesY; + float endX = startX + (1f / imagesX); + float endY = startY + (1f / imagesY); + + temp[index++] = startX; + temp[index++] = startY; + temp[index++] = endX; + temp[index++] = endY; + } + + elements.asFloatBuffer().put(temp, 0, (TOTAL_SIZE / 4) * particles.length).flip(); + + eb.updateData(elements); - // update data in vertex buffers - positions.rewind(); - colors.rewind(); - sizes.rewind(); - texcoords.rewind(); - for (int i = 0; i < particles.length; i++){ - Particle p = particles[i]; - - positions.put(p.position.x) - .put(p.position.y) - .put(p.position.z); - - sizes.put(p.size * sizeScale); - colors.putInt(p.color.asIntABGR()); - - int imgX = p.imageIndex % imagesX; - int imgY = (p.imageIndex - imgX) / imagesY; - - float startX = ((float) imgX) / imagesX; - float startY = ((float) imgY) / imagesY; - float endX = startX + (1f / imagesX); - float endY = startY + (1f / imagesY); - - texcoords.put(startX).put(startY).put(endX).put(endY); + // cheating! + rm.getRenderer().updateBufferData(eb); + } finally { + vars.release(); } - positions.flip(); - colors.flip(); - sizes.flip(); - texcoords.flip(); - - // force renderer to re-send data to GPU - pvb.updateData(positions); - cvb.updateData(colors); - svb.updateData(sizes); - tvb.updateData(texcoords); } } diff --git a/jme3-core/src/main/java/com/jme3/effect/ParticleTriMesh.java b/jme3-core/src/main/java/com/jme3/effect/ParticleTriMesh.java index 8002197b0..fdc7f633d 100644 --- a/jme3-core/src/main/java/com/jme3/effect/ParticleTriMesh.java +++ b/jme3-core/src/main/java/com/jme3/effect/ParticleTriMesh.java @@ -35,6 +35,7 @@ import com.jme3.math.FastMath; import com.jme3.math.Matrix3f; import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer.Format; import com.jme3.scene.VertexBuffer.Usage; @@ -145,7 +146,7 @@ public class ParticleTriMesh extends ParticleMesh { } @Override - public void updateParticleData(Particle[] particles, Camera cam, Matrix3f inverseRotation) { + public void updateParticleData(RenderManager rm, Particle[] particles, Camera cam, Matrix3f inverseRotation) { // System.arraycopy(particles, 0, particlesCopy, 0, particlesCopy.length); // comparator.setCamera(cam); // Arrays.sort(particlesCopy, comparator); diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 8a13d9624..cdc9efcaa 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -2680,6 +2680,10 @@ public final class GLRenderer implements Renderer { private void setupVertexBuffers(Mesh mesh, VertexBuffer[] instanceData) { VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); + if (interleavedData != null && interleavedData.isUpdateNeeded()) { + updateBufferData(interleavedData); + } + if (instanceData != null) { for (VertexBuffer vb : instanceData) { setVertexAttribVAO(vb, null); @@ -2707,9 +2711,7 @@ public final class GLRenderer implements Renderer { private void updateVertexBuffers(Mesh mesh, VertexBuffer[] instanceData) { VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); - if (interleavedData != null && interleavedData.isUpdateNeeded()) { - updateBufferData(interleavedData); - } + if (instanceData != null) { for (VertexBuffer vb : instanceData) { if (vb.isUpdateNeeded()) { @@ -2717,6 +2719,14 @@ public final class GLRenderer implements Renderer { } } } + + if (interleavedData != null) { + if (interleavedData.isUpdateNeeded()) { + updateBufferData(interleavedData); + } + return; + } + for (VertexBuffer vb : mesh.getBufferList().getArray()) { if (vb.getBufferType() == Type.InterleavedData || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers diff --git a/jme3-core/src/main/java/com/jme3/scene/Mesh.java b/jme3-core/src/main/java/com/jme3/scene/Mesh.java index a38bf0447..628af069a 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Mesh.java +++ b/jme3-core/src/main/java/com/jme3/scene/Mesh.java @@ -713,13 +713,21 @@ public class Mesh extends NativeObject implements Savable { * {@link #setInterleaved() interleaved} format. */ public void updateCounts(){ - if (getBuffer(Type.InterleavedData) != null) - throw new IllegalStateException("Should update counts before interleave"); +// if (getBuffer(Type.InterleavedData) != null) { +// throw new IllegalStateException("Should update counts before interleave"); +// } VertexBuffer pb = getBuffer(Type.Position); VertexBuffer ib = getBuffer(Type.Index); - if (pb != null){ - vertCount = pb.getData().limit() / pb.getNumComponents(); + if (pb != null) { + VertexBuffer ip = getBuffer(Type.InterleavedData); + if (ip != null) { + int limitBytes = ip.getData().limit(); + int elementSizeWithOthers = pb.getStride(); + vertCount = limitBytes / elementSizeWithOthers; + } else { + vertCount = pb.getData().limit() / pb.getNumComponents(); + } } if (ib != null){ elementCount = computeNumElements(ib.getData().limit()); diff --git a/jme3-core/src/main/resources/Common/MatDefs/Misc/Particle.vert b/jme3-core/src/main/resources/Common/MatDefs/Misc/Particle.vert index 878c8e6da..705936943 100644 --- a/jme3-core/src/main/resources/Common/MatDefs/Misc/Particle.vert +++ b/jme3-core/src/main/resources/Common/MatDefs/Misc/Particle.vert @@ -32,7 +32,7 @@ void main(){ #ifdef POINT_SPRITE vec4 worldPos = g_WorldMatrix * pos; float d = distance(g_CameraPosition.xyz, worldPos.xyz); - float size = (inSize * SIZE_MULTIPLIER * m_Quadratic) / d); + float size = (inSize * SIZE_MULTIPLIER * m_Quadratic) / d; gl_PointSize = max(1.0, size); //vec4 worldViewPos = g_WorldViewMatrix * pos;