Răsfoiți Sursa

Emitter: use own sprite sheet for texture animations, prevent texture from being multiplied twice when also set on material. Synchronize frames to particles lifetimes

trethaller 4 ani în urmă
părinte
comite
435ef78da6
1 a modificat fișierele cu 21 adăugiri și 19 ștergeri
  1. 21 19
      hrt/prefab/fx/Emitter.hx

+ 21 - 19
hrt/prefab/fx/Emitter.hx

@@ -154,6 +154,7 @@ private class ParticleInstance  {
 	public var childMat = new h3d.Matrix();
 	public var baseMat : h3d.Matrix;
 
+	public var startTime = 0.0;
 	public var life = 0.0;
 	public var lifeTime = 0.0;
 	public var color = new h3d.Vector();
@@ -406,6 +407,7 @@ class EmitterObject extends h3d.scene.Object {
 	public var enable : Bool;
 	public var particleVisibility(default, null) : Bool;
 
+	public var startTime = 0.0;
 	public var catchupSpeed = 4; // Use larger ticks when catching-up to save calculations
 	public var maxCatchupWindow = 0.5; // How many seconds max to simulate when catching up
 	public var totalBurstCount : Int = 0; // Keep track of burst count
@@ -438,6 +440,7 @@ class EmitterObject extends h3d.scene.Object {
 	public var emitRad2 : Float = 1.0;
 	public var emitSurface : Bool = false;
 	// ANIMATION
+	public var spriteSheet : String;
 	public var frameCount : Int = 0;
 	public var frameDivisionX : Int = 1;
 	public var frameDivisionY : Int = 1;
@@ -576,6 +579,7 @@ class EmitterObject extends h3d.scene.Object {
 			else
 				part.baseMat = emitterBaseMat.clone();
 
+			part.startTime = startTime + curTime;
 			part.lifeTime = hxd.Math.max(0.01, lifeTime + hxd.Math.srand(lifeTimeRand));
 			tmpQuat.identity();
 
@@ -668,7 +672,8 @@ class EmitterObject extends h3d.scene.Object {
 			}
 
 			var frameCount = frameCount == 0 ? frameDivisionX * frameDivisionY : frameCount;
-			part.startFrame = random.random(frameCount);
+			if(animationLoop)
+				part.startFrame = random.random(frameCount);
 
 			if( trailTemplate != null ) {
 				if( tmpCtx == null ) {
@@ -686,7 +691,7 @@ class EmitterObject extends h3d.scene.Object {
 		emitCount += count;
 	}
 
-	function createMeshBatch( startTime : Float ) {
+	function createMeshBatch() {
 
 		if( batch != null )
 			batch.remove();
@@ -729,13 +734,12 @@ class EmitterObject extends h3d.scene.Object {
 
 			// Animated textures animations
 			var frameCount = frameCount == 0 ? frameDivisionX * frameDivisionY : frameCount;
-			if( frameCount > 1 ) {
-				if( mesh != null && mesh.material != null && mesh.material.texture != null ) {
-					var pshader = new h3d.shader.AnimatedTexture(mesh.material.texture, frameDivisionX, frameDivisionY, frameCount, frameCount * animationRepeat / lifeTime);
-					pshader.startTime = startTime;
-					pshader.loop = animationLoop;
-					mesh.material.mainPass.addShader(pshader);
-				}
+			if( frameCount > 1 && spriteSheet != null ) {
+				var tex = hxd.res.Loader.currentInstance.load(spriteSheet).toTexture();
+				var pshader = new h3d.shader.AnimatedTexture(tex, frameDivisionX, frameDivisionY, frameCount, frameCount * animationRepeat / lifeTime);
+				pshader.startTime = startTime;
+				pshader.loop = animationLoop;
+				mesh.material.mainPass.addShader(pshader);
 			}
 
 			if( meshPrim != null ) {
@@ -844,6 +848,7 @@ class EmitterObject extends h3d.scene.Object {
 
 		if( full && batch != null ) {
 			batch.begin(hxd.Math.nextPOT(maxCount));
+			var animTex = batch.material.mainPass.getShader(h3d.shader.AnimatedTexture);
 			if( particleVisibility ) {
 				camPosTmp = getScene().camera.pos;
 				particles = haxe.ds.ListSort.sortSingleLinked(particles, sortZ);
@@ -862,13 +867,9 @@ class EmitterObject extends h3d.scene.Object {
 						var t = hxd.Math.clamp(p.life / p.lifeTime, 0.0, 1.0);
 						anim.setTime(t);
 					}
-					// Init the start frame for each particle
-					var frameCount = frameCount == 0 ? frameDivisionX * frameDivisionY : frameCount;
-					if( frameCount > 0 && animationRepeat == 0 ) {
-						var s = batch.material.mainPass.getShader(h3d.shader.AnimatedTexture);
-						if( s != null){
-							s.startFrame = p.startFrame;
-						}
+					if( animTex != null ){
+						animTex.startTime = p.startTime;
+						animTex.startFrame = p.startFrame;
 					}
 					batch.emitInstance();
 					p = p.next;
@@ -1005,6 +1006,7 @@ class Emitter extends Object3D {
 		{ name: "alignAxis", t: PVec(3, -1.0, 1.0), def: [0.,0.,0.], disp: "Axis", groupName : "Alignment" },
 		{ name: "alignLockAxis", t: PVec(3, -1.0, 1.0), def: [0.,0.,0.], disp: "Lock Axis", groupName : "Alignment" },
 		// ANIMATION
+		{ name: "spriteSheet", t: PFile(["jpg","png"]), def: null, groupName : "Animation" },
 		{ name: "frameCount", t: PInt(0), def: 0, groupName : "Animation" },
 		{ name: "frameDivisionX", t: PInt(1), def: 1, groupName : "Animation" },
 		{ name: "frameDivisionY", t: PInt(1), def: 1, groupName : "Animation" },
@@ -1240,6 +1242,7 @@ class Emitter extends Object3D {
 		emitterObj.alignAxis 			= 	getParamVal("alignAxis");
 		emitterObj.alignLockAxis 		= 	getParamVal("alignLockAxis");
 		// ANIMATION
+		emitterObj.spriteSheet 			= 	getParamVal("spriteSheet");
 		emitterObj.frameCount 			= 	getParamVal("frameCount");
 		emitterObj.frameDivisionX 		= 	getParamVal("frameDivisionX");
 		emitterObj.frameDivisionY 		= 	getParamVal("frameDivisionY");
@@ -1250,12 +1253,11 @@ class Emitter extends Object3D {
 		emitterObj.killOnCollision 		= 	getParamVal("killOnCollision");
 		emitterObj.elasticity 			= 	getParamVal("elasticity");
 
-		var startTime = 0.0;
 		var scene = ctx.local3d.getScene();
 		if(scene != null)
-			startTime = @:privateAccess scene.renderer.ctx.time;
+			emitterObj.startTime = @:privateAccess scene.renderer.ctx.time;
 
-		emitterObj.createMeshBatch(startTime);
+		emitterObj.createMeshBatch();
 		refreshChildren(ctx);
 
 		#if editor