Notifications
Clear all

[Closed] CgTalk Maxscript Challenge 007: "Laser wars"

CgTalk Maxscript Challenge 007: “Laser wars”

DESCRIPTION: Create an emitter that fires a spline “laser” a specified distance (we don’t really want infinity here!). If it hits an object, it must bounce off at an angle. Try to make 3 bounces.

          INTERMEDIATE SCRIPTERS: Define some properties for the objects. If it's stone, the laser stops. If it's reflective, it bounces. If it's transparent, have the spline beam "refract" into multiple directions. Think of more options for objects.

      ADVANCED SCRIPTERS: Have the laser terminate at an object and throw in some particle effects at the spline end for burning the surface. Sparks and smoke.
  
             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: Everybody loves lasers! I’m still not getting many votes for the last 4 challenges either! What’s up?

12 Replies

yea laser beams! !! !! !!! !! ! !!!

J.

damn I’ll never find time for this one!

J.

Yeah…sorry erilaz for the lack of response from me on the last one or this one…I’m just having a hard time finding extra time for stuff like this because I just moved from Can to the US…hopefully in the near future I’ll have time to participate. I haven’t forgotten though!

I’m thinking i may have to expand the timeframe for these challenges. More and more people are finding less time. I’ll leave this one up for another week perhaps?

Yea I’m having trouble to find time this last week! maybe another week would give me enough time to unattach my laser beams from the freakin sharks heads and digitize them into my maxscript listener.

J.

Heh…

Okay people, we’ll leave this up for another week. And hey, now Max 8 has a script debugger, these should be even easier to handle!

Re:debugger…hehe…my thoughts exactly!

Ok, laser wars!

Here is my entry. Again (as with my lightning entry) I’ve used vectors to calculate where the collisions are, and where the vector is reflected to. I then collect these points and create a shape that goes through these points.

limitations:

  • only bounces of editable mesh’s ( a limitation max’s RAYex function)
  • doesn’t collide with the back of faces ( a limitation max’s RAYex function)
  • laser fires along the z axis of the laser object (ok this could be changed easily enough!)

Installation:

It is a macroscript, so you’ll need to execute it and then drag it from JNScripts to your toolbar

Notes:

There is a certain amount of AI when you execute the script, if you have one object selected then this will become the source object. If you have multiple objects selected, then these will become the collision objects.

Things for the future:

Everything is ready to enhance the script to apply burnt patches or smoke. This is because I have used intersectRayEx which also provides face number and barycentric co-ordinates.

It could also use material information such as IOR or density to change how the ray is deflected, or even if the ray is split into multiple rays on collision.

It’s all a matter of time

Thanks for looking.
download here

Cheers,

Josh.


