PDA

View Full Version : Script: QUAD-ifying Ball poles



jeric_synergy
08-31-2015, 05:03 PM
Has anyone made a script that,

if a poly in a Ball's pole is selected,
AND there's an even number of polys in the pole,


the script goes around and Merges every other poly, resulting in an all-quad pole?

(Obviously, this would attempt to work on any successful Loop that was all tris, or even partial Loops. It's up to the user to select the first poly.)

ernpchan
08-31-2015, 06:05 PM
You could see if this script does what you want.
https://www.lightwave3d.com/assets/plugins/entry/cm_polydivide/

jeric_synergy
08-31-2015, 06:49 PM
Not quite, because of the requirement of selecting all the polys and Merging them. The drawback is the actual POLE point is lost in this process.

In the description above, the tool is more specialized (understatement!) but preserves the pole point, and therefore works better with SubDs.

In fact, the thing I described doesn't HAVE to operate exclusively on even numbers of tris, it can just leave one unmolested. It'd be nice if it put alert msg in the status bar if that were the case.

Good call though. Very close.

Kryslin
09-01-2015, 11:04 PM
I've got half of the solution - sp_fusepolypairs. You have to manually select the pairs, but it does work.

@script modeler
@warnings off
@name Fuse Poly Pairs

main
{
//debug();
polys = nil;
plynfo = nil;
plysel = nil;
plysel += 0;
plysel += 0;
idx = 0;
selmode(DIRECT);
plynfo = polycount();
plycnt = plynfo[1];
if(plycnt == 0) error("No Polygons Selected!");
if((plycnt % 2) != 0) error("Need an even amount of polygons!");
editbegin();
polys = polygons;
editend();

idx = 1;
max = plycnt - 1;
while(idx <= max)
{
plysel[1] = polys[idx];
plysel[2] = polys[idx+1];
selpolygon(CLEAR);
selpolygon(SET,POLYID,plysel);
mergepols();
idx += 2;
}
selpolygon(CLEAR);
}


The code is kind of nasty, but it works. The problem with auto selection would be doing an adjacency test on the triangles, making sure all your pairs were next to each other, so they could be selected in turn.

jeric_synergy
09-02-2015, 12:32 AM
Nice, Kryslin! :thumbsup:

Adjacency: how about defining the workflow to be "Select the pole point, then run". Would that help with detecting pole polys? --I realize it makes the plugin absolutely specific.

Kryslin
09-02-2015, 10:31 AM
Actually, that's easy to do...

@script modeler
@warnings off
@name Quadify Poles

main
{
//debug();
polys = nil;
plynfo = nil;
plysel = @0,[email protected];
idx = 0;
selmode(USER);

//Let's Grab a point, and grab the polygons it's
//a part of.

pcnt = pointcount();
if (pcnt < 1) error("Select a pole point!");
editbegin();
my_pole = points[1];
editend();

//Get it's polygons and select them.
my_sel = my_pole.polygon();
selpoint(CLEAR);
selpolygon(CLEAR);
selpolygon(SET, POLYID, my_sel);

plynfo = polycount();
plycnt = plynfo[1];
if(plycnt == 0) error("No Polygons Selected!");
if((plycnt % 2) != 0) error("Need an even amount of polygons!");
editbegin();
polys = polygons;
editend();

idx = 1;
max = plycnt - 1;
while(idx <= max)
{
plysel[1] = polys[idx];
plysel[2] = polys[idx+1];
selpolygon(CLEAR);
selpolygon(SET,POLYID,plysel);
mergepols();
idx += 2;
}
selpolygon(CLEAR);
}

Select a pole point, and let 'er rip. Selects the polygons the point is a part of, selects pairs, and merges the polygons.

jeric_synergy
09-03-2015, 01:05 PM
Actually, that's easy to do...
Select a pole point, and let 'er rip. Selects the polygons the point is a part of, selects pairs, and merges the polygons.
Dood, THAT IS SWEET!!!

Bang! All quads. Very nice. :thumbsup:
++++

How does one get the LW3dG to host plugins/scripts so this doesn't get lost? Some they do and some they don't.

jeric_synergy
09-03-2015, 06:07 PM
Found an odd behaviour:

I wanted to enjoy the quadifying while subds were on, so I subd' the standard globe, selected the pole point, ran the script,.... nothing. Figured that's because there's no Faces when all have been subd'd.

Possibly related: ran the script, then backed out using UNDO. When I tried to run it again, no go.

Just figured you'd like to know. As long as I don't pull any shenanigans it works fine.

Kryslin
09-04-2015, 12:37 AM
Ok, I've made the standard ball (24 sides, 12 segments), pressed tab, selected the pole point, and ran the script...

which worked flawlessly. I had a flash of selected polygons, which then got merged. Lightwave 2015.3, In case it matters.

I did, however, get the second one. I'll look at crushing those.

I do see where one improvement can be made... I need to insert an Undo group begin/end, so you're not undoing n merge polygon operations, and not clobbering your undo history.

I know what the problem is, and it's the adjacency problem...

Ok, so now I need to implement a simple grab the next polygon that shares at least one common point besides the pole...

However, on a freshly created sphere, it works perfectly.

(I'm working on getting some hosting for a modest webpage. I'll get these things properly hosted soon.)

Kryslin
09-04-2015, 08:28 AM
I've got a working solution, but I want to test it out a bit more. I'm still not getting the first odd behavior, but I have smashed the second one with a simple adjacency test and swap sort routine. Might take a while to run on large selections, because of nested loops ( and a peculiarity of lscript, which I'll report in, just in case...).

jeric_synergy
09-04-2015, 08:30 AM
Sounds great. --I wonder if I was just repeating the UNDO error with my first subd problem.....

Oooooo "Undo group", never heard that in LScript discussions before. I wonder what the python equiv is?

ernpchan
09-04-2015, 08:52 AM
Sounds great. --I wonder if I was just repeating the UNDO error with my first subd problem.....

Oooooo "Undo group", never heard that in LScript discussions before. I wonder what the python equiv is?

Use the same Modeler command.
http://static.lightwave3d.com/sdk/2015/python/pris_modeler.html?highlight=undo#lwsdk.pris.modele r.undogroupbegin

jeric_synergy
09-04-2015, 09:42 AM
Thanks..... at the top of that page, there's a sentence:


Functions based on CommandSequence commands will return an integer code that corresponds to one of the following values:

My programming is VERY weak: do you have to query to get each of the resulting codes? If they're just returned, how are they delimited?

ernpchan
09-04-2015, 10:04 AM
You might have to do a bitwise operation on them to get the integer code. Then you check against that.

jeric_synergy
09-04-2015, 11:14 AM
I was kinda surprised there didn't seem to be a table of values on that page. Would that make sense?

ernpchan
09-04-2015, 12:45 PM
I was kinda surprised there didn't seem to be a table of values on that page. Would that make sense?

This is just my guess...but if the intent is to use a bitwise operator...then the returning value might change as sdk changes happen. So if you always use a bitwise operator to check against then you're guaranteed to get the proper condition check value versus a hard coded value.

jeric_synergy
09-04-2015, 02:36 PM
I must not get what a bitwise operator is: I thought that it was like a flag embedded bitwise in, say, a byte. So that each bit in a returned byte was a flag. ::sigh::

Oh yeah, this is why I bailed on computer science....

ernpchan
09-04-2015, 03:04 PM
I must not get what a bitwise operator is: I thought that it was like a flag embedded bitwise in, say, a byte. So that each bit in a returned byte was a flag. ::sigh::


See if this thread helps in understanding bitwise.
http://forums.newtek.com/showthread.php?146606-Ask-Layout-if-an-Item-is-set-to-Unseen-by-Camera-or-Matte-Object&highlight=bitwise

jeric_synergy
09-04-2015, 04:16 PM
that's pretty much what I thought, although an example of the specific syntax is EXTREMELY helpful. Thanks for the link.

I find it alarming that an experienced user such as Nanogator had never heard of LWObjectInfo, --to me that indicates that ferreting out useful information from the dox continues to be difficult and fraught with pitfalls. :(

ernpchan
09-04-2015, 05:35 PM
Yes the LW dox are an adventure.

I don't have Ryan Roye's python tutorial series but I imagine they're very helpful.

Kryslin
09-04-2015, 10:51 PM
Now that I have a few minutes, I can take care of this...

Again, select your pole point, and let 'er rip. Sorts the selection so that adjacent polygons (ie, share a common edge) are also adjacent in the list used internally for selection. Refactored the resulting mess into something readable... and added some comments.


//Quadify Poles Ver. 1.1
//by Steven Pettit
//03 Sept 2015

@script modeler
@warnings off
@name Quadify Poles

main
{
m_polys = nil;
my_sel = nil;
pnts_a = nil;
pnts_b = nil;

plysel = @0,[email protected];
idx = 0;
pcnt = 0;
my_pole = 0;
plycnt = 0;
i = 0;
j = 0;

selmode(DIRECT);

//Let's Grab a point, and grab the polygons it's a part of.
pcnt = pointcount();
if (pcnt < 1) error("Select a pole point!");
editbegin();
my_pole = points[1];
editend();

//Get it's polygons and select them.
selmode(USER);
undogroupbegin();
my_sel = my_pole.polygon();
selpoint(CLEAR);
selpolygon(CLEAR);
selpolygon(SET, POLYID, my_sel);
plycnt = my_sel.count();

editbegin();
m_polys = polygons;
//I don't want to deal with wrapping a value, so...
// I add the first value to the end of the list.
m_polys += polygons[1];

//I need to sort the polygons, so they are adjacent to each other...
for(i=1;i<=plycnt;i++){
//Get the point IDs for polygon[i]
pnts_a = nil;
pnts_a = getpolypts(m_polys[i], my_pole);
for(j=i+1; j <= m_polys.count(); j++){
//Get the point IDs on the polygon we're testing
pnts_b = nil;
pnts_b = getpolypts(m_polys[j],my_pole);
if( adjacent_test(pnts_a,pnts_b) && ( j != (i+1))){
//We've got an adjacent polygon that is not adjacent in the list
//So, we'll swap them, and break out of the loop.
tmp = m_polys[i+1];
m_polys[i+1] = m_polys[j];
m_polys[j] = tmp;
j = m_polys.count() + 1;
}
}
}
editend();

idx = 1;
max = plycnt - 1;
while(idx <= max)
{
plysel[1] = m_polys[idx];
plysel[2] = m_polys[idx+1];
selpolygon(CLEAR);
selpolygon(SET,POLYID,plysel);
mergepols();
idx += 2;
}
undogroupend();
selpolygon(CLEAR);
}

rot: qA
{
//Rotate Left for an array of 3 elements.
tmp = qA[1];
qA[1] = qA[2];
qA[2] = qA[3];
qA[3] = tmp;
return(qA);
}

getpolypts: qA, qP
{
//Get's the point IDs for polygon qA, and rotates point ID qP
//(the pole point ID) into the first index - that makes the
//adjacency test simpler to code.

retv = nil;
k = 0;
for(k=1;k <= qA.pointCount;k++) retv += qA.points[k];
while(retv[1] != qP) { retv = rot(retv); }
return(retv);
}

adjacent_test: qA, qB
{
//Simple Adjacency Test, to see if qA and qB share a common
//point besides the pole, which is index 1 of both arrays.
//qA and qB are arrays of point IDs.
//returns TRUE if at least 1 point is shared, false otherwise.

retv = false;
retv = ((qA[2] == qB[2]) || (qA[2] == qB[3]));
retv = retv || ((qA[3] == qB[2]) || (qA[3] == qB[3]));
return(retv);
}