PDA

View Full Version : scripting with booleans ...


deadalvs
12-27-2007, 11:15 PM
hey there.

i am currently scripting an «edge crusher» script with the boolean difference command.

but somehow the command cannot compute all results even though all the mesh pairs should be mathematically closed and ok. (history is off too !)

are there any known issues with the stability of the boolean commands ? any cv amount limitations ?

*help*

else, the script would be a little dream... :)

Gravedigger
12-28-2007, 03:01 AM
hey matthias
hmm..i already had some problems with the boolean command. but i can't tell you if this has something to do with your script.

maybe you could post the script or maybe a screenshot or whatever so we can better see your problem.

what do you try to do?

have a nice evening!

deadalvs
12-28-2007, 04:45 PM
aah, nice... night-active person !

:applause:

okay...

i'll post the script now...

one minute...

* * *

let me make an other post for that ...

deadalvs
12-28-2007, 04:46 PM
if (`window -exists "edgeCrusherWindow"` == 1){deleteUI "edgeCrusherWindow";}

window -title "edgeCrusherWindow" -mnb 0 -mxb 0 edgeCrusherWindow;
columnLayout -adjustableColumn 1;
setParent ..;
setParent ..;

frameLayout -label "INFO AND USE" -cll true -collapse 1;
columnLayout;
text -l "crushes poly edges for realism";
text -l "scripted by deadalvs, dec 07";
text -l "";
text -l "select edges before hitting the button";
text -l "";
text -l "DON'T USE TOO MANY FACES AT A TIME !";
text -l "";
text -l "uvs get ****ed up, just re-project them";
text -l "";
text -l "HAVE FUN !";

setParent ..;
setParent ..;

frameLayout -label "SETTINGS" -cll true;
columnLayout;
text -l "";
text -l "approximative edge Radius";
floatField -v 0.035 edgeRadiusFloatField;
text -l "subdivisions per unit";
intField -v 16 subdivIntField;
text -l "roughness [%]";
floatField -v 25 roughnessFloatField;
text -l "crushing probability [%]";
floatField -v 25 crushingProbabilityFloatField;
checkBox -l "use secondary crushing subdivision" secondaryCrushingBox;
text -l "";
text -l "";
button -label "CRUSH !" -command "d_crushEdges();";
setParent ..;
setParent ..;
showWindow edgeCrusherWindow;