macroScript laser category:"JN Scripts" tooltip:"Fire laser beams through you scene." icon:#("JNmesh",1)
(
--------------------------------------------------------------------------------
--	Laser
--	version 1.0
--	max version 6, 7
--	written by Joshua Newman
--	[www.joshuanewman.net]( http://www.joshuanewman.net/) 
--	written 04/08/05
--	last updated 04/08/05
--	copyright 2005
--------------------------------------------------------------------------------
--
-- CGTALK Maxscript competition.
--
-- This script will fire a spline from a source object throught your scene bouncing of your scene objects
--
--------------------------------------------------------------------------------
--
-- LIMITATIONS
--
-- needs editable meshes! there are no collisions on other object.
-- only collides against faces in the direction of the normal! ie, will not collide with the back of a face.
-- laser fires in the Z direction of the source object.
--
--------------------------------------------------------------------------------
--
-- USAGE
--
-- 1 This is a macroscript, drag it into the max viewport
-- 2 customize / customize user interface
-- 3 category : JNScripts
-- 4 drag the script to your toolbar.
--
 
--------------------------------------------------------------------------------
-- Script starts here.
--------------------------------------------------------------------------------
local obj=#(),src
--------------------------------------------------------------------------------
-- FUNCTIONS 
--
-- These two functions are the heart of the collision detection, and the reflectance calulations.
--------------------------------------------------------------------------------
fn reflectance u n=u-(dot (2*u) n)*n	 -- calculate the reflectance vector (ray trace)
fn calcintersections spos sdir obj=	 -- Calculate the collisions.
(
ipnt=#()			-- an array to hold the intersections
r=ray spos sdir		 -- cast the laser ray!
for j=1 to obj.count do
(
i=intersectrayex obj[j] r	 -- does the ray intersect?
if i!=undefined then append ipnt i	-- collect the intersections
)
-- this routine finds the closest intersect to the source
if ipnt.count!=0 then
(
pnt=ipnt[1]		 -- the first intersection
for j=1 to ipnt.count do if (distance spos ipnt[j][1].pos)<(distance spos pnt[1].pos) then pnt=ipnt[j] -- tests all of the intersections to find the closest
return pnt		 -- return the closest point
) else
(
return undefined		 -- return undefined if there is non collision.
)
)
--------------------------------------------------------------------------------
-- ROLLOUTS
--------------------------------------------------------------------------------
fn elementfilter obj= iskindof obj editable_mesh
rollout lsercontrol "Parameters"
(
group "Source"
(
pickbutton sobj "Source object" width:235 -- filter:elementfilter
)
group "Collision Objects (Editable mesh's only!)"
(
button addl "+" images:#((getdir #ui)+"\icons\\Maintoolbar_16i.bmp",(getdir #ui)+"\icons\\Maintoolbar_16a.bmp",100,19,20,19,20) width:22 height:21 tooltip:"Add collision objects by name." offset:[-52,0] across:2
pickbutton addp "Pick collision objects" tooltip:"Pick collision objects in the viewport." width:212 offset:[-92,0] filter:elementfilter
dropdownlist cobj "" tootltip:"Collision objects" width:212 offset:[-5,0]across:2
button rem "R" width:22 height:21 tooltip:"Remove object from the collision list." offset:[52,0] across:2
)
group "Laser Parameters."
(
spinner mxnm "Maximum bounces" tooltip:"The maximun number of bounces or collisions." range:[0,1E9,100]
spinner over "final length" tooltip:"The distance travelled after final collision." range:[0,1E9,100]
spinner thck "Thickness" tooltip:"The thickness of the laser beam." range:[0,1E9,.1]
checkbox rnd "Renderable" tooltip:"Make the laser beam renderable" across:2 checked:true
checkbox vwp "Display in Viewport" tooltip:"Display the laserbeam in the vewport as a mesh" checked:true
)
button fire "Fire!" width:240 height:50
label l1 "\xa9 2005 Joshua Newman" across:2 offset:[-8,0]
hyperlink hl "[www.joshuanewman.net]( http://www.joshuanewman.net/ )" address:"[www.joshuanewman.net]( http://www.joshuanewman.net/ )" offset:[4,0]
 
--------------------------------------------------------------------------------
-- LOACL FUNCTIONS
--------------------------------------------------------------------------------
fn updatelist=	 -- this routine updates the drop down list containing the collision objects
(
x=#()
for i=1 to obj.count do append x obj[i].name
sort x
cobj.items=x
flashnodes obj
)
fn getsource c=	 -- this routine is for getting the source object
(
src=c
sobj.text=c.name
)
fn getcollisions c=	 -- this routine is for getting the collision objects
(
for i=1 to c.count do
(
if finditem obj c[i]==0 then append obj c[i]
)
updatelist()
)
 
--------------------------------------------------------------------------------
-- EVENTS
--------------------------------------------------------------------------------
-- Pick source object
on sobj picked c do getsource c
 
-- Add collision objects by list
on addl pressed do
(
c=selectbyname title:"Select editable mesh's" filter:elementfilter(c)
if c!= undefined then getcollisions c
)
 
-- Add collision objects by picking in the viewport
on addp picked c do getcollisions #(c)
 
-- Remove collision objects
on rem pressed do
(
for i=1 to obj.count do
(
if cobj.selected==obj[i].name then (deleteitem obj i; exit)
)
updatelist()
)
 
-- When the script opens, analyse the selection to see if it is useful.
on lsercontrol open do
(
if selection.count==1 then
(
getsource selection[1]
) else
(
if selection.count!=0 then getcollisions (selection as array)
)
)
--------------------------------------------------------------------------------
-- This is where the magic happens! 
--------------------------------------------------------------------------------
on fire pressed do
(
if src==undefined then
(
messgebaox "You need to choose a source object for your laser beam." beep:true
) else
(
spos=src.pos	-- the source pos
d=src.dir	-- the source dir
lpnts=#()	-- initialize an array to hold the collision opints
append lpnts spos -- add the starting position to the array
i=0
-- calculate the collisions positions, and the ray trace vectors
while (i!=undefined) and (lpnts.count<mxnm.value) do -- when there is a collision and the total number of collsiion is under n
(
	i=(calcintersections lpnts[lpnts.count] d obj) -- calculate collisions, get the closest one
	if i!=undefined then		 -- if this returns a valid position,
	(
-- format "point:%	%
" i d
	 d=reflectance d (i[1].dir)	 -- calculate the reflectance vector
	 append lpnts i[1].pos	 -- and add it to the list
	) --else d=undefined		 -- if it's not valid, then set the loop to end.
)
-- format "% %
" i d
append lpnts ((d*over.value)+lpnts[lpnts.count]) -- add the final laser beam from the final collision.
 
-- create the laserbeam
lsrbm=splineshape pos:src.pos			 -- initiate a splineshape
s=addnewspline lsrbm			 -- add a spline
for i=1 to lpnts.count do addknot lsrbm s #corner #line lpnts[i] -- add all of the knots
updateshape lsrbm			 -- update the shape
 
-- set the splines renderable parameters.
lsrbm.baseobject.renderable=rnd.checked
lsrbm.displayrendermesh=vwp.checked
lsrbm.thickness=thck.value
 
-- make the collision objects flash.
flashnodes obj
)
)
)
--------------------------------------------------------------------------------
try closerolloutfloater newroll		 -- close the roulout if it is already open
catch()
newroll=newrolloutfloater "Laser." 260 350 800 100
addrollout lsercontrol newroll
)
--------------------------------------------------------------------------------
-- end of script
-- [www.joshuanewman.net]( http://www.joshuanewman.net/) 
-- copyright 2005
--------------------------------------------------------------------------------
 

Hi Scripteroonies,

I’ve updated my script but have a minor bug so I’m going to post it here as a download. I’ve added a preview option using gw drawing methods which I always seem to have trouble with (ok not always but quite a lot!). I think it might be something to do with my video card so if you can test it and even have a look I would appreciate it.
Basically when you move the source object it draws the path of the laser without creating any objects. It’s a great option since it makes the whole thing a bit more interactive since when opening the script you really don’t have much of an idea what to do.

download

Thanks again for looking.

J.

Page 1 / 2