PDA

View Full Version : Small(ish) LScript tutorial for beginners!

Tom Speed
08-13-2003, 07:49 PM
Hi,

Here's an LScript that I started commenting and thought what the hell....turn it into a small tutorial for beginners :)

I'm assuming (hoping!) you have some basic knowledge of variables, arrays, for/next loops e.t.c.

The Script:
I wanted to quickly 'fan-triple' a selection of Polygons, here's how I went about doing it.

My Plan:
In psuedo code it goes like this:

Check the user has selected some polygons, if not exit.
Record the user selected Polygons so we can later delete them.

For each Polygon selected, repeat the following:

Get all the IDs of the Points that make up this Polygon (the method to do this has a nice side effect, more about that later)
Find the center point of the Polygon by averaging the Positions of all its Points
Add a new Point at the center positon

Loop through all this Polygons Points, from Point 1 to Point[last - 1] adding a Triangle using the Points as follows:

Center Point, PolyPoint 1, PolyPoint 2
Center Point, PolyPoint 2, PolyPoint 3
...
repeat until Number of Points - 1

Center Point, PolyPoint(LAST), PolyPoint1

Clear our Polygon Selection (because newly added Polygons are automaticaly selected)
Reselect the initial Polygon selection
Delete them

Done!

Now to implement all this into a script!

// In the header we can tell LScript some things about the script.
@version 2.6 // The minimum LScript version required to run this script
@warnings // Some operations can give non critical warnings, this will suppress those warnings and prevent the need for user input
@script modeler // This is a Modeler script
@name TriPolyFan // The name of the script as seen in Modeler, if omitted Modeler will use the filename as the script name