global proc d_crushEdges(){
global float $edgeRadius;
$edgeRadius = `floatField -q -v edgeRadiusFloatField`;
global float $subdiv;
$subdiv = `intField -q -v subdivIntField`;


string $selectedEdges[] = `ls -sl -fl`;

for ($eachSelectedEdge in $selectedEdges){
string $buffer[];
$numTokens = `tokenize $eachSelectedEdge "." $buffer`;
global string $meshToCrush;
$meshToCrush = $buffer[0];

string $pi[]=`polyInfo -edgeToVertex ($eachSelectedEdge )`;
string $piParts[];
tokenize $pi[0] $piParts;
//print ("#verts: "+(size($piParts)-2)+"\n");
int $CVNum_A = $piParts[2];
int $CVNum_B = $piParts[3];
vector $PosA = `pointPosition -w ($meshToCrush + ".vtx[" + ($CVNum_A) + "]")`;
vector $PosB = `pointPosition -w ($meshToCrush + ".vtx[" + ($CVNum_B) + "]")`;
//calc both vertex normals for the active edge
vector $VTXNormalA = `d_getPolyVertexNormal(($meshToCrush + ".vtx[" + ($CVNum_A) + "]"))`;
vector $VTXNormalB = `d_getPolyVertexNormal(($meshToCrush + ".vtx[" + ($CVNum_B) + "]"))`;
//calc "edge normal" by averaging the two vertex normals
vector $edgeNormal = unit ($VTXNormalA + $VTXNormalB);
//print ($eachSelectedEdge + "\n");
//print ($edgeNormal + "\n");
float $edgeLength = abs ($PosA - $PosB);
spaceLocator -n "EdgeVertex_A" -p 0 0 0;
move -a ($PosA.x) ($PosA.y) ($PosA.z);
spaceLocator -n "EdgeVertex_B" -p 0 0 0;
move -a ($PosB.x) ($PosB.y) ($PosB.z);
aimConstraint EdgeVertex_A EdgeVertex_B;
//getRotation !
float $rotBX = `getAttr EdgeVertex_B.rotateX`;
float $rotBY = `getAttr EdgeVertex_B.rotateY`;
float $rotBZ = `getAttr EdgeVertex_B.rotateZ`;
vector $edgeOrientation = <<$rotBX, $rotBY, $rotBZ>>;
undo;
select -r EdgeVertex_A;
select -add EdgeVertex_B;
delete;
polyCylinder -r 0.05 -h (($edgeLength) / $subdiv * ($subdiv + 2)) -sx 4 -sy ($edgeLength * $subdiv +2) -sz 1 -ax 1 0 0 -rcp 0 -cuv 3 -ch 1 -n "crushCylinder_1";
//deformation Process
string $lastCreatedCylinderArray[] = `ls - sl`;
string $lastCreatedCylinder = $lastCreatedCylinderArray[0];
//$lastCreatedCylinder = "pCylinder1";
select ($lastCreatedCylinder + ".vtx[0:1000000]");
string $selectedCVArray[] = `ls -sl -fl`;

vector $PosLastCV = `pointPosition -w ($selectedCVArray[(size ($selectedCVArray)-1)])`;
vector $PosSecondLastCV = `pointPosition -w ($selectedCVArray[(size ($selectedCVArray)-2)])`;

//scale end 2nd last
select -r $selectedCVArray[0];
select -add $selectedCVArray[1];
select -add $selectedCVArray[2];
select -add $selectedCVArray[3];
select -add $selectedCVArray[(size ($selectedCVArray)-2)];
scale -r -p ($PosSecondLastCV.x) ($PosSecondLastCV.y) ($PosSecondLastCV.z) .1 .1 .1 ;

//scale end last
select -r $selectedCVArray[(size ($selectedCVArray)-3)];
select -add $selectedCVArray[(size ($selectedCVArray)-4)];
select -add $selectedCVArray[(size ($selectedCVArray)-5)];
select -add $selectedCVArray[(size ($selectedCVArray)-6)];
select -add $selectedCVArray[(size ($selectedCVArray)-1)];
scale -r -p ($PosLastCV.x) ($PosLastCV.y) ($PosLastCV.z) .1 .1 .1 ;

//calc max travel dist for not corrupting the model with randomizing the cvs
// r !< small edge length of crushCylinder, then divided by 2
vector $PosDistCV_A = `pointPosition -w ($selectedCVArray[6])`;
vector $PosDistCV_B = `pointPosition -w ($selectedCVArray[10])`;
global float $edgeDist;
$edgeDist = abs (mag ($PosDistCV_A - $PosDistCV_B));
global float $maxMoveDistX;
$maxMoveDistX = $edgeDist;

// move all cvs a little
//but first create a new selection
select -r $selectedCVArray;
select -d $selectedCVArray[0];
select -d $selectedCVArray[1];
select -d $selectedCVArray[2];
select -d $selectedCVArray[3];
select -d $selectedCVArray[(size ($selectedCVArray)-2)];
select -d $selectedCVArray[(size ($selectedCVArray)-3)];
select -d $selectedCVArray[(size ($selectedCVArray)-4)];
select -d $selectedCVArray[(size ($selectedCVArray)-5)];
select -d $selectedCVArray[(size ($selectedCVArray)-6)];
select -d $selectedCVArray[(size ($selectedCVArray)-1)];

string $selectedInnerCVArray[] = `ls -sl -fl`;

for ($eachInnerCV in $selectedInnerCVArray){
global float $maxMoveDistX;
$maxMoveDistX = $maxMoveDistX * .9 * ((`floatField -q -v roughnessFloatField`) / 100);
global float $edgeRadius;
$edgeRadius = `floatField -q -v edgeRadiusFloatField`;
$edgeRadius = $edgeRadius * .5 * ((`floatField -q -v roughnessFloatField`) / 100);

select $eachInnerCV;
move -r (rand (-$maxMoveDistX, $maxMoveDistX)) (rand (-$edgeRadius, $edgeRadius)) (rand (-$edgeRadius, $edgeRadius));
}
if (`checkBox -q -v secondaryCrushingBox` == 1){

polySubdivideFacet -dv 1 -m 0 -ch 1 $lastCreatedCylinder ;
select -r $selectedInnerCVArray;
ConvertSelectionToFaces;

string $selectedSubdividedFacesArray[] = `ls -sl -fl`;
for ($eachSubdividedFace in $selectedSubdividedFacesArray){
global float $maxMoveDistX;
$maxMoveDistX = $maxMoveDistX * 0.08;
global float $edgeRadius;
$edgeRadius = `floatField -q -v edgeRadiusFloatField`;
$edgeRadius = $edgeRadius * .45;

select $eachSubdividedFace;
move -r (rand (-$maxMoveDistX, $maxMoveDistX)) (rand (-$edgeRadius, $edgeRadius)) (rand (-$edgeRadius, $edgeRadius));
//end if checkBox
}
}

select -r $lastCreatedCylinder;
move -r (($PosA.x + $PosB.x)/2) (($PosA.y + $PosB.y)/2) (($PosA.z + $PosB.z)/2);
rotate -r ($edgeOrientation.x) ($edgeOrientation.y) ($edgeOrientation.z);
// end eachEdgeLoop
}


//booleans
select "crushCylinder_*";
select -d "*Shape*";
string $crushCylinderArray[] = `ls -sl -fl`;


for ($eachCylinder in $crushCylinderArray){

//$eachCylinder = "crushCylinder_1";
// print $eachCylinder;
global string $meshToCrush;
select -r $meshToCrush;
select -tgl $eachCylinder;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// deactivate booleans here by commenting out the polyBoolOp command !
polyBoolOp -op 2 -ch 0 -useThresholds 1;
pickWalk -d up;
rename ($meshToCrush);
select -cl;
//end booleanloop
}

//end d_crushEdges
}









