PDA

View Full Version : Get positions of multiple objects in scene


Oluphant
11-13-2011, 11:58 AM
Hello everyone, it's me again, hope you can help me once again. I am working on a script that generates multiple spheres and a cube (amongst other things), I want to be able to calculate the distance between the circles and this one cube. Does anyone know how to do that? This is the code I have come up with so far, the pertinent code is on the last 10 lines:

proc makeSpheres( int $amount,string $groupName, string $emitterName, string $particleName, string $sphereName, string $volumeAxisName, string $controllerName) {

global int $amount; //defines how many spheres are created

global string $sphereName; //the name of the sphere

global string $controllerName;// the name of the controller

string $baseSphereName = $sphereName; //this cleans up the names of the objects.

string $baseEmitterName = $emitterName;// if you plug in $emitterName+$i the naming will look something like this: object1, object12, object123, object1234, object12345 etc.

string $baseParticleName = $particleName;

string $baseVolumeAxisName = $volumeAxisName;

for ($i=1; $i<=$amount;$i++)

{

$sphereName = ($baseSphereName+$i);

$particleName = ($baseParticleName+$i);

$emitterName = ($baseEmitterName+$i);

sphere;

rename $sphereName;

select -cl;

//the below script creates an emitter and connects the dynamic to the nParticle

emitter;

rename $emitterName;

nParticle;

rename $particleName;

connectDynamic -em $emitterName $particleName;

//create the volume axis field and connect it to the nParticle

select -cl;

select -r ($baseParticleName+$i);

addAttr -is true -ln "betterIllumination" -at bool -dv false ($baseParticleName+$i);

addAttr -is true -ln "surfaceShading" -at "float" -min 0 -max 1 -dv 0 ($baseParticleName+$i);

string $volume[] = `volumeAxis -pos 0 0 0 -name ($volumeAxisName+"_"+$i) -m -6 -att 0.485 -ia 0 -afc 0.132 -afx 1 -arx 0 -alx 0 -drs 0 -dx 1 -dy 0 -dz 0 -trb 0 -trs 0.2 -tfx 1 -tfy 1 -tfz 1 -tox 0 -toy 0 -toz 0 -dtr 0 -mxd -1 -vsh sphere -vof 0 0 0 -vsw 360 -tsr 0.5 `;

connectDynamic -f $volume[0] $particleName;

// Result: nParticleShape1 //

connectAttr time1.outTime ($volume[0]+".time");

// Result: Connected time1.outTime to volumeAxisField1.time. //

//the below script parents the emitter and particle to the sphere

//therefore when I move the sphere, the emitter moves with it

select -cl;

select ($baseParticleName+$i);

select -add $volume;

select -add ($baseEmitterName+$i);

select -add ($baseSphereName+$i);

parent;

select -cl;

}

//the below script generates random positions within the values specified

for($i=1;$i<$amount;$i++)

{

select ($baseSphereName+$i);

$x = rand(-5,5);

$y = rand(0,2);

$z = rand(-6,8);

move $x $y $z;

select -d;

}



//the cube below will control the sweep attributes change

polyCube ;

rename $controllerName;

move 0 10 0;

select -cl;

for ($i=1; $i<=$amount;$i++)

{

float $spherePositions = ($sphereName+".translateX" $sphereName+".translateY" $sphereName+".translateZ");

float $controlPosition = ($controllerName+".translateX" $controllerName+".translateY" $controllerName+".translateZ");

float $difference = $spherePositions - $controlPosition;

getAttr ("makeNurbSphere"+$i+".endSweep");

if ($difference =< 2) getAttr "makeNurbSphere"+$i+".endSweep" = 180;

else getAttr "makeNurbSphere"+$i+".endSweep" = 360;

}

}

makeSpheres(12,"together","emitter","particle","premier","volume","control");

NaughtyNathan
11-13-2011, 12:17 PM
oddly, this has been asked many times just this week..? what is going on? :)

storing positions and directions is best, and simplest done using the vector variable type:
vector $spherePositions = << ($sphere+".tx") , ($sphere+".ty") , ($sphere+".tz") >>;
// or, even simpler:
vector $spherePos = `getAttr ($sphere+".t")`;
// once you have two vectors, you can subtract them
// then use the mag command for the distance:
float $distance = mag($spherePos - $controlPos);
// the distance may be negative depending which point was given first
// so use the abs command to make it positive
$distance = abs($distance);

but bear in mind the .translation attribute won't usually give you the real position if your object is frozen, or is under any parents. better to use the xform command, or get the objects rotate pivot position instead.

:nathaN

Oluphant
11-13-2011, 01:15 PM
Hello Nathan,
many thanks for your post, I will try it out and let you know if it works. I've been banging my head against this trying to figure it out myself for the past 4 hours. I've tried arrays, I've tried creating procedures I don't know where I was going wrong but it was definitely not going right. Then again, I've only been working with MEL for about 6 weeks.

You said there were other posts regarding this, are they in this forum?

Oluphant
11-14-2011, 04:50 AM
oddly, this has been asked many times just this week..? what is going on? :)

