Pārlūkot izejas kodu

correctly handle movement of emitter w/ amount variation

ncannasse 8 gadi atpakaļ
vecāks
revīzija
0990c3983f
1 mainītis faili ar 36 papildinājumiem un 9 dzēšanām
  1. 36 9
      h3d/parts/GpuParticles.hx

+ 36 - 9
h3d/parts/GpuParticles.hx

@@ -389,6 +389,8 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 	var resourcePath : String;
 	var partAlloc : GpuPart;
 	var rnd = new hxd.Rand(0);
+	var lastMove : Float;
+
 	public var seed(default, set) : Int	= Std.random(0x1000000);
 	public var volumeBounds(default, set) : h3d.col.Bounds;
 	public var currentTime : Float = 0.;
@@ -496,6 +498,11 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 		return groups.iterator();
 	}
 
+	override function calcAbsPos() {
+		super.calcAbsPos();
+		lastMove = currentTime;
+	}
+
 	function rebuildAll(cam) {
 		if( primitive != null ) {
 			primitive.dispose();
@@ -564,16 +571,16 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 
 	static var PUVS = [new h3d.prim.UV(0, 0), new h3d.prim.UV(1, 0), new h3d.prim.UV(0, 1), new h3d.prim.UV(1, 1)];
 
-	function cleanParts( g : GpuPartGroup ) {
+	function cleanParts( g : GpuPartGroup, pneeded : Int, checkMove = false ) {
 		if( g.maxTime < 0 )
 			return;
-		var pneeded = Math.ceil(hxd.Math.clamp(g.amount * amount) * g.nparts);
 		var p = g.particles;
 		var prev = null;
 		var ftime = g.maxTime;
 		while( p != null && g.currentParts > pneeded ) {
 			var t = p.time + currentTime;
-			if( t - (t % p.life) > p.time + ftime ) {
+			var st = t - (t % p.life);
+			if( st > p.time + ftime && (!checkMove || -p.time < ftime) ) {
 				var n = p.next;
 				p.next = partAlloc;
 				partAlloc = p;
@@ -596,10 +603,31 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 		var needSync = false;
 		var pneeded = Math.ceil(hxd.Math.clamp(g.amount * amount) * g.nparts);
 
+		if( lastMove != 0 ) {
+			var p = g.particles;
+			while( p != null ) {
+				if( p.time > -lastMove ) break;
+				p = p.next;
+			}
+			if( p == null ) {
+				lastMove = 0;
+			} else {
+				var old = g.maxTime;
+				g.maxTime = lastMove;
+				var count = g.currentParts;
+				cleanParts(g, 0, true);
+				if( g.currentParts < count ) needSync = true;
+				g.maxTime = old;
+			}
+		}
+
 		if( g.currentParts != pneeded ) {
 
 			if( g.currentParts < pneeded ) {
-				cleanParts(g);
+
+				if( lastMove == 0 )
+					cleanParts(g, pneeded);
+
 				var partAlloc = partAlloc;
 				while( g.currentParts < pneeded ) {
 					var pt = partAlloc;
@@ -608,7 +636,7 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 					else
 						partAlloc = pt.next;
 					g.emitPart(rnd, pt, absPos);
-					pt.time -= prevTime;
+					if( lastMove != 0 ) pt.time = -prevTime /* no delay */ else pt.time -= prevTime;
 					pt.index = -1;
 					pt.next = g.particles;
 					g.particles = pt;
@@ -618,7 +646,7 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 				needSync = true;
 			}
 
-			if( g.currentParts > pneeded ) {
+			if( g.currentParts > pneeded && lastMove == 0 ) {
 				var ftime = g.maxTime;
 				if( ftime < 0 )
 					g.maxTime = ftime = currentTime;
@@ -626,13 +654,12 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 				var p = g.particles;
 				var count = 0;
 				while( p != null ) {
-					var t = p.time + currentTime;
-					if( t - (t % p.life) > p.time + ftime ) count++;
+					if( currentTime - ((p.time + currentTime) % p.life) > ftime ) count++;
 					p = p.next;
 				}
 				// remove at once
 				if( g.currentParts - count <= pneeded || count > 1000 ) {
-					cleanParts(g);
+					cleanParts(g, pneeded);
 					if( g.currentParts > pneeded ) g.maxTime = ftime;
 					needSync = true;
 				}