//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// d_getPolyVertexNormal script

//input string
//output vector
/*
example
string $targetVertex = "pCube1.vtx[5]" ;

d_getPolyVertexNormal($targetVertex)
*/

global proc vector d_getPolyVertexNormal(string $targetVertex){

select $targetVertex;
string $buffer[];
$numTokens = `tokenize $targetVertex "." $buffer`;
string $targetMesh = $buffer[0];

string $pi[] = `polyInfo -vertexToFace`;
string $piParts[];
tokenize $pi[0] $piParts;
int $i;
int $faceID;
vector $vNorm = 0;
vector $fNorm;
string $pi2[], $piParts2[];
for ($i = 2; $i< size($piParts); $i++){
$faceID = $piParts[$i];
$pi2 = `polyInfo -faceNormals ($targetMesh + ".f[" + $faceID + "]")`;
tokenize $pi2[0] $piParts2;
$fNorm = << float ($piParts2[2]),
float ($piParts2[3]),
float ($piParts2[4]) >>;
$vNorm += $fNorm;
}
$vNorm = `unit $vNorm`;

return $vNorm ;

//end d_getPolyVertexNormal
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

deadalvs
12-28-2007, 04:56 PM
i hope that text can be copy-pasted wo it works properly !


• just select an edge of a cube or whatever object and hit the crush button.
• when the object disappears with an error, the boolean command failes
• the input filed about probability is not yet built-in, so altering that value does nothing.
• important: the boolean command is not executed when commented out at the proper position in the script. there's a note with a lot of ///////// signs.

the idea of the script is first creating a lot of randomized cylinders for each selected object and then subtract these from the selected object to simulate crushed edges.
the mentioned probability input field would move the geomety away from the «edge normal» that i calculate from the two vertex normals by averaging.

the script has still a few issues, especially the mentioned failing boolean command and that the cylinder is not the perfect type of object to be place on the edges...

...

i guess i'll have to re-write the script because it lacks a little of everything... well..

Gravedigger
12-28-2007, 05:03 PM
phu... i think you have still a lot of things in the script which could be shorted.
could you explain what the steps you're doing to achieve this effect?

the error message you get means that the boolean operation deletes all geometry. so maybe one of the objects is too big.

i'm sorry i don't have enough time to read through it because i'm going out tonight with some friends. if i'm still ok when i return i'll take some time to work on your problem.

have a nice evening and "pfuus de guet" ;-D

deadalvs
12-28-2007, 05:21 PM
ah ... noooo problem...

this is more a hobby-project than a rational to-use script ...

i know ... it's a little long and could certainly be majorly shortened, but this was just the first approach...

* * *

the steps.

1) window

2) procedure that crushed the edge (directly called from the window)
2.1) get values from GUI
2.2) list all selected edges
2.3) for each edge loop:
2.4) calc the two vertex normals
2.5) calc the edge normal
2.6) calc the xyz rotation in [deg] for an object to look from one vertex to the other
2.7) create a cylinder, deform it, maybe subdivide it if checkBox ==1
(the deformations are based on the cv circles along the cylinder. this is why the cvs are directly called... self-intersecting geometry cannot be computed by the boolean command, this is why the cv randomizing must be controlled locally inside the smallest distance between the cvs, divided by 2)
2.8) move the cylinder to place
2.9) rotate the cylinder
2.10) end loop

3.1) select all cylinders
3.2) run thru each cylinder and boole it away.
3.3) rename the newly booled surface to the old name

* * *

don't bother ... a solution is not really needed... if the boolean command cannot trim meshes with many faces/subdivisions, the script itself is useless... !

have a nice evening !

greets !

Gravedigger
12-29-2007, 01:27 PM
your scripting style could still be improved :-D it was quite exhausting to read through.

what i can say about your script is that it's working. the problem is that your cylinder objects are heavily deformed and because of this you can't use them for boolean operations. well you can but the result is an object without geometry.

here you can see one of those overdeformed cylinders:

http://patrikhadorn.ch.vu/screen.jpg

you can see that with this object you can't really calculate the boolean operation.

another problem with your script is that you get a lot of n-gons which could make some problems during the render process

deadalvs
12-29-2007, 01:48 PM
if i ever had learned scripting properly... :(
yes, i hate the looks of the script too... i've made better ones... way better ones .. ! hehe.

i know there are issues with over-deformed cylinders when going above 100% roughness... but even with very little deformation that normally should work, i have gotten proplems with the boolean command...

the n-gons certainly are an issue, but remapping the UVs helps a bit for the looks...

* * *

i guess the approach with booleans is a simplistic one... but thinking of a different way to do this sort of crushing effect... i could not find an other fast answer.

CGTalk Moderation
12-29-2007, 01:48 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.