Particle Instancer Problem

Hello,

Im trying to shatter up windows in a building ive created. The first part of the code works out the center of each window on the building and creates a simple polyCube to represent the glass/window.

I then shatter up the window, create particles at the window shard positions and then instance the shards to the particles.
This is nice n neat as it by passes the nasty rigid body systems which are full in interpenetration errors and the like.

The issue I have is that when the shards are created, they inherit the original cubes pivot point. Using the center pivot command, the shards appear to center their pivots closer to their own body of mass.
When querying this position information per shard then emiting a particle at these positions per shard, the particles still adopt the original cubes pivot point, not the shards position.

The secondary issue this creates is that when i come to instance the shards to the particles, the shards will instance with the original cubes pivot point also. This means that each shard object is controlled from the same point making the simulation incorrect.

I need to be able to first, move the pivot to the center of each shard, then, create a particle at that point, and then finally, instance the object without the shards moving out of shape (tesselation).

Hope that makes sense

Any help would be most appreciated.

Code:
Shatter code based on the 'simple shatter code' in the mel scripts section at highend3d.

CODE
//loop through each window and shatter accordingly.
//$former_windows is a list of the window objects.

for ($o=0; $o<size($former_windows); $o++)
{
    select $former_windows[$o];
    DeleteHistory;
    float $bb[] = `polyEvaluate -boundingBox ($former\_windows[$o])`;

    for ($i = 0; $i < 7; $i++)
    {
        float $px = rand(($bb[0]0.95),($bb[1]0.95));
        float $py = rand(($bb[2]0.95),($bb[3]0.95));
        float $pz = rand(($bb[4]0.95),($bb[5]0.95));
        float $rx = rand(0,180);
        float $ry = rand(0,180);
        float $rz = rand(0,180);
        polyCut -pc ($px)($py)($pz) -ro ($rx)($ry)($rz) -ef 1 -eo 0 0 0 ($former_windows[$o]);
        polyCloseBorder ($former_windows[$o]);
    }
    select -r ($former_windows[$o]);
    polySeparate ($former_windows[$o]);

//visual progress output
float $percent = ($o/(float)(size($former_windows))*100);
string $perc = (int)$percent + "%" + "\n";
print $perc;
}

simple center pivot loop:
CODE
//center all pivots
//$shards[] = list of all shards that make up the window object
for ($each in $shards)
{xform -centerPivots $each;}

simple rename loop:
CODE
//rename all shards for association purposes.
string $shards[] = ls -transforms "polySurface*";
string $token[];
for ($each in $shards)
{
tokenize $each "polySurface" $token;
string $name = "windowShard_" + $token[0];
rename $each $name;
}

particle instance code:
CODE
//create particle node
particle -name windowDyn;

//list all window shards
string $shards[] = ls -transforms "windowShard\_*";

//emit a particle at the center of each shard
for ($each in $shards)
{
    //get shard position
    float $shardPos[] = xform -q -ws -translation $each;

    //get shard volume
    float $bb[] = xform -q -ws -bb $each;
    float $x = abs($bb[3] - $bb[0]);
    float $y = abs($bb[4] - $bb[1]);
    float $z = abs($bb[5] - $bb[2]);
    vector $v = <>;

    //get the magnitude of the vector - use for particle mass
    float $mag = mag($v);

    //emit particle at center of the shard
    emit    -o windowDyn
            -pos $shardPos[0] $shardPos[1] $shardPos[2]
            -at mass
            -fv $mag;
}

//save the initial state
saveInitialState windowDyn;

QUOTE(divineavata @ 04/05/09, 08:41 PM) [snapback]305027[/snapback]
When querying this position information per shard then emiting a particle at these positions per shard, the particles still adopt the original cubes pivot point, not the shards position.

Position of a object and the pivot of the object are 2 different things. Only position ever counts. Pivot is justa a postion for a handle. So moving the pivot about doesnt do anything for you.

Read:

http://www.highend3d.com/boards/index.php?showtopic=256323

in essence if you move pivot you have moved nothing. Now move the objects pivot to the center of its current local zero and freeze you NOW have moved it.

QUOTE
This means that each shard object is controlled from the same point making the simulation incorrect.

You must move the reference or just counter offset yoru calculations.

Thanks joopaa.

Ive just read your article and its very informative. However, I'm still not 100% sure how I can solve my problem.

If the pivot point is simply a handle to manipulate the object, not a positional reference for the object, how can i manipulate/change the positional information for the shard objects (original example).

What would i need to do in maya to move the reference point to the center of the shard object,
then use that information to correectly emit a particle and place it at that vector position,
then finally instance the object without the instance moving from its current position?

My current method for aquiring the center point of each shard is to calculate the center point of each face, then the average of those points. This calculates a nice position within the shards mass to use for reference. I can then simply emit particles at this position.