main
{
/* first thing to do is check the user has a selection of Polygons for us to work with.
There are 3 selection modes, USER, GLOBAL & DIRECT
In USER mode LScript will only see the selected polygons, OR, if none are selected it will see ALL polygons.
Additionaly USER mode MUST be selected for us to do things like select a polygon or point ourselves

In GLOBAL mode LScript sees ALL polygons or points and disregards any user selections
In DIRECT mode LScript reports back exactly what the user has selected, or 0 if nothing is selected*/

selmode(DIRECT);

/*The next line actualy returns an array of information to the variable 'pc'. The first element of that array is the Polygon count
As we are in DIRECT mode, it will return an accurate count of selected Polygons*/
pc=polycount();

// Check array element [1] to see if the user has selected some Polygons
if(pc[1] < 1) // is the polygon count < 1?
return; // if it's < 1, the user hasn't selected any polys, so exit back to Modeler

/*Ok, we're ready to go! Let's change to USER mode now, as later on we'll want to select some polygons, and USER mode
must be set for us to do this*/
selmode(USER);

/*Operations to get point IDs, add points, add polygons e.t.c are considered 'Mesh Editing'. LScript must be set to a special
mode before you can do these things.*/
editbegin(); // Start a 'MeshEdit' session (MUST be closed later using editend())

/*Whilst within a 'MeshEdit' session, there exists 2 special arrays, called points[] and polygons[]. These 2 arrays
contain the IDs of the points & polygons respectively. If you're in USER mode, they contain only the selected points
or polygons, if in GLOBAL they contains ALL point & polygon IDs

Lets record the currently selected Polygon IDs so we can select them later*/
SelectedPolys = polygons;

/*Now we want to visit each selected polygon in turn, and perform the same operations on each

We're going to use the foreach() function
Example: if we had an array tom[1]=1 tom[2]=3 tom[3]=5
foreach(t,tom)
{
.. do something ..
}
Array 'tom' has 3 elements, so the foreach() loop would happen 3 times, 1st loop t would equal 1, next loop t=3, next loop t=5*/

foreach(pol,polygons) // for each element in the array 'polygons', let 'pol' = that element
{
// (Re)Initialise some variables we'll be using. This is important when you're reusing them each loop!
CenterPosition = <0,0,0>; // Set the Vector variable to 0,0,0
PointIDs = nil; // Clear PointIDs
PolyData = nil; // Clear PolyData

/*polyinfo() returns an array of information about the Polygon specified. The first element PolyData[1] contains the
String name of the surface that this Polygon is assigned to
The rest of the elements (PolyData[2] to PolyData[last]) contain the Point IDs of the Points that make up this Poly */
PolyData = polyinfo(pol);

/* Now we'll loop through the PolyData array to get the Point IDs for this Polygon, and the Points Positions
This time we'll use a regular for() loop as we want to ignore element [1] (the surface name)

Quick note about the += operator
In LScript, if a variable is not declared before the += (overload operator) is used on it, it will get promoted to
Array status.
Above we assigned CenterPosition a value, if we didn't, in the lines below: CenterPosition += pointinfo(PolyData[n]);
CenterPosition would get promoted to an Array!
i.e we would have CenterPosition[1] CenterPosition[2] ... e.t.c, which is not what we want :) */

for(n=2;n<=size(PolyData);n++) // loop through PolyData[2] to PolyData[end]
{
PointIDs += PolyData[n]; // Add this Point ID to our arrays of IDs
CenterPosition += pointinfo(PolyData[n]); // Add the Position of this Point to CenterPosition
}

// Now to find the Average Position of all the Points in this Polygon, we simply divide CenterPosition by the Point count
CenterPosition /= size(PointIDs); // The size() of the PointIDs array is the same as the Point count

// Let's add the center point!
cPoint = addpoint(CenterPosition); // cPoint = the ID of the newly created Point

/* Now we have our Center Point, we can add all our Triangles.
Remember earlier I commented that getting a Polygons Point IDs has a nice side effect? It's not really a side effect,
just something cool :)
Point IDs are returned in the 'clockwise' order that they make up the Polygon! It might not mean much to you at the
moment, but it's important as the order in which you specify Points when creating Polygons, as we are about too, defines
which side the 'normal' (the actual face) points.

Loop from PointIDs[1] to PointIDs[last - 1]
Each loop we gather 3 Point IDs that will make up each new Triangle Poly
NewPolyIDs[1] always equals our new center point 'cPoint'
NewPolyIDs[2] = PointIDs[n]
NewPolyIDs[3] = PointIDs[n + 1]
Because we are using n + 1 ^^ we can't loop directly to the last PointID else we'd get an error
so the last Triangle we create when this loop is finished */
for(n=1;n<size(PointIDs);n++) // note we're only looping while n < size(PointIDs) !
{
NewPolyIDs[1] = cPoint;
NewPolyIDs[2] = PointIDs[n];
NewPolyIDs[3] = PointIDs[n+1];

// addpolygon() create a new Polygon using the Points specified in NewPolyIDs array
}

// Add the last Triangle, maintaining a clockwise order we use: Centerpoint, Last PolyPointID, First PolyPointID
NewPolyIDs[1] = cPoint;
NewPolyIDs[2] = PointIDs[size(PointIDs)]; // Last Point
NewPolyIDs[3] = PointIDs[1]; // First Point

// All done with this Selected Polygon, loop to next if there is one...
}

/* We're all done Mesh Editing, so end the MeshEdit session
All newly added geometry will now 'exist' */
editend();

// Last thing we want to do is Clear any selected Polygons, reselect the original user selection, then delete it
selpolygon(CLEAR);
selpolygon(SET,POLYID,SelectedPolys);
cut();

// Finished! woohoo
}

In case the formatting gets screwed up somehow, I've attatched the above script.

Hope it was of some use to someone :)

Cya!
Tom

p.s Formatting this post took longer than writing the tutorial LOL

Matt
08-14-2003, 02:09 AM
Cool! Thanks Tom, I wish more people would comment their code so others can learn from them!

:)

riki
08-14-2003, 07:47 AM
Sweet thanks for the Tut

Titus
08-14-2003, 10:08 AM
Good programmers comment their code :)

Jimzip
09-03-2003, 07:22 AM
Great stuff. LScript was covered briefly on the Worldwide tour, but it's very nice to see work like this to learn from also.

Thank you,
Jimzip :D