mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-03-15 02:10:55 +00:00
various fixes and performance improvements
This commit is contained in:
parent
cb28b66dad
commit
0c9ddb476a
62 changed files with 3109 additions and 1286 deletions
|
|
@ -295,6 +295,17 @@ export class EmitterInstance {
|
|||
|
||||
if (this.particles.length < this.maxParticles) {
|
||||
this.addParticle(pos, axis);
|
||||
|
||||
// V12: when overrideAdvances is false, immediately age the newly
|
||||
// spawned particle by the remaining time in this frame. If that
|
||||
// exceeds its lifetime, kill it immediately (never rendered).
|
||||
if (!this.data.overrideAdvances && timeLeft > 0) {
|
||||
const p = this.particles[this.particles.length - 1];
|
||||
p.currentAge += timeLeft;
|
||||
if (p.currentAge >= p.totalLifetime) {
|
||||
this.particles.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute next emission time.
|
||||
|
|
@ -310,10 +321,10 @@ export class EmitterInstance {
|
|||
update(dtMS: number): void {
|
||||
this.emitterAge += dtMS;
|
||||
|
||||
// Check emitter lifetime.
|
||||
// Check emitter lifetime (V12 uses strictly greater).
|
||||
if (
|
||||
this.emitterLifetime > 0 &&
|
||||
this.emitterAge >= this.emitterLifetime
|
||||
this.emitterAge > this.emitterLifetime
|
||||
) {
|
||||
this.emitterDead = true;
|
||||
}
|
||||
|
|
@ -339,9 +350,9 @@ export class EmitterInstance {
|
|||
|
||||
// a = acc - vel*drag - wind*windCoeff + gravity*gravCoeff
|
||||
// We skip wind for now (no wind system yet).
|
||||
const ax = -p.vel[0] * drag;
|
||||
const ay = -p.vel[1] * drag;
|
||||
const az = -p.vel[2] * drag + GRAVITY_Z * gravCoeff;
|
||||
const ax = p.acc[0] - p.vel[0] * drag;
|
||||
const ay = p.acc[1] - p.vel[1] * drag;
|
||||
const az = p.acc[2] - p.vel[2] * drag + GRAVITY_Z * gravCoeff;
|
||||
|
||||
// Symplectic Euler: update vel first, then pos with new vel.
|
||||
p.vel[0] += ax * dt;
|
||||
|
|
@ -430,14 +441,13 @@ export class EmitterInstance {
|
|||
ejZ * speed,
|
||||
];
|
||||
|
||||
// V12: acc = vel * constantAcceleration (set once, never changes).
|
||||
// We fold this into the initial velocity for simplicity since the
|
||||
// constant acceleration just biases the starting velocity direction.
|
||||
// Actually, in V12 acc is a separate constant vector added each frame.
|
||||
// For faithfulness, we should track it. But since it's constant, we can
|
||||
// just apply it in the update loop as a per-particle property.
|
||||
// For now, bake it into the velocity since most Tribes 2 datablocks
|
||||
// have constantAcceleration = 0.
|
||||
// V12: acc = vel * constantAcceleration, set once at spawn, applied every frame.
|
||||
const ca = pData.constantAcceleration;
|
||||
const acc: [number, number, number] = [
|
||||
vel[0] * ca,
|
||||
vel[1] * ca,
|
||||
vel[2] * ca,
|
||||
];
|
||||
|
||||
// Particle lifetime with variance.
|
||||
let lifetime = pData.lifetimeMS;
|
||||
|
|
@ -456,6 +466,7 @@ export class EmitterInstance {
|
|||
this.particles.push({
|
||||
pos: spawnPos,
|
||||
vel,
|
||||
acc,
|
||||
orientDir: [ejX, ejY, ejZ],
|
||||
currentAge: 0,
|
||||
totalLifetime: lifetime,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ attribute vec4 particleColor;
|
|||
attribute float particleSize;
|
||||
attribute float particleSpin;
|
||||
attribute vec2 quadCorner; // (-0.5,-0.5) to (0.5,0.5)
|
||||
attribute vec3 orientDir;
|
||||
|
||||
uniform bool uOrientParticles;
|
||||
// cameraPosition is a built-in Three.js uniform.
|
||||
|
||||
varying vec2 vUv;
|
||||
varying vec4 vColor;
|
||||
|
|
@ -12,27 +16,47 @@ void main() {
|
|||
vUv = quadCorner + 0.5; // [0,1] range
|
||||
vColor = particleColor;
|
||||
|
||||
// Transform particle center to view space for billboarding.
|
||||
vec3 viewPos = (modelViewMatrix * vec4(position, 1.0)).xyz;
|
||||
if (uOrientParticles) {
|
||||
if (length(orientDir) < 0.0001) {
|
||||
// V12: don't render oriented particles with zero velocity.
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
return;
|
||||
}
|
||||
// V12 oriented particle: quad aligned along direction, facing camera.
|
||||
vec3 worldPos = (modelMatrix * vec4(position, 1.0)).xyz;
|
||||
vec3 dir = normalize(orientDir);
|
||||
vec3 dirFromCam = worldPos - cameraPosition;
|
||||
vec3 crossDir = normalize(cross(dirFromCam, dir));
|
||||
|
||||
// Apply spin rotation to quad corner.
|
||||
float c = cos(particleSpin);
|
||||
float s = sin(particleSpin);
|
||||
vec2 rotated = vec2(
|
||||
c * quadCorner.x - s * quadCorner.y,
|
||||
s * quadCorner.x + c * quadCorner.y
|
||||
);
|
||||
// V12 maps U along dir (velocity) — match by using quadCorner.x for dir.
|
||||
vec3 offset = dir * quadCorner.x + crossDir * quadCorner.y;
|
||||
worldPos += offset * particleSize;
|
||||
|
||||
// Offset in view space (camera-facing billboard).
|
||||
viewPos.xy += rotated * particleSize;
|
||||
gl_Position = projectionMatrix * viewMatrix * vec4(worldPos, 1.0);
|
||||
} else {
|
||||
// Standard camera-facing billboard.
|
||||
vec3 viewPos = (modelViewMatrix * vec4(position, 1.0)).xyz;
|
||||
|
||||
gl_Position = projectionMatrix * vec4(viewPos, 1.0);
|
||||
// Apply spin rotation to quad corner.
|
||||
float c = cos(particleSpin);
|
||||
float s = sin(particleSpin);
|
||||
vec2 rotated = vec2(
|
||||
c * quadCorner.x - s * quadCorner.y,
|
||||
s * quadCorner.x + c * quadCorner.y
|
||||
);
|
||||
|
||||
// Offset in view space (camera-facing billboard).
|
||||
viewPos.xy += rotated * particleSize;
|
||||
|
||||
gl_Position = projectionMatrix * vec4(viewPos, 1.0);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const particleFragmentShader = /* glsl */ `
|
||||
uniform sampler2D particleTexture;
|
||||
uniform bool hasTexture;
|
||||
uniform float debugOpacity;
|
||||
|
||||
varying vec2 vUv;
|
||||
varying vec4 vColor;
|
||||
|
|
@ -44,5 +68,6 @@ void main() {
|
|||
} else {
|
||||
gl_FragColor = vColor;
|
||||
}
|
||||
gl_FragColor.a *= debugOpacity;
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ export interface EmitterDataResolved {
|
|||
export interface Particle {
|
||||
pos: [number, number, number];
|
||||
vel: [number, number, number];
|
||||
/** V12: constant acceleration = vel * constantAcceleration, set once at spawn. */
|
||||
acc: [number, number, number];
|
||||
orientDir: [number, number, number];
|
||||
currentAge: number;
|
||||
totalLifetime: number;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue