Page 1 of 4

Dynamic diesel smoke

PostPosted: Wed May 21, 2014 11:33 am
by JamesLit
Hello all,

I'd like to inquire as to whether any of you incredibly knowledgeable chaps and chapettes here know anything about scripting dynamic diesel smoke.

I am making some modifications to an existing loco in TS purely for my own personal use, and would like to take the opportunity to brush up on some skills that would be useful for more public work. The loco in question is receiving a low RPM 3 cylinder engine, which idles at 290rpm and maxes out at 400rpm. At idle it produces bursts of white-blue smoke, which is easily noticeable as in time with the cylinders firing - as in, it would look very strange indeed just to have a constant flow, or something along those lines. I was thinking of trying to replicate something along the lines of what Oovee have done with their 57s, where the exhaust particles are in good time with the engine beat. I'd like to get the smoke changing colour too, something a bit more grey and certainly a lot more thick and longer lasting at higher revs, and if possible, further changes according to the load the loco is pulling.

I am familiar with a lot of LUA stuff relating to TS but even after studying existing examples dynamic smoke in various applications and by various authors I really am not much further than I was before! :oops:

Any help would be greatly appreciated, and thanks in advance. :)

EDIT: While I wait for some responses, I suppose I should probably stop the loco in question crashing TS... :roll:

Re: Dynamic diesel smoke

PostPosted: Wed May 21, 2014 1:18 pm
by AndiS
Changing the exhaust (of a steamer) in the engine script is another item on my long (dream) to-do list. All I can do is relay other persons' information here and my own guesses.

Starting point would be searching for ParticleEmitter in Tankski's reference document.

Some related threads on UKTS:
http://forums.uktrainsim.com/viewtopic. ... 0#p1643160
http://forums.uktrainsim.com/viewtopic. ... 4&t=114285

To make the exhaust depend on the RPM, you would query that controller (in function Update) and change the parameters accordingly. A few of those you wish to alter (such as longer lasting) seem to be hard-coded properties of the particle emitter. While you could experiment with making up system calls with plausible names, you may well have to resort to switching them on and off as the RPM change.

Re: Dynamic diesel smoke

PostPosted: Wed May 21, 2014 7:10 pm
by cjbarnes5294
I'm a bit busy atm (and on my phone, making explaining anything and code writing too laborious and fiddly), but I should be able to come back with some suggestions later. :)

Chris

Re: Dynamic diesel smoke

PostPosted: Wed May 21, 2014 7:42 pm
by deltic009
cjbarnes5294 wrote:I'm a bit busy atm (and on my phone, making explaining anything and code writing too laborious and fiddly), but I should be able to come back with some suggestions later. :)

Chris

Sort of on topic, I seem to recall a while ago you were trying to make a Deltic....well, do what a Deltic does! Did you have any joy and you're just extremely busy? Or did you have to let it go because it wasn't working.

Re: Dynamic diesel smoke

PostPosted: Wed May 21, 2014 8:49 pm
by DominusEdwardius
When doing particle scripting there are basically 3 important functions;

1)
Code: Select all
Call( "EmitterName:SetEmitterActive", State );
--where EmitterName is substituted for name of emitter
--State is substituted for whether you want it on or of i.e 0 for off and 1 for on

2)
Code: Select all
Call (   "EmitterName:SetEmitterColour",R,G,B);
--where EmitterName is substituted for name of emitter
--R = Red, G = Green and, B = blue. The letter is substituted for  a decimal between 0 and 1 with 0 being 0 and 1 being 255 ( in terms of a colour )
--e.g 255, 0, 255 would be 1,0,1

3)
Code: Select all
Call( "EmitterName:SetInitialVelocityMultiplier", Multiplier );
--where EmitterName is substituted for name of emitter
--Multiplier is substituted for a value you wish to alter the outlet velocity of the emitter by for example 1.5 would increase the velocity of which the particles leave by by 50%


The use of the above functions is really up to you, but to give some examples of how you could use them:

