View Full Version : Float Script for Brake Lights along a path constraint

 gallion31106 June 2008, 01:05 AMWhats up guys, working on a project animating some cars along paths. So the client wants to add brake lights to the cars, which I figure I'll implement by animating the Self Illumination in the cars' material. This works, but would be a pain to do for a whole traffic jam. So I'm wondering if it's possible to tie the "speed" (which is really just the percentage based progression along the path) of the car to the value of the self illumination in the material. So when that percentage gets low enough, the brake lights illuminate. Now this might be fantastic idea, but I have absolutely no idea how to make this happen. Anyone have a tutorial, suggestion, or even be interested in creating something like this for paying work? Naturally we'd discuss the number, but this would save a lot of time so I think its worth it. Thanks, Ryan
ZeBoxx2
06 June 2008, 02:04 AM
you could tie the speed to the selfIllumination, but you need braking - not speed.

You need to get three positions at three different points in time. With those you can determine whether the car is...
standing still / going forward / going backwards
coasting / accelerating / decelerating (braking)

Example script controller code:

acceleration = 1.09
braking = 0.9

theCar = \$GeoSphere01
nextPos = at time (currentTime + 1) theCar.pos
curPos = at time currentTime ( theCar.pos )
prevPos = at time (currentTime - 1) ( theCar.pos )

travel = distance nextPos curPos
travelPrev = distance curPos prevPos
travelDir = (ray nextPos (nextPos - curPos)).dir

r = 0
g = 0
b = 0

if (travel == 0) then ( ) -- standing still
else (
if ((dot theCar.dir travelDir) < 0) then ( r = 0.25; g = 0.25; b = 0.25 ) -- reversing
if ((travel / travelPrev) < braking) then ( r = 1 ) -- braking
else if ((travel / travelPrev) > acceleration) then ( b = 1 ) -- accelerating
else ( r = 0.25 ) -- coasting
)
[r,g,b]

( Note: I'm in max5 at the moment - in later versions you can make 'theCar' a nice variable instead of a reference to an absolute value, making it much easier to set it up on multiple objects as well. )

See attachment for a sample file.

Edit: obviously, this is a Color Script controller. If all you need is self-illumination for braking, you can do so with a Float Script controller, and ignore any of the items not related to braking.

Edit2: Forward/reverse depends on the car's 'direction', i.e. its local Z axis. If it's using a different axis, you'll have to adjust accordingly. You mentioned using path controllers, so you could actually determine whether it's moving forward/backward much more easily, simple check if its percentage along the path is greater or smaller between two points in time. The above code is a bit more generic.

gallion311
06 June 2008, 02:25 AM
That's an awesome start ZeBoxx2 (http://forums.cgsociety.org/member.php?u=235423); but I am truly a beginner at Scripting. I opened the file and in an effort to dig deeper into the script I'd like to mess around with some values in max, but I can't even find where/how that script is applied.

How do I access that script and change the values around. I thought it would be in a Float Script controller but I can't seem to find it...

Thanks,
Ryan

ZeBoxx2
06 June 2008, 02:41 AM
It's on the pointy sphere's material's diffuse color track :)

gallion311
06 June 2008, 02:53 AM
Alright got that, now I'm starting to test the script.

I think it should be a relatively easy transfer over to a Path Constraint; here's what I have:

acceleration = 1.09
braking = 1

theCar = \$Box01
nextPos = at time (currentTime + 1) theCar.pos.controller.percent
curPos = at time currentTime ( theCar.pos.controller.percent )
prevPos = at time (currentTime - 1) ( theCar.pos.controller.percent )

travel = distance nextPos curPos
travelPrev = distance curPos prevPos

r = 0
g = 0
b = 0

if (travel == 0) then ( ) -- standing still
else (

if ((travel / travelPrev) < braking) then ( r = 1 ) -- braking

else ( r = 0.25 ) -- coasting
)
[r,g,b]

It's not working though. I need the equivalent for distance in regards to the path constraint...anything else look incorrect?

ZeBoxx2
06 June 2008, 11:40 AM
the path controller's percentage is a float value (e.g. 1.0, 10.2, 0.23, -0.8, etc.), while distance works with point3 values (e.g. [0,0,0], [1,2,3], [-1,3,-2], etc.).

The equivalent for floats would be:

travel = abs (nextPos - curPos)
travelPrev = abs (curPos - prevPos)

One thing to keep in mind is that, if "constant velocity" is off in the path controller, then the actual speed along the path will depend on the distance between knots in your path spline. So the difference beteen 0% to 1% and 1% to 2% is not necessarily the same in that case.
Easiest solution for that is to make sure you -are- using "constant velocity". If you're not, there's further calls in 3ds Max that help you get the actual distance along a path given a percentage value... but we can get to that if that applies and "constant velocity" is not an option :)

gallion311
06 June 2008, 04:27 PM
Thats awesome Zeboxx2 the script is working without any errors, but I'm not sure if I need to further adjust that script as far as constant velocity...

I am using Constant Velocity, but I applied a Bezier Float to the Percent value of my Car. This way it graduallys slows down along the path, based on custom tangents on the keyframes. So constant velocity is checked, but it does slow down and speed up along the path so it really isn't constant velocity...

The only issue with it now as that I can't seem to get that perfect value where the brake turns on as soon as it slows down, its always a before or once it's practically stopped. (based on changing the braking value)