storing positions and directions is best, and simplest done using the vector variable type:
vector $spherePositions = << ($sphere+".tx") , ($sphere+".ty") , ($sphere+".tz") >>;
// or, even simpler:
vector $spherePos = `getAttr ($sphere+".t")`;
// once you have two vectors, you can subtract them
// then use the mag command for the distance:
float $distance = mag($spherePos - $controlPos);
// the distance may be negative depending which point was given first
// so use the abs command to make it positive
$distance = abs($distance);

but bear in mind the .translation attribute won't usually give you the real position if your object is frozen, or is under any parents. better to use the xform command, or get the objects rotate pivot position instead.

:nathaN

Once again thanks for the answer, I seem to have run into a problem. When I wrote the code as you indicated I received the error message that no object matches the name .translate. Do you know why that is? Is there something else I have to do to get the script editor to execute the code? Also, the object is not under a parent but it is a parent, would that change the script in any way?

global proc getDistance()
{
global string $sphereName;
global string $controllerName;
global int $amount;

vector $spherePosition = `getAttr ($sphereName+".translate")`;
vector $controlPosition= `getAttr (($controllerName)+".translate")`;
float $distance = mag($spherePosition - $controlPosition);
$distance = abs($distance);
}

Thank you in advance

PozestStar
11-14-2011, 06:13 AM
You'll have to do translateX, translateY and/or translateZ, not just translate.

WesHowe
11-14-2011, 07:13 AM
When I wrote the code as you indicated I received the error message that no object matches the name .translate.


There is no place in your code where you assign any value to $sphereName or $controllerName. Thus they are empty, and ($sphereName+".translate") evaluates to just ".translate".

You need to integrate some way to set those variables to the name of the objects you want to calculate the difference on.

<* Wes *>

Oluphant
11-14-2011, 08:21 AM
There is no place in your code where you assign any value to $sphereName or $controllerName. Thus they are empty, and ($sphereName+".translate") evaluates to just ".translate".

You need to integrate some way to set those variables to the name of the objects you want to calculate the difference on.

<* Wes *>
if you look at my very first code I declare $sphereName as a global string. Was that not sufficient? If not what will be?

NaughtyNathan
11-14-2011, 10:46 AM
it doesn't matter if you've made it a global string or not. Your problem is that you've initialised $sphereName as a global string, but AFTER you have initialised and used it as an input parameter to your function. This is not valid. As soon as you initialise a new variable (in a new scope), it will override the previous variable (in it's current scope) and as the scope is global, the original $sphereName (the input parameter) is lost, giving you an empty string, and hence ".translate" as Wes pointed out.

Just get rid of all your gloabal strings, you don't need them. If you want to pass the sphere name to any other procs, just do it with an input parameter again.
global proc float getDistance(string $sphere, string $controller, float $amount)
Also, ignore what PozestStar said, she's new at this too! ;)

:nathaN

Oluphant
11-14-2011, 01:30 PM
it doesn't matter if you've made it a global string or not. Your problem is that you've initialised $sphereName as a global string, but AFTER you have initialised and used it as an input parameter to your function. This is not valid. As soon as you initialise a new variable (in a new scope), it will override the previous variable (in it's current scope) and as the scope is global, the original $sphereName (the input parameter) is lost, giving you an empty string, and hence ".translate" as Wes pointed out.

Just get rid of all your gloabal strings, you don't need them. If you want to pass the sphere name to any other procs, just do it with an input parameter again.
global proc float getDistance(string $sphere, string $controller, float $amount)
Also, ignore what PozestStar said, she's new at this too! ;)

:nathaN
Thank you so much for your replies, they have helped so much.I think I may finally know how to make this work. A toast to you Nathan :beer:

PozestStar
11-14-2011, 03:03 PM
Whoops, well I learned something else new! :p I should investigate before opening my mouth.

jwvanderbeck
11-15-2011, 02:38 PM
oddly, this has been asked many times just this week..? what is going on? :)

storing positions and directions is best, and simplest done using the vector variable type:
vector $spherePositions = << ($sphere+".tx") , ($sphere+".ty") , ($sphere+".tz") >>;
// or, even simpler:
vector $spherePos = `getAttr ($sphere+".t")`;
// once you have two vectors, you can subtract them
// then use the mag command for the distance:
float $distance = mag($spherePos - $controlPos);
// the distance may be negative depending which point was given first
// so use the abs command to make it positive
$distance = abs($distance);

but bear in mind the .translation attribute won't usually give you the real position if your object is frozen, or is under any parents. better to use the xform command, or get the objects rotate pivot position instead.

:nathaN

If I am dealing with transforms in a scripted node, and want to get say the transform of a camera as an input plug, would they be stored in the default nodes the same way, using a vector?

IOW is this correct?


# initializer
def nodeInitializer():
# inputs
nAttr = OpenMaya.MFnNumericAttribute();
CustomCamNode.inCamTranslate = nAttr.create( "sourceCameraTranslate", "sct", OpenMaya.MFnNumericData.k3Double, 0.0 )
nAttr.setStorable(1)
...........

def compute(self, plug, dataBlock):
dataHandle = dataBlock.inputValue(CustomCamNode.inCamTranslate)
inputVec = dataHandle.asDouble3()
.............

CGTalk Moderation
11-15-2011, 02:38 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.