The first function can be used to turn on or off a variety of emitter, for example the turning on or off a emitter for say an injector or ejector when that control is used. This is probably best used in conjunction with a series of emitters with different alphas when used for exhaust smoke since you cannot alter the alpha via the scripting ( or at least from memory you can't ).

The second function can be used to alter the colour of say smoke, for example on a steamer you can have that script gradually increase the blackness of the colour as you add coal. Pretty simple but I believe it sets the entire emitter ( start, middle and end) to the RGB value specified and not act as a multiplier so say you had black smoke near the chimney fading to white at its outer reaches I think the script if the colour is changed to say grey the whole lot goes that colour, but then again my memory could be faulty.

The third function is best used to make it look like the smoke is coming out at a faster rate, its how I did the blower smoke on the Jinty etc by using the mutliplier to increase the velocity hence the smoke looks like it's coming out in a jet rather than just flopping out of the chimney :)

hope that helps
regards
Edward

Re: Dynamic diesel smoke

PostPosted: Wed May 21, 2014 9:31 pm
by AndiS
Thanks in advance to all contributions (and Edward for contributing while I type). They will benefit the signal scripts indirectly as I am always tempted to fix the default speech bubble showing on the original AI. I have lots of ideas (for steamers) but not time to get them implemented. So I will be more than happy to take a leaf from the diesels.

Re: Dynamic diesel smoke

PostPosted: Wed May 21, 2014 11:37 pm
by cjbarnes5294
deltic009 wrote:
cjbarnes5294 wrote:I'm a bit busy atm (and on my phone, making explaining anything and code writing too laborious and fiddly), but I should be able to come back with some suggestions later. :)

Chris

Sort of on topic, I seem to recall a while ago you were trying to make a Deltic....well, do what a Deltic does! Did you have any joy and you're just extremely busy? Or did you have to let it go because it wasn't working.


The Deltic is on the back bench at the moment unfortunately, Matt, although I do intend to finish it at some point this year - you'll have to blame it partially on the number of steam locos that need to come first. ;) I realised that it was going to take more work than I originally anticipated, work that really needs to be in place before the particles go on. I had a play with it a few weeks ago though, fancying some deltic thrash at 100mph, so it's not dead. :D

Righty, now I'm sat at a keyboard...

JamesLit wrote:I am making some modifications to an existing loco in TS purely for my own personal use, and would like to take the opportunity to brush up on some skills that would be useful for more public work. The loco in question is receiving a low RPM 3 cylinder engine, which idles at 290rpm and maxes out at 400rpm.


Ok, I think if you want the emitter to "putt" in time with the engine correctly, the first port of call is to get the RPM value, which I think should be:
Code: Select all
Call("*:GetControlValue", "RPM", 0);


I would rather have the number of revolutions per second than RPM, so I would declare a global (you could have it as a local but you might want to use it in more than one function) called gRPS and assign it the value of RPM/60.
Code: Select all
gRPS = Call("*:GetControlValue", "RPM", 0)/60;


Now, I prefer working in radians when it comes trig, circles and circular movement, but you could use degrees just as easily. ;) There are 2pi radians (360 degrees) in one revolution, so I could declare another variable that gives the RPS in radians for me:
Code: Select all
gRPS_radians = gRPS*2*math.pi;


Finally, I want another global that will store and update the angle of revolution of the crankshaft, from 0 to 2pi full revolution. To do this, I use the gRPS_radians variable I declared just now, multiply it by time (distance = speed x time) and increment this new global. Before you do any arithmetic on any variable, you must declare it first and assign it a numerical value, otherwise it will try to do nil + nil which is nil, which is ok (but not useful) until you try comparing nil to a non-nil value in an if-else statement. I would declare this in the Initialise function as gRevAngle = 0. If you declare a value in the Update function like that, that's ok, but it will essentially forget the last value it was assigned to and reset everytime the script updates, which isn't what we want.

Code: Select all
gRevAngle = gRevAngle + gRPS_radians*time;
--I don't want this to exceed 2pi so I reset it if gRevAngle > 2pi
if gRevAngle > 2*math.pi then
     gRevAngle = 0;
end


Hopefully my maths is not too shakey tonight and I've not screwed up anything above, but that is the underlying system I would probably use to drive the particles. So onto the fun/dull (depends how you feel at the time) bit of scripting the particles. We have this really useful variable that should accurately give us the angle of the crankshaft in the engine, and we can use this to control the particles, so as to fire them in time with the engine RPM.

JamesLit wrote:The loco in question is receiving a low RPM 3 cylinder engine, which idles at 290rpm and maxes out at 400rpm.


I must admit, I don't know an awful lot about diesel engines, or whether it would make any difference if it is a 2-stroke or 4-stroke machine, but I'm going to assume that each cylinder fires on everything third of a revolution (I'm guessing that if it is a 4-stroke engine, we'd need to allow gRevAngle to increase to 4pi instead of 2*pi, so that each cylinder ignites only once every two cycles). The easiest way of doing this is by using the angle to control the emitters directly, but this could possibly cause problems if the frequency of ignitions or RPM reaches a certain threshold. To keep things simple, we'll go with it for now. :)