The issue then comes however when trying to instance the object due to the above problem with the shards reference point. If I instance the shards to their respective particle, the resulting instanced geometry creates what can be best described as an exploded view from an engineering manual

Im still very new to maya, and havent worked out its deep inner workings which im sure are very simple once found and understood

The code to calculate the center point to use is as follows:

CODE
for ($each in $shards)
{
//get shard face count
int $count[] = polyEvaluate -face $each;

    //loop through each face to assertain the center points.
    for ($i=0; $i<$count[0]; $i++)
    {
        //face position
        string $face = $each + ".f[" + $i + "]";
        float $pos[] = `xform -q -ws -t $face`;

        //size of pos - size = 3 times vertex qty
        int $size = size($pos);    

        //take the position of the first vector
        float $x = $pos[0];
        float $y = $pos[1];
        float $z = $pos[2];
        vector $vec = <>;
        vector $sum = $vec;

            //loop through the face and create a vector sum
            for($o = 1; $o < ($size/3); $o++)
            {
            $x = $pos[$o*3];  
            $y = $pos[(($o*3)+1)];
            $z = $pos[(($o*3)+2)];

            $vec = <>;
            $sum = $sum + $vec;
            }

        //calculate the center of the face - (vecSum/vtxSum)
        $faceCenter = $sum/($size/3);

        //sum up each face center vector
        if ($i == 0)
            $shardCenter = $faceCenter;
        else
            $shardCenter = $shardCenter + $faceCenter;
    }

//calculate the center of the shard - (vecSum/faceSum)
$mid = $shardCenter/$count[0];

//emit particles at the center of the shards
emit    -o z1_b1_particleShape
        -pos ($mid.x) ($mid.y) ($mid.z)
        -attribute mass
        -floatValue $mag;
}

QUOTE(Joojaa @ 04/05/09, 09:47 PM) [snapback]305028[/snapback]
Now move the objects pivot to the center of its current local zero and freeze you NOW have moved it.

in code it looks like this:

CODE
//lets define a support function
global proc vector floatArrToVec(float $arr[]){
  return <>;
}

// move all selected objects origin to pivot
// assumes rotate pivot is the main pivot
// no check is made to test whether or not
// this is possible to do!
{
  for ($item in ls -sl){
    $orig=floatArrToVec(xform -q -os -t $item);
    $offset=floatArrToVec(xform -q -os -rp $item);
    $reverse=-1*$offset;
    $offset=$offset+$orig;
    xform -os -t ($reverse.x) ($reverse.y) ($reverse.z) $item;
    xform -p 1 -ra 0 0 0 $item;
    makeIdentity -apply 1  -t 1 -r 1 -s 1;
    xform -os -t ($offset.x) ($offset.y) ($offset.z) $item;
  }
}

I also reset the rotation at same time

PS: what you read in the channelbox is where the object is actually located.

Hello,

Thanks for that, I'll have a look and see what I can do
Many thanks for your help.

Hey joojaa,

I've tried to implement your method into my own code. I get a syntax error though for the line:

CODE
$reverse = $offset * -1;

as $reverse is a vector, I thought that perhaps it needed to multiplied by a vector rather than a singular number (<>, however that also gave syntax errors.

Any thoughts?

It will only work if maya explicitly kows its been cast as a vector. Anyway you dont need to implement it into your code you can just call it for whatever selection you need it to happen.

Hello,

Yeah, I've purposely stated

CODE
vector $reverse;
vector $offset;

before the loop to tell maya its a vector. However, it still doesnt like the statement

CODE
$reverse = $offset * -1;

theres got to be something fundamentally simple that im overlooking as I cant see why "$var * -1" doesnt work. :S

CODE
vector $reverse;
vector $offset;

That does not mean anything if you later call something that puts in a float array in a subsequent block then the previous declaration looses its meaning. Array variables cant be mutiplied with, and that makes perfect sense.

Hello,

Sussed the problem. Silly me. I missed out a ";".
No wonder it was getting confused.

Now the code works, however, the shards still have the same origin. The shards positions didnt change to the rotate pivots position.

Edit:
I tried to do the scripts operation 1 line at a time, and discovered what may have been the issue, and thats that the values of the objectSpace were 0,0,0. Ofc this would play silly-buggers with the calculations.

if i moved the shards away from the place they were created, the code worked, and the generation of both the particle and the instance worked as well. However, the problem i face now is automating it for every shard. When i do this it doesnt work correctly.

But the code does work and manually executing it line by line for a single shard did prove the code to work .

Sometimes you may find maya errors silently and when it does so yoru code is not fully run so it appears to work wrong.

Because you can run line by line it means some variable is out of scope somehow.