![]() | ![]() |
Uzly DAG mohou také mít více otců - v takovém případě existuje více instancí tohoto uzlu - pro každého otce jedna. Např. DAG na obrázku vlevo reprezentuje dvě instance geom. objektu nazvaného Leaf. Na první instanci se aplikují transformace Transform1 a Transform3 a na druhou instanci transformace Transform2 a Transform3.
Pro práci s uzly DAG grafu můžete využít následující třídy:
Poloha každého uzlu v DAGu je jednoznačně určena pomocí cesty - třída MDagPath. Cesta je sekvencí transformačních uzlů zakončená danným uzlem. Např. cesta k první instanci uzlu Leaf je Transform1|Transform3|Leaf a cesta k druhé instanci Leafu je Transform2|Transform3|Leaf.
Chcete-li modifikovat některý uzel DAGu (nebo provádět nějaké operace s uzlem ve světových souřadnicích) nestačí znát pouze referenci na příslušný uzel (třída MObject), ale musíte také znát správnou cestu k tomuto uzlu, protože teprve až ta jednoznačně identifikuje instanci uzlu. Většina operací pracujících s uzly vyžaduje zadání jak reference na MObject tak cesty k tomuto objektu v DAGu. V závislosti na typu posledního uzlu v cestě lze aplikovat buď function sety pracující s tranformacemi nebo function sety pracující s geometríí určenou typem uzlu. Transformační matice můžete z transformačních uzlů vytáhnout pomocí následujících dvou operací:
Jako příklad si zde uvedeme jednoduchý plug-in, který bude procházet DAG do hloubky nebo do šířky a současně bude vypisovat jména uzlů reprezentujících nějaký světelný zdroj ve scéně.
class scanDagSyntax: public MPxCommand {
public:
scanDagSyntax() {};
virtual ~scanDagSyntax();
static void* creator();
static MSyntax newSyntax();
virtual MStatus doIt( const MArgList& );
private:
// Zpracování parametrů příkazové řádky.
MStatus parseArgs( const MArgList& args, MItDag::TraversalType& traversalType, MFn::Type& filter);
// Procházení DAGu - do hloubky nebo do šířky.
MStatus doScan( const MItDag::TraversalType traversalType, MFn::Type filter);
// Uživatelská metoda, která vypíše informace o transformacích.
void printTransformData(const MDagPath& dagPath);
};
// Konstruktor třídy.
scanDagSyntax::~scanDagSyntax() {}
// Metoda pro vytváření instancí této třídy.
void* scanDagSyntax::creator() {
return new scanDagSyntax;
}
#define kBreadthFlag "-b"
#define kBreadthFlagLong "-breadthFirst"
#define kDepthFlag "-d"
#define kDepthFlagLong "-depthFirst"
// Definice parametrů příkazové řádky.
MSyntax scanDagSyntax::newSyntax() {
MSyntax syntax;
syntax.addFlag(kBreadthFlag, kBreadthFlagLong);
syntax.addFlag(kDepthFlag, kDepthFlagLong);
return syntax;
}
// Provede akci požadovanou po plug-inu.
MStatus scanDagSyntax::doIt( const MArgList& args ) {
MItDag::TraversalType traversalType = MItDag::kDepthFirst;
MFn::Type filter = MFn::kInvalid; // počáteční nastavení filtru - bez filtrování
MStatus status;
status = parseArgs ( args, traversalType, filter );
if (!status)
return status;
return doScan( traversalType, filter );
};
// Zpracování parametrů příkazové řádky.
MStatus scanDagSyntax::parseArgs(const MArgList& args, MItDag::TraversalType& traversalType, MFn::Type& filter) {
MStatus stat;
MArgDatabase argData(syntax(), args);
if (argData.isFlagSet(kBreadthFlag))
traversalType = MItDag::kBreadthFirst;
else
if (argData.isFlagSet(kDepthFlag))
traversalType = MItDag::kDepthFirst;
filter = MFn::kLight;
return stat;
}
// Vlastní procházení DAGu.
MStatus scanDagSyntax::doScan( const MItDag::TraversalType traversalType, MFn::Type filter, bool quiet) {
MStatus status;
// Inicializace iterátoru pro procházení DAGu od shora dolů.
MItDag dagIterator(traversalType, filter, &status);
if ( !status) {
status.perror("MItDag constructor");
return status;
}
// Procházení DAGu s vypisováním jmen uzlů a jejich hloubky.
if (traversalType == MItDag::kBreadthFirst)
cout << endl << "Starting Breadth First scan of the Dag";
else
cout << endl << "Starting Depth First scan of the Dag";
int objectCount = 0;
// Procházení DAGu pomocí iterátoru.
for ( ; !dagIterator.isDone(); dagIterator.next() ) {
MDagPath dagPath;
// MItDag::getPath() vrací cestu k objektu na kterém právě stojí iterátor.
// Není dobrý nápad měnit DAG během použití iterátoru.
status = dagIterator.getPath(dagPath);
if ( !status ) {
status.perror("MItDag::getPath");
continue;
}
MFnDagNode dagNode(dagPath, &status);
if ( !status ) {
status.perror("MFnDagNode constructor");
continue;
}
cout << dagNode.name() << ": " << dagNode.typeName() << endl;
cout << " dagPath: " << dagPath.fullPathName() << endl;
objectCount += 1;
if (dagPath.hasFn(MFn::kLight)) { // je-li uzel skutečně světlo, pak pokračuj
// zde je tento test zbytečný.
MFnLight light (dagPath, &status);
if ( !status ) {
status.perror("MFnLight constructor");
continue;
}
// Vypiš transformace.
printTransformData(dagPath);
// Výpis některých informací o světle.
MColor color;
color = light.color();
cout << " color: [" << color.r << ", " << color.g << ", " << color.b << "]\n";
color = light.shadowColor();
cout << " shadowColor: [" << color.r << ", " << color.g << ", " << color.b << "]\n";
cout << " intensity: " << light.intensity() << endl;
cout.flush();
}
setResult(objectCount); // Výsledkem příkazu je počet zpracovaných světel.
return MS::kSuccess;
}
// Následující metoda vypíše informace o transformačním uzlu pro světlo určené dagPath.
void scanDagSyntax::printTransformData(const MDagPath& dagPath, bool quiet) {
MStatus status;
// dagPath::transform() vrací nadřazený transformační uzel.
MObject transformNode = dagPath.transform(&status);
// Tento uzel nemá transformační matici
if (!status && status.statusCode () == MStatus::kInvalidParameter)
return;
MFnDagNode transform (transformNode, &status);
if (!status) {
status.perror("MFnDagNode constructor");
return;
}
// Vytažení transformační matice z uzlu.
MTransformationMatrix matrix (transform.transformationMatrix());
cout << " translation: " << matrix.translation(MSpace::kWorld) << endl;
double threeDoubles[3];
MTransformationMatrix::RotationOrder rOrder;
matrix.getRotation (threeDoubles, rOrder, MSpace::kWorld);
cout << " rotation: [" << threeDoubles[0] << ", " << threeDoubles[1] << ", " << threeDoubles[2] << "]\n";
matrix.getScale (threeDoubles, MSpace::kWorld);
cout << " scale: [" << threeDoubles[0] << ", " << threeDoubles[1] << ", " << threeDoubles[2] << "]\n";
}
// Metoda volaná při inicializaci plug-inu.
MStatus initializePlugin( MObject obj ) {
MStatus status;
MFnPlugin plugin ( obj, "Alias - Example", "2.0", "Any" );
status = plugin.registerCommand( "scanDagSyntax",
scanDagSyntax::creator,
scanDagSyntax::newSyntax );
return status;
}
// Metoda volaná při odstraňování plug-inu z Mayi.
MStatus uninitializePlugin( MObject obj ) {
MStatus status;
MFnPlugin plugin( obj );
status = plugin.deregisterCommand( "scanDagSyntax" );
return status;
}
![]() |
![]() |