We can just tell the script to turn the emitter on whenever the crankshaft angle is in thirds of 2pi, plus a short range:
Code: Select all
if gRevAngle > 0 and gRevAngle < 0.1*math.pi then
     smokeOn = 1; --as Edward points out, 1 sets the smoke to on and 0 to off
elseif gRevAngle > 0.666*math.pi and gRevAngle < 0.766*math.pi then
     smokeOn = 1; --because the devil says so ;)
elseif gRevAngle > 1.332*math.pi and gRevAngle < 1.432*math.pi then
     smokeOn = 1;
else
     smokeOn = 0; --turn it off
end

Call("ExhaustSmoke:SetEmitterActive", smokeOn);


JamesLit wrote:I'd like to get the smoke changing colour too, something a bit more grey and certainly a lot more thick and longer lasting at higher revs, and if possible, further changes according to the load the loco is pulling.


You have the choice of either changing the colour of the smoke, using different emitters (and hence textures) for the different conditions, or combining the two effects. A simple way to control the colour of just one emitter, based on the RPM, would be to do something like this:

Code: Select all
gRPMColourDriver = (Call("*:GetControlValue", "RPM", 0) - 290)/110; --400 - 290 = 110
gExhaustColour = 1 - 0.7*gRPMColourDriver; --if you wanted it to go from normal to absolute black, you'd make it 1 - gRPMColourDriver so that full 400RPM leads to an exhaust colour of 0.
Call("ExhaustSmoke:SetEmitterColour", gExhaustColour, gExhaustColour, gExhaustColour); -- again as Edward has defined


And hopefully that's enough for anybody to seek their teeth into for tonight. :lol: Let me know if I've been confusing at any point, or made a mistake anywhere. :oops:

Chris

Re: Dynamic diesel smoke

PostPosted: Wed May 21, 2014 11:44 pm
by DominusEdwardius
Personally I hate using Radians in scripting, I find them a bit too imprecise 349.945 is more accurate than in radians ( 6.107 ) to the same number of decimal places plus 360 degrees is easier to remember than 6.283185307..... ( blasted irrational numbers! ). Easier at a glance to with determine a relative amount e.g 256 degrees is very near 3/4 or a revolution whereas its harder to determine what 4.4680.... is :D

I digress ;)

regards
Edward

Re: Dynamic diesel smoke

PostPosted: Thu May 22, 2014 10:59 am
by cjbarnes5294
In this case, fair enough as it you can more easily/precisely divide 360 degrees into 3 120 degree spaces, than taking a third of an already irrational number. Otherwise I counter your easier to remember argument with the fact that you don't need to multiply out n x pi if you leave it in terms of pi!!! ;). I want a quarter of a revolution, oh yes, 0.5pi, very easy to remember. :D

It's horses for courses at the end of the day, you go with the one you feel most comfortable using, although I agree that it would have been better to do it in degrees last night. I've stuck with radians ever since being taught it, and I don't know why, but my brain likes it better... :lol: Most trig functions I've used in all the different languages I've tried use/return values in radians. :twisted: The only one I can think of that didn't was glRotated for OpenGL graphics, which insisted I convert back into degrees. :(

Re: Dynamic diesel smoke

PostPosted: Thu May 22, 2014 5:59 pm
by deltic009
So, I've been reading all of the above with great interest, and so I just have to interject by asking if you can make the script do a combination of all three of the things discussed, all based on the RPM value. Actually, scrap that, is there anyway to make it apply to either the rate of RPM increase or the rate of throttle control increase? As we all know (more or less), when you open up the throttle you get the blackness AND the increase in the rate of exhaust emmission, which quickly settles down after a while at full throttle even if it remains fully opened up. The particle pulsing could still be timed purely to match the engines revs, but the speed it belches out and the colour would be great if allied to those rapid rev rises and then they tail off when the revs remain at the same level.

Chris, if you can explain HOW it could be done then I am just stubborn enough to keep on trying until I correctly get the donkey work of file editing and testing done to make it all actually happen. Wouldn't that be great, all this Steam Sounds Supreme business has reinvigorated the steam side and we have Armstrong Powerhouse for diesel sounds but the visuals are sadly lacking.