Pārlūkot izejas kodu

added particles trails

Nicolas Cannasse 11 gadi atpakaļ
vecāks
revīzija
b3d2807943
5 mainītis faili ar 226 papildinājumiem un 85 dzēšanām
  1. 1 0
      h3d/parts/Data.hx
  2. 37 5
      h3d/parts/Editor.hx
  3. 183 79
      h3d/parts/Emitter.hx
  4. 1 1
      h3d/parts/Material.hx
  5. 4 0
      h3d/parts/Particle.hx

+ 1 - 0
h3d/parts/Data.hx

@@ -85,6 +85,7 @@ class State {
 	public var shape : Shape;
 	public var emitFromShell : Bool;
 	public var emitLocal : Bool;
+	public var emitTrail : Bool;
 	public var randomDir : Bool;
 
 	// system globals

+ 37 - 5
h3d/parts/Editor.hx

@@ -51,6 +51,7 @@ class Editor extends h2d.Sprite {
 	var redo : Array<History>;
 	public var currentFilePath : String;
 	public var autoLoop : Bool = true;
+	public var moveEmitter(default,set) : Bool = false;
 	
 	static var CURVES : Array<{ name : String, f : Curve -> Data.Value }> = [
 		{ name : "Const", f : function(c) return VConst(c.min) },
@@ -109,6 +110,12 @@ class Editor extends h2d.Sprite {
 		buildUI();
 	}
 	
+	function set_moveEmitter(v) {
+		this.moveEmitter = v;
+		buildUI();
+		return v;
+	}
+	
 	public dynamic function loadTexture( textureName : String ) : h2d.Tile {
 		var bytes = null;
 		try {
@@ -188,6 +195,15 @@ class Editor extends h2d.Sprite {
 		getScene().addEventListener(onEvent);
 	}
 	
+	var time : Float = 0.;
+	public dynamic function onMoveEmitter(dt:Float) {
+		time += dt * 0.03 * 60;
+		var r = 1;
+		emit.x = Math.cos(time) * r;
+		emit.y = Math.sin(time * 0.5) * r;
+		emit.z = (Math.cos(time * 1.3) * Math.sin(time * 1.5) + 1) * r;
+	}
+	
 	function onEvent( e : hxd.Event ) {
 		function loadHistory( h : History ) {
 			curState = h.state;
@@ -437,15 +453,24 @@ class Editor extends h2d.Sprite {
 							</div>
 						</div>
 						<div class="line">
-							<checkbox checked="${state.emitLocal}" onchange="api.s.emitLocal = this.checked"/> <span>Emit Local</span>
+							<div class="box">
+								<checkbox checked="${state.emitTrail}" onchange="api.s.emitTrail = this.checked"/> <span>Trail</span>
+							</div>
+							<div class="box">
+								<checkbox checked="${state.randomDir}" onchange="api.s.randomDir = this.checked"/> <span>Rand. Dir</span>
+							</div>
 						</div>
 						<div class="line">
-							<checkbox checked="${state.emitFromShell}" onchange="api.s.emitFromShell = this.checked"/> <span>Emit from Shell</span>
+							<div class="box">
+								<checkbox checked="${state.emitLocal}" onchange="api.s.emitLocal = this.checked"/> <span>Local</span>
+							</div>
+							<div class="box">
+								<checkbox checked="${state.emitFromShell}" onchange="api.s.emitFromShell = this.checked"/> <span>From Shell</span>
+							</div>
 						</div>
 						<div class="line">
-							<checkbox checked="${state.randomDir}" onchange="api.s.randomDir = this.checked"/> <span>Random Dir</span>
+							<checkbox checked="${this.moveEmitter}" onchange="api.setMove(this.checked)"/> <span>Move Emitter</span>
 						</div>
-						<!-- TODO : Bursts edition -->
 					</div>
 					
 					<h1>Particle</h1>
@@ -579,6 +604,7 @@ class Editor extends h2d.Sprite {
 			selectTexture : function() onTextureSelect(),
 			load : function() onLoad(),
 			save : function() onSave(haxe.io.Bytes.ofString(curState)),
+			setMove : function(b) moveEmitter = b,
 		});
 		addChildAt(ui,0);
 		stats = cast ui.getElementById("stats");
@@ -925,8 +951,14 @@ class Editor extends h2d.Sprite {
 			redo = [];
 		}
 		emit.speed = props.pause ? 0 : (props.slow ? 0.1 : 1);
+		if( moveEmitter ) onMoveEmitter(ctx.elapsedTime);
 		var pcount = emit.count;
-		if( stats != null ) stats.text = hxd.Math.fmt(emit.time * state.globalLife) + " s\n" + pcount + " p\n" + hxd.Math.fmt(ctx.engine.fps) + " fps" + ("\n"+getScene().getSpritesCount());
+		if( stats != null )
+			stats.text = [
+				hxd.Math.fmt(emit.time * state.globalLife) + " s",
+				pcount + " parts",
+				hxd.Math.fmt(ctx.engine.fps) + " fps",
+			].join("\n");
 		if( autoLoop && !emit.isActive() ) {
 			if( lastPartSeen == null )
 				lastPartSeen = emit.time;

+ 183 - 79
h3d/parts/Emitter.hx

@@ -168,6 +168,7 @@ class Emitter extends h3d.scene.Object {
 			p.dy = v.y;
 			p.dz = v.z;
 		}
+		p.fx = p.fy = p.fz = 0;
 		p.time = 0;
 		p.lifeTimeFactor = 1 / eval(state.life, time, rand);
 	}
@@ -224,17 +225,17 @@ class Emitter extends h3d.scene.Object {
 	
 		// apply forces
 		if( state.force != null ) {
-			p.dx += eval(state.force.vx, time, rand) * dt;
-			p.dy += eval(state.force.vy, time, rand) * dt;
-			p.dz += eval(state.force.vz, time, rand) * dt;
+			p.fx += eval(state.force.vx, time, rand) * dt;
+			p.fy += eval(state.force.vy, time, rand) * dt;
+			p.fz += eval(state.force.vz, time, rand) * dt;
 		}
-		p.dz -= eval(state.gravity, time, rand) * dt;
+		p.fz -= eval(state.gravity, time, rand) * dt;
 		// calc speed and update position
 		var speed = eval(state.speed, p.time, rand);
 		var ds = speed * dt;
-		p.x += p.dx * ds;
-		p.y += p.dy * ds;
-		p.z += p.dz * ds;
+		p.x += p.dx * ds + p.fx * dt;
+		p.y += p.dy * ds + p.fy * dt;
+		p.z += p.dz * ds + p.fz * dt;
 		p.size = eval(state.size, p.time, rand);
 		p.ratio = eval(state.ratio, p.time, rand);
 		p.rotation = eval(state.rotation, p.time, rand);
@@ -345,82 +346,185 @@ class Emitter extends h3d.scene.Object {
 			t.v = 0; t.v2 = 1;
 			frames = [t];
 		}
-		while( p != null ) {
-			var f = frames[p.frame];
-			if( f == null ) f = frames[0];
-			var ratio = p.size * p.ratio * (f.height / f.width);
-			tmp[pos++] = p.x;
-			tmp[pos++] = p.y;
-			tmp[pos++] = p.z;
-			// delta
-			tmp[pos++] = 0;
-			tmp[pos++] = 0;
-			tmp[pos++] = p.rotation;
-			tmp[pos++] = p.size;
-			tmp[pos++] = ratio;
-			// UV
-			tmp[pos++] = f.u;
-			tmp[pos++] = f.v;
-			// RBGA
-			if( hasColor ) {
-				tmp[pos++] = p.cr;
-				tmp[pos++] = p.cg;
-				tmp[pos++] = p.cb;
-				tmp[pos++] = p.ca;
-			}
-			
-			tmp[pos++] = p.x;
-			tmp[pos++] = p.y;
-			tmp[pos++] = p.z;
-			tmp[pos++] = 0;
-			tmp[pos++] = 1;
-			tmp[pos++] = p.rotation;
-			tmp[pos++] = p.size;
-			tmp[pos++] = ratio;
-			tmp[pos++] = f.u;
-			tmp[pos++] = f.v2;
-			if( hasColor ) {
-				tmp[pos++] = p.cr;
-				tmp[pos++] = p.cg;
-				tmp[pos++] = p.cb;
-				tmp[pos++] = p.ca;
-			}
+		if( state.emitTrail ) {
+			var prev = p;
+			var prevX1 = p.x, prevY1 = p.y, prevZ1 = p.z;
+			var prevX2 = p.x, prevY2 = p.y, prevZ2 = p.z;
+			if( p != null ) p = p.next;
+			while( p != null ) {
+				var f = frames[p.frame];
+				if( f == null ) f = frames[0];
+				var ratio = p.size * p.ratio * (f.height / f.width);
+				
+				tmp[pos++] = prevX1;
+				tmp[pos++] = prevY1;
+				tmp[pos++] = prevZ1;
+				// delta
+				tmp[pos++] = 0;
+				tmp[pos++] = 0;
+				tmp[pos++] = p.rotation;
+				tmp[pos++] = p.size;
+				tmp[pos++] = ratio;
+				// UV
+				tmp[pos++] = f.u;
+				tmp[pos++] = f.v;
+				// RBGA
+				if( hasColor ) {
+					tmp[pos++] = p.cr;
+					tmp[pos++] = p.cg;
+					tmp[pos++] = p.cb;
+					tmp[pos++] = p.ca;
+				}
+				
+				tmp[pos++] = prevX2;
+				tmp[pos++] = prevY2;
+				tmp[pos++] = prevZ2;
+				tmp[pos++] = 0;
+				tmp[pos++] = 0;
+				tmp[pos++] = p.rotation;
+				tmp[pos++] = p.size;
+				tmp[pos++] = ratio;
+				tmp[pos++] = f.u;
+				tmp[pos++] = f.v2;
+				if( hasColor ) {
+					tmp[pos++] = p.cr;
+					tmp[pos++] = p.cg;
+					tmp[pos++] = p.cb;
+					tmp[pos++] = p.ca;
+				}
+
+				var dx = p.x - prev.x;
+				var dy = p.y - prev.y;
+				var dz = p.z - prev.z;
+				var d = hxd.Math.invSqrt(dx * dx + dy * dy + dz * dz);
+				dx *= d;
+				dy *= d;
+				dz *= d;
+				var dir = new h3d.Vector(Math.sin(p.rotation), 0, Math.cos(p.rotation)).cross(new h3d.Vector(dx, dy, dz));
+				
+				prevX1 = p.x + dir.x * p.size;
+				prevY1 = p.y + dir.y * p.size;
+				prevZ1 = p.z + dir.z * p.size;
+				
+				prevX2 = p.x - dir.x * p.size;
+				prevY2 = p.y - dir.y * p.size;
+				prevZ2 = p.z - dir.z * p.size;
 
-			tmp[pos++] = p.x;
-			tmp[pos++] = p.y;
-			tmp[pos++] = p.z;
-			tmp[pos++] = 1;
-			tmp[pos++] = 0;
-			tmp[pos++] = p.rotation;
-			tmp[pos++] = p.size;
-			tmp[pos++] = ratio;
-			tmp[pos++] = f.u2;
-			tmp[pos++] = f.v;
-			if( hasColor ) {
-				tmp[pos++] = p.cr;
-				tmp[pos++] = p.cg;
-				tmp[pos++] = p.cb;
-				tmp[pos++] = p.ca;
+				tmp[pos++] = prevX1;
+				tmp[pos++] = prevY1;
+				tmp[pos++] = prevZ1;
+				tmp[pos++] = 0;
+				tmp[pos++] = 0;
+				tmp[pos++] = p.rotation;
+				tmp[pos++] = p.size;
+				tmp[pos++] = ratio;
+				tmp[pos++] = f.u2;
+				tmp[pos++] = f.v;
+				if( hasColor ) {
+					tmp[pos++] = p.cr;
+					tmp[pos++] = p.cg;
+					tmp[pos++] = p.cb;
+					tmp[pos++] = p.ca;
+				}
+
+				tmp[pos++] = prevX2;
+				tmp[pos++] = prevY2;
+				tmp[pos++] = prevZ2;
+				tmp[pos++] = 0;
+				tmp[pos++] = 0;
+				tmp[pos++] = p.rotation;
+				tmp[pos++] = p.size;
+				tmp[pos++] = ratio;
+				tmp[pos++] = f.u2;
+				tmp[pos++] = f.v2;
+				if( hasColor ) {
+					tmp[pos++] = p.cr;
+					tmp[pos++] = p.cg;
+					tmp[pos++] = p.cb;
+					tmp[pos++] = p.ca;
+				}
+				
+				prev = p;
+				p = p.next;
 			}
+		} else {
+			while( p != null ) {
+				var f = frames[p.frame];
+				if( f == null ) f = frames[0];
+				var ratio = p.size * p.ratio * (f.height / f.width);
+				tmp[pos++] = p.x;
+				tmp[pos++] = p.y;
+				tmp[pos++] = p.z;
+				// delta
+				tmp[pos++] = -0.5;
+				tmp[pos++] = -0.5;
+				tmp[pos++] = p.rotation;
+				tmp[pos++] = p.size;
+				tmp[pos++] = ratio;
+				// UV
+				tmp[pos++] = f.u;
+				tmp[pos++] = f.v;
+				// RBGA
+				if( hasColor ) {
+					tmp[pos++] = p.cr;
+					tmp[pos++] = p.cg;
+					tmp[pos++] = p.cb;
+					tmp[pos++] = p.ca;
+				}
+				
+				tmp[pos++] = p.x;
+				tmp[pos++] = p.y;
+				tmp[pos++] = p.z;
+				tmp[pos++] = -0.5;
+				tmp[pos++] = 0.5;
+				tmp[pos++] = p.rotation;
+				tmp[pos++] = p.size;
+				tmp[pos++] = ratio;
+				tmp[pos++] = f.u;
+				tmp[pos++] = f.v2;
+				if( hasColor ) {
+					tmp[pos++] = p.cr;
+					tmp[pos++] = p.cg;
+					tmp[pos++] = p.cb;
+					tmp[pos++] = p.ca;
+				}
 
-			tmp[pos++] = p.x;
-			tmp[pos++] = p.y;
-			tmp[pos++] = p.z;
-			tmp[pos++] = 1;
-			tmp[pos++] = 1;
-			tmp[pos++] = p.rotation;
-			tmp[pos++] = p.size;
-			tmp[pos++] = ratio;
-			tmp[pos++] = f.u2;
-			tmp[pos++] = f.v2;
-			if( hasColor ) {
-				tmp[pos++] = p.cr;
-				tmp[pos++] = p.cg;
-				tmp[pos++] = p.cb;
-				tmp[pos++] = p.ca;
+				tmp[pos++] = p.x;
+				tmp[pos++] = p.y;
+				tmp[pos++] = p.z;
+				tmp[pos++] = 0.5;
+				tmp[pos++] = -0.5;
+				tmp[pos++] = p.rotation;
+				tmp[pos++] = p.size;
+				tmp[pos++] = ratio;
+				tmp[pos++] = f.u2;
+				tmp[pos++] = f.v;
+				if( hasColor ) {
+					tmp[pos++] = p.cr;
+					tmp[pos++] = p.cg;
+					tmp[pos++] = p.cb;
+					tmp[pos++] = p.ca;
+				}
+
+				tmp[pos++] = p.x;
+				tmp[pos++] = p.y;
+				tmp[pos++] = p.z;
+				tmp[pos++] = 0.5;
+				tmp[pos++] = 0.5;
+				tmp[pos++] = p.rotation;
+				tmp[pos++] = p.size;
+				tmp[pos++] = ratio;
+				tmp[pos++] = f.u2;
+				tmp[pos++] = f.v2;
+				if( hasColor ) {
+					tmp[pos++] = p.cr;
+					tmp[pos++] = p.cg;
+					tmp[pos++] = p.cb;
+					tmp[pos++] = p.ca;
+				}
+				
+				p = p.next;
 			}
-			
-			p = p.next;
 		}
 		var stride = 10;
 		if( hasColor ) stride += 4;

+ 1 - 1
h3d/parts/Material.hx

@@ -24,7 +24,7 @@ private class PartShader extends h3d.impl.Shader {
 			var tpos = input.pos.xyzw;
 			tpos.xyz = input.pos.xyzw * mpos;
 			var tmp = tpos * mproj;
-			var rpos = input.delta - 0.5;
+			var rpos = input.delta;
 			var cr = input.rotation.cos();
 			var sr = input.rotation.sin();
 			var rtmp = rpos.x * cr + rpos.y * sr;

+ 4 - 0
h3d/parts/Particle.hx

@@ -14,6 +14,10 @@ class Particle {
 	public var dy : Float;
 	public var dz : Float;
 
+	public var fx : Float;
+	public var fy : Float;
+	public var fz : Float;
+
 	public var cr : Float;
 	public var cg : Float;
 	public var cb : Float;