EDIT: I also can't figure out how to modify this script to set the amount of Self Illumination. I deleted the old script from the diffuse, and addeda float script controller to the Self Illumination. Then I added this code, but I keep getting an "Unable to Convert: Undefined to type: Float" error...

braking = .96

theCar = \$Box01
nextPos = at time (currentTime + 1) theCar.position.controller.percent
curPos = at time currentTime ( theCar.position.controller.percent )
prevPos = at time (currentTime - 1) ( theCar.position.controller.percent )

travel = abs (nextPos - curPos)
travelPrev = abs (curPos - prevPos)

selfIllumAmount = 0

if (travel == 0) then ( ) -- standing still
else (

if ((travel / travelPrev) < braking) then ( selfIllumAmount = 100 ) -- braking

)

Ryan

ZeBoxx2
06 June 2008, 06:58 PM
I am using Constant Velocity, but [...] it really isn't constant velocity...
Yeah, the wording of that control is a bit confusing. It doesn't mean that your object is moving at a constant speed along the path in general, just that no matter how far points are placed along a spline, it will always move the same distance for the same given percentage.

See the attached file for a basic example showing the difference.

The only issue with it now as that I can't seem to get that perfect value where the brake turns on as soon as it slows down
If you want it as soon as it slows down, the braking value should just be 0.99 or so.

If you want to have it turn on the brake light on the frame it slows down (it currently does it just before; after all, you have to brake first - then the car slows down, not the other way around), change bits to this:

nextPos = at time currentTime theCar.position.controller.percent
curPos = at time (currentTime - 1) ( theCar.position.controller.percent )
prevPos = at time (currentTime - 2) ( theCar.position.controller.percent )

The terminology "nextPos" will be invalid, but you can rename those if you want ;)

I keep getting an "Unable to Convert: Undefined to type: Float" error...

That's because currently, if it's not braking, you're not returning any value..
Change...

if ((travel / travelPrev) < braking) then ( selfIllumAmount = 100 ) -- braking
else ( selfIllumAmount = 0 ) -- coasting

I hope that helps :)

gallion311
06 June 2008, 11:48 PM
Thats amazing ZeBoxx2 (http://forums.cgsociety.org/member.php?u=235423), I really can't thank you enough for all the help.

The last little bump I'm hitting is that I can't set a specific amount For Self Illumination, it's just coming back as 0 or 100.

I modified the code to say:

if ((travel / travelPrev) < braking) then ( selfIllumAmount = 60 ) -- braking

And it still goes from 0 to 100...no in betweens.

Almost like it's returning a true/false value but not a specific amount...

ZeBoxx2
06 June 2008, 12:12 AM
The last little bump I'm hitting is that I can't set a specific amount For Self Illumination, it's just coming back as 0 or 100.
Sometimes parameters in 3ds Max bits and pieces are funky. They display as one thing, but internally they're another.

In this case, the parameter displays as 0 through 100, but internally it uses the values 0.0 through 1.0

So instead of '60', use '0.6'.

You can often tell what a parameter expects when you assign the scripted controller. The default script expression will have the values shown as the parameter stores them internally.

RappyBMX
08 August 2008, 10:41 PM
look what i found today... http://www.xn--d1abb4ane.com/blog/archives/77 ( don't forget to see the video...link above the picture )

edit: forgot... http://www.xn--d1abb4ane.com/blog/archives/68 :)

redlancer
02 February 2009, 08:46 PM

Hopefully your still checking the tread occasionally as I have a new question.

I adjusted the script to work very well with a VrayLight material that I'm using for the taillights of the car, gettting the values to jump between 0 and 1 for the multiplier from your script.

My question is how can I get this working for multiple cars from one material? I have a scene with several hundred cars, most of which are various instances and share the same material. In the above example each object would need a unique material (I think)

Would it be possible to change the Material ID of the taillight polygons instead of the illumination value?

For example, if MatID 1 is no brakes, and MatID 2 is brakes on, then couldn't we have

current object MatID 1 = 1
if current object brakes MatID 1 = 2
if current object accelerates MatID2 = 1

and so on. This would let you use the same material for all the cars, but should animate the brakelights individually.

Not much of a maxscripter, so I'm not sure where to start. The script would need to be a part of each object, and the objects would need to be able to be instanced but have the script still know that's it's on a new object. Any ideas?

Thanks

edit - just looked through the other thread that you guys had on the brake lights, and looks like were trying a similar approach in that to my question. I'll dig through that thread and see if I can gleen any new info :)

SJ

gallion311
02 February 2009, 02:36 AM
Redlancer, upon getting this script to work I had the exact same issue, which prompted a second thread (is this the one you referenced above?)

Anyway, check about halfway down that thread the trick was the volume select modifier, which allowed me to use the same material globally.

gallion311

redlancer
02 February 2009, 08:05 PM
Yup, that was the one. I read through all the ideas on that one, and would probably work for me except the cars I'm using are VRay proxy meshes, so there's no mesh to select via the volume select. You can't really do anything to a proxy besides render it.

I think the only way for it to work with the proxies will be for the script to be able to do a MatID change per object instead of the color change per material (which works great on one car-one mat btw, but would be completely impractical with 3000 cars...)

beyond that, since there are no polygons to select, you coulldn't just change the ID of particular polys, there would have to be a way to swap around what each MatID was, which, now that I think about it, still may need a unique material for each car since swapping the MatID in a global material would effect all the cars at once (seemingly...)

SJ

CGTalk Moderation
02 February 2009, 08:05 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.

1