point particles: various fixes

* support any number of particles by re-using temp buffer
 * fix exception when changing particle count
experimental
Kirill Vainer 9 years ago
parent d76cb99772
commit 8413ed715c
  1. 142
      jme3-core/src/main/java/com/jme3/effect/ParticlePointMesh.java

@ -40,6 +40,7 @@ import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
public class ParticlePointMesh extends ParticleMesh { public class ParticlePointMesh extends ParticleMesh {
@ -47,7 +48,8 @@ public class ParticlePointMesh extends ParticleMesh {
private static final int COLOR_SIZE = 4 * 1; private static final int COLOR_SIZE = 4 * 1;
private static final int SIZE_SIZE = 1 * 4; private static final int SIZE_SIZE = 1 * 4;
private static final int UV_SIZE = 4 * 4; private static final int UV_SIZE = 4 * 4;
private static final int TOTAL_SIZE = POS_SIZE + COLOR_SIZE + SIZE_SIZE + UV_SIZE; private static final int BYTES_PER_PARTICLE = POS_SIZE + COLOR_SIZE + SIZE_SIZE + UV_SIZE;
private static final int FLOATS_PER_PARTICLE = BYTES_PER_PARTICLE / 4;
private ParticleEmitter emitter; private ParticleEmitter emitter;
@ -66,39 +68,46 @@ public class ParticlePointMesh extends ParticleMesh {
this.emitter = emitter; this.emitter = emitter;
ByteBuffer eb = BufferUtils.createByteBuffer(TOTAL_SIZE * numParticles); ByteBuffer eb = BufferUtils.createByteBuffer(BYTES_PER_PARTICLE * numParticles);
VertexBuffer vb = new VertexBuffer(VertexBuffer.Type.InterleavedData); VertexBuffer vb = getBuffer(VertexBuffer.Type.InterleavedData);
vb.setupData(Usage.Stream, 1, Format.Byte, eb); if (vb != null) {
setBuffer(vb); vb.updateData(eb);
} else {
VertexBuffer pb = new VertexBuffer(VertexBuffer.Type.Position); vb = new VertexBuffer(VertexBuffer.Type.InterleavedData);
pb.setupData(Usage.Stream, 3, Format.Float, eb); vb.setupData(Usage.Stream, 1, Format.Byte, eb);
pb.updateData(null); setBuffer(vb);
pb.setOffset(0); }
pb.setStride(TOTAL_SIZE);
setBuffer(pb); if (getBuffer(VertexBuffer.Type.Position) == null) {
VertexBuffer pb = new VertexBuffer(VertexBuffer.Type.Position);
VertexBuffer cb = new VertexBuffer(VertexBuffer.Type.Color); pb.setupData(Usage.Stream, 3, Format.Float, eb);
cb.setupData(Usage.Stream, 4, Format.UnsignedByte, eb); pb.updateData(null);
cb.updateData(null); pb.setOffset(0);
cb.setNormalized(true); pb.setStride(BYTES_PER_PARTICLE);
cb.setOffset(POS_SIZE); setBuffer(pb);
cb.setStride(TOTAL_SIZE);
setBuffer(cb); VertexBuffer cb = new VertexBuffer(VertexBuffer.Type.Color);
cb.setupData(Usage.Stream, 4, Format.UnsignedByte, eb);
VertexBuffer sb = new VertexBuffer(VertexBuffer.Type.Size); cb.updateData(null);
sb.setupData(Usage.Stream, 1, Format.Float, eb); cb.setNormalized(true);
sb.updateData(null); cb.setOffset(POS_SIZE);
sb.setOffset(POS_SIZE + COLOR_SIZE); cb.setStride(BYTES_PER_PARTICLE);
sb.setStride(TOTAL_SIZE); setBuffer(cb);
setBuffer(sb);
VertexBuffer sb = new VertexBuffer(VertexBuffer.Type.Size);
VertexBuffer tb = new VertexBuffer(VertexBuffer.Type.TexCoord); sb.setupData(Usage.Stream, 1, Format.Float, eb);
tb.setupData(Usage.Stream, 4, Format.Float, eb); sb.updateData(null);
tb.updateData(null); sb.setOffset(POS_SIZE + COLOR_SIZE);
tb.setOffset(POS_SIZE + COLOR_SIZE + SIZE_SIZE); sb.setStride(BYTES_PER_PARTICLE);
tb.setStride(TOTAL_SIZE); setBuffer(sb);
setBuffer(tb);
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(BYTES_PER_PARTICLE);
setBuffer(tb);
}
updateCounts(); updateCounts();
} }
@ -107,38 +116,53 @@ public class ParticlePointMesh extends ParticleMesh {
public void updateParticleData(RenderManager rm, Particle[] particles, Camera cam, Matrix3f inverseRotation) { public void updateParticleData(RenderManager rm, Particle[] particles, Camera cam, Matrix3f inverseRotation) {
VertexBuffer eb = getBuffer(VertexBuffer.Type.InterleavedData); VertexBuffer eb = getBuffer(VertexBuffer.Type.InterleavedData);
ByteBuffer elements = (ByteBuffer) eb.getData(); ByteBuffer elements = (ByteBuffer) eb.getData();
FloatBuffer floatElements = elements.asFloatBuffer();
float sizeScale = emitter.getWorldScale().x; float sizeScale = emitter.getWorldScale().x;
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
try { try {
float[] temp = vars.skinTangents; float[] floatArray = vars.skinTangents;
int index = 0;
int particlesPerIteration = floatArray.length / FLOATS_PER_PARTICLE;
for (int i = 0; i < particles.length; i++) { int iterations = (particles.length + particlesPerIteration - 1) / particlesPerIteration;
Particle p = particles[i];
int particleIndex = 0;
temp[index++] = p.position.x; for (int iteration = 0; iteration < iterations; iteration++) {
temp[index++] = p.position.y; int particlesRemaining = Math.min(
temp[index++] = p.position.z; particles.length - particleIndex,
temp[index++] = Float.intBitsToFloat(p.color.asIntABGR()); particlesPerIteration);
temp[index++] = p.size * sizeScale;
int floatIndex = 0;
int imgX = p.imageIndex % imagesX; for (int i = 0; i < particlesRemaining; i++) {
int imgY = (p.imageIndex - imgX) / imagesY; Particle p = particles[particleIndex++];
float startX = ((float) imgX) / imagesX; floatArray[floatIndex++] = p.position.x;
float startY = ((float) imgY) / imagesY; floatArray[floatIndex++] = p.position.y;
float endX = startX + (1f / imagesX); floatArray[floatIndex++] = p.position.z;
float endY = startY + (1f / imagesY); floatArray[floatIndex++] = Float.intBitsToFloat(p.color.asIntABGR());
floatArray[floatIndex++] = p.size * sizeScale;
temp[index++] = startX;
temp[index++] = startY; int imgX = p.imageIndex % imagesX;
temp[index++] = endX; int imgY = (p.imageIndex - imgX) / imagesY;
temp[index++] = endY;
float startX = ((float) imgX) / imagesX;
float startY = ((float) imgY) / imagesY;
float endX = startX + (1f / imagesX);
float endY = startY + (1f / imagesY);
floatArray[floatIndex++] = startX;
floatArray[floatIndex++] = startY;
floatArray[floatIndex++] = endX;
floatArray[floatIndex++] = endY;
}
floatElements.put(floatArray, 0, FLOATS_PER_PARTICLE * particlesRemaining);
} }
elements.asFloatBuffer().put(temp, 0, (TOTAL_SIZE / 4) * particles.length).flip(); if (floatElements.remaining() != 0) {
throw new IllegalStateException();
}
eb.updateData(elements); eb.updateData(elements);

Loading…
Cancel
Save