Notifications
Clear all

[Closed] CgTalk Maxscript Challenge 005: "Lightning Bolts"

CgTalk Maxscript Challenge 005: “Lightning Bolts” – (As suggested by JHaywood)

DESCRIPTION: Create jagged animated lightning bolts from one object to the surface of another object. You can either do this as a random automatic function, or make it an actual tool with options.

    INTERMEDIATE SCRIPTERS: The bolts must light up the scene like actual lightning.

  ADVANCED SCRIPTERS: Create surface scarring from the bolt with a procedural texture.

       RULES:  

[ul]
[li]Code from scratch. Try not to use pre-exisitng functions or plugins.[/li][li]Show your script references, if any (eg. Looking at another script to assist you).[/li][li]You are encouraged to ask for help where needed, but try to do it on your own. The maxscript reference is an invaluable resource.[/li][li]Post your final script inside [/li]“`
tags (located on your posting toolbar).
[li]Post all code into THIS thread.[/li][li]Post the max version you coded in, plus any maxscript extensions you used. (Thanks galagast!)[/li][li]Try to finish the challenge in a week. There is no definite time limit.[/li][li]Voting will occur at the end of each ‘month’ (every 4 challenges). [/li][/ul] NOTES: A little simpler than the last one (great work by the way!), this one should prove useful! Keep on coding! Thanks for the suggestion James!

11 Replies

***EDIT: Fixed a small bug that generated errors half-way through the simulation

Ok…I’m not sure if this was what was expected in this challenge…but I figured I’d give it a shot anyways hehe.

Basically, this script takes to objects of any kind (that you choose), and creates an animated lightning bolt (well…more like an electric bolt) between them. All of the settings can be adjusted so that it can be any size of detail that you like (to some extent hehe).

Also, by default, the whole spline is animated…but you can change settings to affect the falloff from the end points (so areas closer to the end points are not as wavy)…or…you can lock off the ends so that the bolt of electricity is “attached” to the objects, as it moves

Btw…I apologize ahead of time for not adding comments to the code

http://www.theonlyt.com/Main/Scripts/zapper.ms


--Spline Lightning script by Tyson Ibele, 2005.
 
 global startTime = bezier_float()
 global endTime = bezier_float()
 global falloffc = bezier_float()
 global bdet = bezier_float()
 global pdet = bezier_float()
 global a1 = bezier_float()
 global a2 = bezier_float()
 global lock_ends
 global dum1
 global dum2
 
 rollout lightn "Main Parameters"
 (
 	pickbutton obj1 "Select Base Object" width:150
 	pickbutton obj2 "Select End Object" width:150	
 	spinner start1 "Start Time: " type:#integer range:[-100000,100000,0] controller:startTime width:100
 	spinner end1 "End Time: " type:#integer range:[-100000,100000,100] controller:endTime width:100
 	button zap "Zap it!" width:70 height:30
 	progressbar prog color:red
 	progressbar prog2 color:blue
 	
 	on obj1 picked obj do
 	(
 		dum1 = obj
 		obj1.text = dum1.name	
 	)
 	
 	on obj2 picked obj do
 	(
 		dum2 = obj
 		obj2.text = dum2.name
 	)
 	
 	on zap pressed do
 	(
 		if dum1 != undefined and dum2 != undefined then
 		(
 			ltng = SplineShape()
 			addNewSpline ltng	
 			addKnot ltng 1 #corner #line dum1.pos
 			addKnot ltng 1 #corner #line dum2.pos
 			
 			ltng.pivot = ltng.center
 			updateShape ltng
 			
 			remSlider = sliderTime
 			
 			sliderTime = 0
 			init_pos = #()
 			counter = 0
 			prog.value = 0
 			prog2.value = 0
 			mainprog = 0
 		
 			for p in (startTime.value as integer) to (endTime.value as integer) do
 			(
 				counter += 1 
 				sliderTime += 1
 		    	prog.value = (counter/(endTime.value-startTime.value))*100
 				mainprog = prog.value/2
 				prog2.value = mainprog
 				proxy = SplineShape()
 				addNewSpline proxy
 				addKnot proxy 1 #corner #line dum1.pos
 				addKnot proxy 1 #corner #line dum2.pos
 				updateShape proxy
 				init_pos_ver = #()
 				for i in 1 to bdet.value do
 				(
 		    		numk = (numsegments proxy 1) * 2	
 					for j in 1 to numk by 2 do
 		    		(    	
 		    			refineSegment proxy 1 j 0.5
 		    		    	 
 					)
 		    			updateShape proxy
 				)
 				for g in 1 to (numKnots proxy 1) do
 				(
 		    		init_pos_ver[g] = getKnotPoint proxy 1 g	
 					
 				)
 				init_pos[counter] = init_pos_ver
 				
 				delete proxy
 			)
 			
 			sliderTime = remSlider
 					
 			for i in 1 to bdet.value do
 			(
 				numk = (numsegments ltng 1) * 2	
 				for j in 1 to numk by 2 do
 				(		
 					refineSegment ltng 1 j 0.5
 		    		    	 
 				)
 				updateShape ltng
 			)
 		
 		
 			remPos = #()
 			getPos = #()
 					
 			ltng.wireColor = white
 			
 			for p in 1 to (numKnots ltng 1) do
 			(
 		    	remPos[p] = getKnotPoint ltng 1 p    			
 			)			
 			animateVertex ltng #all
 			counter = 0
 			prog.value = 0
 		
 			for m in (startTime.value as integer) to (endTime.value as integer) do
 			(
 				
 				rand1 = (random 0 600) 
 				rand4 = (random .4 1.5) * a1.value
 				rand5 = (random .2 2) * a2.value
 				fallcount = 1
 				counter += 1
 		    	prog.value = (counter/(endTime.value-startTime.value))*100
 				mainprog = (prog.value/2)+50
 				prog2.value = (mainprog as integer)
 				for k in 1 to (numKnots ltng 1) do
 				(
 					
 					setKnotPoint ltng 1 k remPos[k]
 		    		setKnotType ltng 1 k #corner		    	
 		    		initial_pos = init_pos[counter][k]	    			
 					
 		    		if fallcount > (numKnots ltng 1)/2 then fallcount = (numKnots ltng 1)/2
 		    		if fallcount < 0 then fallcount = 0
 					
 		    		if k <= (numKnots ltng 1)/2 then
 					(
 		    			falloff = (1-falloffc.value) * fallcount
 		    			if falloff < 0 then falloff = 0
 		    			if falloff > 1 then falloff = 1	
 		    			fallcount += .2
 					)
 					else
 					(
 		    			falloff = ((1-falloffc.value) * fallcount)
 		    			if falloff < 0 then falloff = 0
 		    			if falloff > 1 then falloff = 1	
 		    			fallcount -= .2 
 					)
 					if lock_ends == true then
 					(
 		    			if k == 1 or k == (numKnots ltng 1) then falloff = 0    			
 					)
 		    		    		
 		    		v1 = (random (1*pdet.value) (2*pdet.value))*falloff	    		
 		    		rand2 = (((sin((k*6*rand4)+rand1))*5)*rand5)*falloff
 		    		rand3 = (((sin(k*30*rand4)))*rand5)*falloff
 					
 		    		setKnotPoint ltng 1 k (initial_pos + [rand2, rand2, rand2])    	
 					
 		    		initial_pos = getKnotPoint ltng 1 k
 		    		setKnotPoint ltng 1 k (initial_pos + [rand3, rand3, rand3])    	
 					
 		    		initial_pos = getKnotPoint ltng 1 k
 		    		setKnotPoint ltng 1 k (initial_pos + (random [0,0,0] [v1,v1,v1]))
 					getPos[k] = getKnotPoint ltng 1 k
 					
 					updateShape ltng
 					
 		    		track = 3*(k-1)+2		
 		    		key = addNewKey ltng[#Object__Editable_Spline][#master][track].controller m
 					key.value = getPos[k]
 					
 					updateShape ltng
 				)
 			)
 		)
 		else messagebox "You must first choose 2 objects"
 		prog.value = 0
 		prog2.value = 0
 		
 	)
 	
 	
 )
 rollout settings "Tweakable Settings"
 (
 	spinner detail1 "Bolt Detail: " type:#integer range:[2,8,6] controller:bdet width:100 align:#right 
 	spinner detail2 "Perturb Amount: " type:#integer range:[0,6,2] controller:pdet width:100 align:#right 
 	spinner amp1 "Cycle Multiplier: " type:#float range:[0,6,2] controller:a1 width:100 align:#right
 	spinner amp2 "Amp Size: " type:#float range:[0,6,2] controller:a2 width:100 align:#right
 	spinner falloff1 "End Falloff: " type:#float range:[0,0.99	,1] controller:falloffc width:100 align:#right 
 	checkbox lock1 "Lock Ends" align:#right
 	on lock1 changed check1 do
 	(
 		lock_ends = check1
 	)
 
 )
 zapit=newrolloutfloater "Spline Zapper" 200 365 750 200
 addrollout lightn zapit
 addrollout settings zapit
 startTime.value = 0
 endTime.value = 100
 falloffc.value = 0.5
 bdet.value = 6
 pdet.value = 3
 a1.value = 1
 a2.value = 1
 dum1 = undefined
 dum2 = undefined
 
  

Nice! And so dang fast!
Mine almost does the same thing, but I’m going for a lightning strike with multiple forks. That’s right, i’m actually participating this time!

Hehe…thanks erilaz…yes I was actually going to try to add in some forks myself…hopefully I’ll get to it by the end of the challenge

I guess since I suggested it, I should post an entry in this one.

I using a slightly different approach where I’m basically creating a bunch of dummies with noise controllers and binding a spline to them.

Here's how it works:
- Run the script and you'll get a floating rollout where you can define the start and end objects for the electricity bolt.
  • There’s also two spinners that control the overal “detail” of the bolt. Use a smaller number, like 2, for the main controls, and a bigger number, like 6, for the sub controls. If you unhide the dummies after clicking the “DO IT!” button, you’ll see what these spinner are really doing.

    • Click the “DO IT!” button to build to bolt.
  • Select the start object and you’ll see a bunch of spinners in the modifier panel. The best way to experiment with these and see what they do is to click the play button and start changing numbers.

    • Start with the “Mini Noise Control” section and go up from there to add new layers of motion.
    • The “Strength” spinners control how much movement, and in which world axis, the bolt has.
    • The “Frequency” spinners control how fast the movement is. Experiment with numbers like .01 to get it moving really slow.
  • The “Render” section lets you define the thickness, as well as the randomness of the thickness. You can also define the color of the bolt.

    • “End Point Pos” lets you animate the bolt shooting from the start object to the end object.

    • You can animate the start and end objects moving around and the bolt will follow.

    • All the spinners are animatable.

I’d like to add some forks on here too. And I’d like to add an overall visibility control so that it kind of blinks on and off randomly.

Have fun!
/*
   ---------------------------------------------------------------------------------------
   ---------------------------------------------------------------------------------------
   Ride the Lightning
   v1.0
   Created: 07/05
   By: James Haywood
   
   ---------------------------------------------------------------------------------------
   Description:
   Creates a lightning object between two points.
   
   How it works:
   A spline is created between the Start Object and the End Object, as defined by the pick
   buttons.  Sub Controls and Main Controls are created, with their numbers defined by the 
   rollout spinners.  The Sub Controls are actually spline IK objects that move the spline
   directly.  The Main Controls are helpers that the Sub Controls are position constrained to,
   and are themselves position constrained between the start and end objects. All the controls 
   have noise controllers on them which create the random movement.
   
   Custom attribute controls are added to the start object which control the strength and
   frequency of the various noise parameters, as well as the thickness of the render mesh
   for the spline.
   
   ---------------------------------------------------------------------------------------
   To do list:
   - Add option for forks.
   
   History:
   v1.00 - Fully armed and operational.
   ---------------------------------------------------------------------------------------
   ---------------------------------------------------------------------------------------
   */
   
   
   fn freezePosition obj = (
   	obj.pos.controller = position_list()
   	posCon = obj.pos.controller
   	posCon.available.controller = position_XYZ()
   	posCon.setName 1 "dontUse"
   	posCon.setName 2 "frozen"
   	posCon.setActive 2
   	)
   
   -- thanks to Mike B, the math master
   fn smoothpulse a b t = ( 
   	if t <= a then return 0 
   	if t >= b then return 0 
   	t = (t-a)/(b-a) 
   	t = 1-((abs (t-0.5))*2) 
   	return (t * t * (3 - 2 * t )) 
   	)
   
   rollout lightningGeneratorRlt "Haywood Tools" (
   	group "Ride the Lightning" (
   		pickButton pickStartBtn "Pick Start Object"
   		pickButton pickEndBtn "Pick End Object"
 	spinner numMainControlsSpnr "Main Controls #:" range:[1,100,1] type:#integer width:100 align:#right
       	spinner numSubControlsSpnr "Sub Controls #:" range:[1,100,1] type:#integer width:100 align:#right
   		)
   	button doItBtn "DO IT!" width:100 height:35 offset:[0,10]
   	
   	on pickStartBtn picked obj do (
   		pickStartBtn.text = obj.name
   		)
   	
   	on pickEndBtn picked obj do (
   		pickEndBtn.text = obj.name
   		)
   	
   	on doItBtn pressed do (
   		if pickStartBtn.object != undefined and pickEndBtn.object != undefined then (
   			max modify mode
   			
   			-- set animation range
   			animRange = animationRange
   			animationRange = (interval -10000 100000)
   			
   			-- define controls
   			obj1 = pickStartBtn.object
   			obj2 = pickEndBtn.object
   			numMainControls = numMainControlsSpnr.value
   			numSubControls = numSubControlsSpnr.value
   			subControlsArr = #()
   			mainControlsArr= #()
   			uberMainControlsArr = #(obj1)
   			
   			-- define variable to use for scale
 		splineScale = ((obj2.max.x - obj2.min.x) + (obj2.max.y - obj2.min.y) + (obj2.max.z - obj2.min.z)) / 3
   
 			-- create helper object to control length of spline from obj1 to obj2
 			lengthHelper = point box:off centerMarker:off axisTripod:off cross:on
   			lengthHelper.pos = obj2.pos
   			lengthHelper.size = splineScale
   			lengthHelper.name = (obj1.name + "_lengthHelper")
   			lengthHelper.wirecolor = (color 87 224 198)
   			
   			-- create spline that goes from obj1 to lengthHelper
 			baseSpline = splineShape name:(obj1.name + "_baseSpline") pos:obj1.pos
   			baseSpline.wirecolor = (color 87 224 198)
   			addNewSpline baseSpline
   			addKnot baseSpline 1 #corner #line obj1.pos
   			addKnot baseSpline 1 #corner #line lengthHelper.pos
   			updateShape baseSpline
   			baseSpline.baseObject.renderable = true
   			baseSpline.displayRenderMesh = true
   			baseSpline.sides = 3
   			baseSpline.optimize = true
   			baseSpline.steps = 1
   			
   			-- add self-illuminated material to spline
   			splineMat = standard()
   			baseSpline.material = splineMat
   			splineMat.ambient = baseSpline.wirecolor
   			splineMat.diffuse = baseSpline.wirecolor
   			splineMat.selfillumamount = 100
   			splineMat.name = uniqueName (obj1.name + "_material")
   			
   			-- create mainControls
 		-- add normalize spline modifier and set the length so that there are enough segments for the number of mainControls needed
   			nsMod = normalize_spl()
   			addModifier baseSpline nsMod
 			nsMod.length = (curveLength baseSpline) / (numMainControls + 1)
   			-- collapse stack
   			collapseStack baseSpline
   			-- create helper objects for numMainControls
   			for i = 1 to numMainControls do (
 			p = point box:on centerMarker:off axisTripod:off cross:off
   				p.size = splineScale * 2
 				p.wirecolor = (color 87 224 198)
 				p.name = uniquename (obj1.name + "_mainControl")
 				p.pos = getKnotPoint baseSpline 1 (i + 1)
   				append mainControlsArr p
   				append uberMainControlsArr p
   				)
   			append uberMainControlsArr lengthHelper
   			
   			-- create subControls
 		-- add normalize spline modifier and set the length so that there are enough segments for the number of subControls needed
   			nsMod = normalize_spl()
   			addModifier baseSpline nsMod
 			nsMod.length = (curveLength baseSpline) / (numSubControls + 1)
   			-- collapse stack
   			collapseStack baseSpline
 			-- add splineIK control modifier and create splineIK helpers
   			sIKMod = spline_ik_control()
   			addModifier baseSpline sIKMod
   			sIKMod.linkTypes = 2
   			sIKMod.helper_size = splineScale
   			sIKMod.createHelper (numKnots baseSpline 1)
   			subControlsArr = sIKMod.helper_list
   			-- rename subControls
   			for i in subControlsArr do (
 				i.name = uniquename (obj1.name + "_subControl")
 				i.wirecolor = (color 39 100 88)
   				)
   			
   			-- freeze position on all objects
   			freezePosition baseSpline
   			freezePosition lengthHelper
   			for i in mainControlsArr do (freezePosition i)
   			for i in subControlsArr do (freezePosition i)
   			
   			-- link objects
   			subControlsArr[1].parent = obj1
 			subControlsArr[subControlsArr.count].parent = lengthHelper
   			lengthHelper.parent = obj2
   			
 		-- add a normalize spline modifier to the baseSpline to create many small segments (detail) in the lightning bolt
   			nsMod = normalize_spl()
   			addModifier baseSpline nsMod
   			nsMod.length = splineScale * .5
   			
 		-- add noise modifier to baseSpline to give the detail some random movement
   			noiseMod = noiseModifier()
   			addModifier baseSpline noiseMod
   			noiseMod.scale = splineScale * .25
 			noiseMod.strength = [splineScale,splineScale,splineScale]
   			noiseMod.animate = on
   			noiseMod.frequency = 2
   			noiseMod.seed = random 0 1000
   			for i in noiseMod.phase.controller.keys do (
   				i.inTangentType = #linear
   				i.outTangentType = #linear
   				)
   			
 		-- add position constraint to lengthHelper to control length of baseSpline from obj1 to obj2
   			posCon = position_constraint()
 			lengthHelper.position.controller.available.controller = posCon
   			posCon.appendTarget obj1 100
   			lengthHelper.position.controller.setName 3 "autoPos"
   			lengthHelper.position.controller.setActive 3
 			lengthHelper.position.controller[#weights][#Weight__autoPos].value = 0
   			
   			-- add controllers to mainControls
   			c = mainControlsArr.count
   			for i = 1 to c do (
   				local obj = mainControlsArr[i]
 			-- add position constraints to mainControls to constrain them between obj1 and lengthHelper
   				n = ((100.0 / (c + 1)) * i)
   				posCon = position_constraint()
       		    obj.position.controller.available.controller = posCon
 				posCon.appendTarget obj1 (100 - n)
 				posCon.appendTarget lengthHelper n
   				-- add noise controller
   				noiseCon = noise_position()
       		    obj.position.controller.available.controller = noiseCon
 				noiseCon[#noise_strength].controller = point3_XYZ()
   				-- change values
   				noiseCon.seed = random 0 1000
   				noiseCon.roughness = 1
 				-- add positionXYZ for animating
   				xyzCon = position_xyz()
       		    obj.position.controller.available.controller = xyzCon
 				-- set names and active controller
 				obj.position.controller.setName 3 "autoPos"
 				obj.position.controller.setName 4 "noisePos"
 				obj.position.controller.setName 5 "animate"
 				obj.position.controller.setActive 5
   				)
   			
   			-- add controllers to subControls
   			mc = uberMainControlsArr.count
   			sc = subControlsArr.count
   			for j = 2 to (sc-1) do (
   				local obj = subControlsArr[j]
 			-- add position constraints to make the subControls move with the mainControls
 				-- got major help from Mike B on this one
   				posCon = position_constraint()
       		    obj.position.controller.available.controller = posCon
   				for i = 1 to mc do (
 					range = .45
  			 t = ( ((i as float)/(mc+1)) - ((j as float)/(sc+1)) )
       	    		w = 100.0 * (smoothpulse -range range t)
   	    		    posCon.appendTarget uberMainControlsArr[i] w
   					) 
   				-- add noise controller
   				noiseCon = noise_position()
       		    obj.position.controller.available.controller = noiseCon
 				noiseCon[#noise_strength].controller = point3_XYZ()
   				-- change values
   				noiseCon.seed = random 0 1000
   				noiseCon.roughness = 1
 				-- add positionXYZ for animating
   				xyzCon = position_xyz()
       		    obj.position.controller.available.controller = xyzCon
 				-- set names and active controller
 				obj.position.controller.setName 3 "autoPos"
 				obj.position.controller.setName 4 "noisePos"
 				obj.position.controller.setName 5 "animate"
 				obj.position.controller.setActive 5
   				)
   			
   			-- create custom attribute controls on obj1
 			lightningControlsCA = attributes lightningControlsAtts (
 			parameters lightningControls rollout:lightningControlsRlt (
  			 endPointPos ui:endPointPosSpnr type:#float default:1
 					-- Macro Noise Control
       		    	mcNoiseStrengthX ui:mcnsXSpnr type:#float
       		    	mcNoiseStrengthY ui:mcnsYSpnr type:#float
       		    	mcNoiseStrengthZ ui:mcnsZSpnr type:#float
       		    	mcNoiseStrengthXYZ ui:mcnsAllSpnr type:#float
 		 	mcFrequency ui:mcfrSpnr type:#float animatable:false default:.5
 					-- Main Noise Control
       		    	scNoiseStrengthX ui:scnsXSpnr type:#float
       		    	scNoiseStrengthY ui:scnsYSpnr type:#float
       		    	scNoiseStrengthZ ui:scnsZSpnr type:#float
       		    	scNoiseStrengthXYZ ui:scnsAllSpnr type:#float
 		 	scFrequency ui:scnsfrSpnr type:#float animatable:false default:.5
 					-- Mini Noise Control
       		    	splNoiseStrength ui:splnsSpnr type:#float
 		 	splNoiseFreq ui:splnfSpnr type:#float animatable:false default:5
 	 			splNoiseScale ui:splnsclSpnr type:#float
 					-- render controls
       		    	splThickness ui:splthckSpnr type:#float
       		    	splRandom ui:splrndSpnr type:#float
       		    	splStrength ui:splstrSpnr type:#float
  			 splColor ui:splclr type:#color default:[87,224,198]
 					-- nodes
       		    	baseSplineID type:#integer animatable:false
       		    	mcIDHandles type:#intTab tabSizeVariable:true
       		    	scIDHandles type:#intTab tabSizeVariable:true
   					)
   				
 				rollout lightningControlsRlt "Lighting Controls" (
 		 	spinner endPointPosSpnr "End Point Pos:" align:#right range:[0,1,1]
 					group "Macro Noise Control" (
 		 		spinner mcnsXSpnr "Strength X:" align:#right range:[0,100000,0]
 		 		spinner mcnsYSpnr "Strength Y:" align:#right range:[0,100000,0]
 		 		spinner mcnsZSpnr "Strength Z:" align:#right range:[0,100000,0]
 		 		spinner mcnsAllSpnr "Strength XYZ:" align:#right range:[0,100000,0]
 		 		spinner mcfrSpnr "Frequency" align:#right range:[0,100000,.5]
 						)
 					group "Main Noise Control" (
 		 		spinner scnsXSpnr "Strength X:" align:#right range:[0,100000,0]
 		 		spinner scnsYSpnr "Strength Y:" align:#right range:[0,100000,0]
 		 		spinner scnsZSpnr "Strength Z:" align:#right range:[0,100000,0]
 		 		spinner scnsAllSpnr "Strength XYZ:" align:#right range:[0,100000,0]
 		 		spinner scnsfrSpnr "Frequency" align:#right range:[0,100000,.5]
 						)
 					group "Mini Noise Control" (
 		 		spinner splnsSpnr "Strength:" align:#right range:[0,100000,0]
 		 		spinner splnfSpnr "Frequency:" align:#right range:[0,100000,5]
 		 		spinner splnsclSpnr "Scale:" align:#right range:[0,100000,0]
 						)
 					group "Render" (
 		 		spinner splthckSpnr "Thickness:" align:#right range:[0,100000,0]
 		 		spinner splrndSpnr "Randomize:" align:#right range:[0,1,0]
 	 		 	spinner splstrSpnr "Strength:" align:#right range:[0,100000,0] enabled:false
 		 		colorpicker splclr "Color:" align:#right
 						)
   					
 					on lightningControlsRlt open do (
 		 		if splrndSpnr.value > 0 then splstrSpnr.enabled = true else splstrSpnr.enabled = false
 						)
   
 					on mcnsAllSpnr changed val do (
       		    		mcnsXSpnr.value = val
       		    		mcnsYSpnr.value = val
       		    		mcnsZSpnr.value = val
 						)
   			
 					on mcfrSpnr changed val do (
  				 for i in mcIDHandles do (
 		 			local obj = maxOps.getNodeByHandle i
 	 		 	 obj.position.controller[#noisePos].frequency = val
  					 )
 						)
   			
 					on scnsAllSpnr changed val do (
       		    		scnsXSpnr.value = val
       		    		scnsYSpnr.value = val
       		    		scnsZSpnr.value = val
 						)
   			
 					on scnsfrSpnr changed val do (
  				 for i in scIDHandles do (
 		 			local obj = maxOps.getNodeByHandle i
 	 		 	 obj.position.controller[#noisePos].frequency = val
  					 )
 						)
   			
 					on splnsAllSpnr changed val do (
       		    		splnsXSpnr.value = val
       		    		splnsYSpnr.value = val
       		    		splnsZSpnr.value = val
 						)
   					
 					on splnfSpnr changed val do (
 		 		local obj = maxOps.getNodeByHandle baseSplineID 
 		 		obj.modifiers[#noise].frequency = val
 						)
   					
 					on splrndSpnr changed val do (
 		 		if val == 0 then splstrSpnr.enabled = false else splstrSpnr.enabled = true
 						)
   					)
   				)
   			
   			-- add empty modifier to hold custom attributes
   			emptyMod = emptyModifier()
   			addModifier obj1 emptyMod
   			emptyMod.name = "Lighting Controls"
   			custAttributes.add emptyMod lightningControlsCA
   			
   			-- define node handles for lightningControlsCA
   			emptyMod.baseSplineID = baseSpline.inode.handle
 			mcIDArr = for i in mainControlsArr collect i.inode.handle
 		scIDArr = for i = 2 to (subControlsArr.count - 1) collect subControlsArr[i].inode.handle
   			emptyMod.mcIDHandles = mcIDArr
   			emptyMod.scIDHandles = scIDArr
   			
   			-- wiring
   			lightningControls = emptyMod.lightningControlsAtts
   			-- wire length control
 		paramWire.connect lightningControls[#endPointPos] lengthHelper.position.controller[#weights][#Weight__autoPos] "1 - endPointPos"
   			-- main controls
   			for i in mainControlsArr do (
   				-- length control
 		 paramWire.connect lightningControls[#endPointPos] i.position.controller[#weights][#Weight__noisePos] "endPointPos"
   				-- wire Macro Noise Control
 		 paramWire.connect lightningControls[#mcNoiseStrengthX] i.position.controller[#noisePos][#noise_strength][#x] "mcNoiseStrengthX"
 		 paramWire.connect lightningControls[#mcNoiseStrengthY] i.position.controller[#noisePos][#noise_strength][#y] "mcNoiseStrengthY"
 		 paramWire.connect lightningControls[#mcNoiseStrengthZ] i.position.controller[#noisePos][#noise_strength][#z] "mcNoiseStrengthZ"
   				)
   			-- sub controls
   			for i = 2 to (sc - 1) do (
   				-- length control
 		 paramWire.connect lightningControls[#endPointPos] subControlsArr[i].position.controller[#weights][#Weight__noisePos] "endPointPos"
   				-- wire Macro Noise Control
 		 paramWire.connect lightningControls[#scNoiseStrengthX] subControlsArr[i].position.controller[#noisePos][#noise_strength][#x] "scNoiseStrengthX"
 			 paramWire.connect lightningControls[#scNoiseStrengthY] subControlsArr[i].position.controller[#noisePos][#noise_strength][#y] "scNoiseStrengthY"
 			 paramWire.connect lightningControls[#scNoiseStrengthZ] subControlsArr[i].position.controller[#noisePos][#noise_strength][#z] "scNoiseStrengthZ"
   				)
   			-- spline noise control
 		paramWire.connect lightningControls[#splNoiseStrength] baseSpline.modifiers[#Noise][#strength] "[splNoiseStrength,splNoiseStrength,splNoiseStrength]"
 		paramWire.connect lightningControls[#splNoiseScale] baseSpline.modifiers[#Noise][#scale] "splNoiseScale"
   			-- spline render controls
 			lightningControls[#splThickness].controller = float_list()
       	    lightningControls[#splThickness].controller.available.controller = bezier_float()
   	        lightningControls[#splThickness].controller.available.controller = noise_float()
 	 	baseSpline.baseObject[#thickness].controller = lightningControls[#splThickness].controller
 		paramWire.connect lightningControls[#splRandom] lightningControls[#splThickness][#weights][#Weight__Noise_Float] "splRandom"
 		 paramWire.connect lightningControls[#splStrength] lightningControls[#splThickness][#noise_float][#noise_strength] "splStrength"
 		 paramWire.connect lightningControls[#splColor] baseSpline[5][#Shader_Basic_Parameters][#Diffuse_Color] "splColor"
   			
   			-- hide controls
   			for i in subControlsArr do hide i
   			for i in mainControlsArr do hide i
   			hide lengthHelper
   			
   			-- reset animation range
   			animationRange = animRange
   			)
   		) -- end doItBtn pressed
   	) -- end rollout
   
   createDialog lightningGeneratorRlt width:150 pos:[40,80]

Great job James! Love the handles and IK work you’ve thrown into this! A really unique method! I noticed the animation range is off the charts though. A setup for wire parameters?
Here’s the first stage of mine. It works on the same method of picking two objects, but then has options for number of forked bolts off the root bolt, plus amount of jags. No animation as yet. I want to throw in an animation that actually strikes the surface, rather than a continual zap:


  global boltEm
  global boltSurf
  
  
  fn makeBolts seedNum maxJag minJag bolts = 
  (
  	seed seedNum 
  	rootBolt = line steps:6 thickness:1.0
  	convertToSplineShape rootBolt 
  	updateShape rootBolt -- how many times do I have to update this thing???
  	addNewSpline rootBolt
  	addKnot rootBolt 1 #corner #line boltEm.pos 
  	addKnot rootBolt 1 #corner #line boltSurf.pos 
  	updateShape rootBolt
  	jags = random minJag maxJag 
  	
  	for i = 1 to jags do
  	(
  		segs = numSegments rootBolt 1
  		refineSegment rootBolt 1 (random 1 segs) (random 0.1 0.9)
  	)
  	updateShape rootBolt
  	
  	kNum = numKnots rootBolt
  	for i = 2 to (kNum-1) do
  	(
  		kPos = getKnotPoint rootBolt 1 i
 		setKnotPoint rootBolt 1 i (kPos + [(random -10 10),(random -10 10),(random -10 10)])
  		setKnotType rootBolt 1 i #corner 
  	)
  	
  	updateShape rootBolt
  	
  	-- add extra bolts!
  	for bIdx = 2 to bolts do
  	(
  		splineN = addNewSpline rootBolt 
 		addKnot rootBolt bIdx #corner #line (getKnotPoint rootBolt 1 (random 1 (numKnots rootBolt 1)))
  		addKnot rootBolt bIdx #corner #line boltSurf.pos 
  		updateShape rootBolt 
  		jags = random minJag maxJag 
  	
  		for i = 1 to jags do
  		(
  			segs = numSegments rootBolt bIdx
 			refineSegment rootBolt bIdx (random 1 segs) (random 0.1 0.9)
  		)
  		updateShape rootBolt 
  	
  		kNum = numKnots rootBolt bIdx
  		for i = 2 to (kNum-1) do
  		(
  			kPos = getKnotPoint rootBolt bIdx i
 			setKnotPoint rootBolt bIdx i (kPos + [(random -10 10),(random -10 10),(random -10 10)])
  			setKnotType rootBolt bIdx i #corner 
  		)
  		updateShape rootBolt
  	)
  	
  	
  	rootBolt.renderable = true
  	rootBolt.thickness = 1
  	
  
  )
  
  
  
  
  rollout zapper "Frank" width:152 height:331
  (
  	pickbutton boltBtn "Lightning Emitter" pos:[15,36] width:113 height:34
  	pickbutton surfaceBtn "Surface" pos:[15,96] width:113 height:34
  	label boltLbl "Pick Bolt" pos:[16,13] width:113 height:18 enabled:true
  	label surfaceLbl "Pick Surface" pos:[15,75] width:113 height:18 enabled:true
  	button zapBtn "Zap!" pos:[21,274] width:108 height:45
  	spinner seedSpn "Random Seed " pos:[14,241] width:124 height:16 range:[1,99999,12345] type:#integer
  	spinner maxJag "Max Jags " pos:[39,179] width:99 height:16 range:[1,100,5] type:#integer
  	spinner minJag "Min Jags " pos:[39,210] width:99 height:16 range:[1,100,1] type:#integer
  	spinner boltsSpn "Bolts" pos:[79,148] width:59 height:16 range:[1,100,5] type:#integer
  	
  	on boltBtn picked obj do
  	(
  		boltLbl.text = obj.name
  		boltEm = obj
  	)
  	
  	on surfaceBtn picked obj do
  	(
  		surfaceLbl.text = obj.name
  		boltSurf = obj
  	)
  	
  	on zapBtn pressed do
  	(
  		if boltEm != undefined and boltSurf != undefined then
  		(
  			undo on
  			(
 			makeBolts seedSpn.value maxJag.value minJag.value boltsSpn.value
  			)
  		)
  		else
  			messageBox "Pick an emitter and a surface to continue"
  			
  	)
  )
  
  
  createDialog zapper

Max 7.5 used

By the way, I’m glad to see people commenting code with headers and such. I usually practice this, but i’m lazy today!

Looks cool Martin. I like the forks. Can’t wait to see it animating.

The animation range is made really huge because of the noise controllers. By default they’re only active for the range of time that is set when they’re added. So this way I make sure they’re not going to just stop if the animation range is made longer after it’s created, like with wire parameters. I wish Autodesk would just get rid of this “feature”, it’s way more annoying than useful.

They should at least allow you to configure it! I always forget to reset my ranges after wiring.

thanks . for all of ur doing will be a good reference for new scripters like me . and i will collected all the challanges. i cant write so fast but i m learning .wish some day i will be a member like u all .

Page 1 / 2