guzikk Napisano 5 Listopad 2010 Napisano 5 Listopad 2010 Przy orient constrain circle i bone, bone obraca się o -180, 180, -180. O co chodzi? Nie mam pojęcia skąd się to bierze tym bardziej że przy prawym odpowiedniku owej kości tego problemu nie było. Może to kwestia złego mirrora?
Kroopson Napisano 5 Listopad 2010 Napisano 5 Listopad 2010 prawdopodobnie jest to kwestia tego że bone i circle mają całkowicie różne przestrzeni transformacji. Jak jeszcze rigowałem swego czasu w Maya to obchodziłem to w ten sposób że kontrolery dla kości przygotowywałem tak że najpierw tworzyłem transform node (albo group się to nazywało), kopiowałem mu macierz kości po czym linkowałem atrybuty (ma to swoją taką zaletę że nie używa się orient constraint, który jest znacznie bardziej zasobożerny niż connectAttr. Generalnie popatrz sobie jak wyglądają lokalne osie obiektów.
guzikk Napisano 5 Listopad 2010 Autor Napisano 5 Listopad 2010 tylko dlaczego w po jednej stronie osi globalnej wszystko działa a po drugiej już nie. Nie jest coś spaprane z mirror jointem?
Kroopson Napisano 8 Listopad 2010 Napisano 8 Listopad 2010 Nie jest nic spaprane. Jeśli faktycznie poważnie myślisz o robieniu rigów to niestety nie ominie cię nauka matematyki która odpowiada za przekształcenia przestrzeni.
asblaze Napisano 8 Listopad 2010 Napisano 8 Listopad 2010 pewnie mirrorowałeś kości z zaznaczonym Behavior a nie Orientation. I niestety pewnie tak musisz zrobić. Jeśli bardzo CI to przeszkadza, to: 1. zgrupuj obiekt który ma orientConstraint, 2. wyrównaj pivoty grup 3. obróć grupę o właściwe wartości tak, żeby kanały z orientem się wyzerowały
guzikk Napisano 8 Listopad 2010 Autor Napisano 8 Listopad 2010 Tu jednak chodzi chyba faktycznie o to na co wskazuje Kroopson. Zrobiłem parę doświadczeń i faktycznie wyszło że to nie zależy od mirrora tylko od fragmentu przestrzeni na której działam. a zatem Kroopson móglbyś konkretniej wyjaśnić co masz na myśli?
ca mel Napisano 8 Listopad 2010 Napisano 8 Listopad 2010 Ja bym tu sprobowal wyrownac kolejnosc rotacji wszystkich jointow po jednej stronie i odwrocic po drugiej (opcją orient joints). A jesli nie pomoze to moze wstaw sobie dodatkowy locator miedzy kosciami odwracajacy transformacje. Pozdr.
Kroopson Napisano 9 Listopad 2010 Napisano 9 Listopad 2010 if(`window -exists "addFKControl"`) deleteUI "addFKControl"; if(`windowPref -exists "addFKControl") windowPref -r "addFKControl"; // Prepare the UI window -rtf true -title "Add FK Controller" addFKControl; columnLayout -rowSpacing 5 addFKControlColumn1; intSliderGrp -label "Number of sides" -field true -minValue 3 -maxValue 32 -value 4 FKnumber; intSliderGrp -label "Height divisions" -field true -minValue 1 -maxValue 32 -value 1 FKheight; floatSliderGrp -label "Radius" -field true -minValue .0001 -maxValue 2 -value 1 FKradius; text -label "Controller Orientation"; separator -ann "Controller Orientation" -w 250; radioCollection addFKRadioGrp1; rowLayout -numberOfColumns 3 addFKControlRow1; radioButton -label "+X" posX; radioButton -label "+Y" posY; radioButton -label "+Z" posZ; setParent ..; rowLayout -numberOfColumns 3 addFKControlRow2; radioButton -label "-X" negX; radioButton -label "-Y" negY; radioButton -label "-Z" negZ; setParent ..; separator -w 250; button -c "addFKControlPrep" -label "Create"; setParent ..; showWindow addFKControl; radioCollection -e -sl posX addFKRadioGrp1; // Preparation phase global proc addFKControlPrep(){ $sel = `ls -sl`; string $a; float $length; // See if we have anything selected if (size($sel) == 0){ error "Select a target"; } // Recurence trough selection for($a in $sel){ $child = `listRelatives -c $a`; if (size($child) > 0 && nodeType($child[0]) == "joint"){ // If the target is a joint calculate the length float $componentX = `getAttr ($child[0] + ".tx")`; float $componentY = `getAttr ($child[0] + ".ty")`; float $componentZ = `getAttr ($child[0] + ".tz")`; $length = `mag (>)`; } else { // If not - set length to 1 $length = 1; } int $nGon = `intSliderGrp -q -value "FKnumber"`; // Read values int $height = `intSliderGrp -q -value "FKheight"`; float $rad = `floatSliderGrp -q -value "FKradius"`; string $orient = `radioCollection -q -sl addFKRadioGrp1`; addFKControl( $nGon, $height, $length, $rad, $a, $orient); // Make the main function } } global proc string addFKControl ( int $nGon, int $height, float $len , float $radius, string $targetName, string $orient) { string $name = $targetName + "_FK_control"; float $vertCoords[] = {}; string $command = "curve -d 1 "; float $step = 360/$nGon; float $angle = 0 - ($step/2); string $endcommand = " "; for ($a = 0; $a $angle +=$step; float $resultX = (`cos (deg_to_rad($angle))`) * $radius; float $resultY = (`sin (deg_to_rad($angle))`) * $radius; $vertCoords[($a*2)] = $resultX; $vertCoords[($a*2) + 1] = $resultY; } $vertCoords[$nGon*2] = $vertCoords[0]; $vertCoords[($nGon*2)+1] = $vertCoords[1]; for ($n = 0; $n float $div = 1.0; float $flHeight = ($height/$len) * 1.0; int $count = 0; for ($a = 0; $a float $div = `floor($n/$nGon)`; $command += "-p " + $vertCoords[($a*2)] + " " + ($n/$flHeight) + " " + $vertCoords[($a*2) + 1] + " "; $command += "-p " + $vertCoords[(($a+1)*2)] + " " + ($n/$flHeight) + " " + $vertCoords[(($a+1)*2) + 1] + " "; $command += "-p " + $vertCoords[(($a+1)*2)] + " " + (($n+1)/$flHeight) + " " + $vertCoords[(($a+1)*2) + 1] + " "; $command += "-p " + $vertCoords[($a*2)] + " " + (($n+1)/$flHeight) + " " + $vertCoords[($a*2) + 1] + " "; $command += "-p " + $vertCoords[($a*2)] + " " + ($n/$flHeight) + " " + $vertCoords[($a*2) + 1] + " "; $count = $a; } $command += "-p " + $vertCoords[($count*2)] + " " + (($n + 1)/$flHeight) + " " + $vertCoords[($count*2) + 1] + " "; } $command += $endcommand; $command += " -n "; $command += $name; $curveNode = `eval ($command)`; $curveNodeShape = `listRelatives -c $curveNode`; rename $curveNodeShape ($curveNode + "Shape"); if ($orient == "posX"){ setAttr ($curveNode + ".rotateZ") -90; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } if ($orient == "negX"){ setAttr ($curveNode + ".rotateZ") 90; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } if ($orient == "negY"){ setAttr ($curveNode + ".rotateZ") 180; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } if ($orient == "posZ"){ setAttr ($curveNode + ".rotateX") 90; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } if ($orient == "negZ"){ setAttr ($curveNode + ".rotateZ") -90; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } $controlOrient = `group -e 1 -n ($targetName + "_FK_control_orient")`; setAttr ($controlOrient[0] + ".localScaleX") ($radius / 10); setAttr ($controlOrient[0] + ".localScaleY") ($radius / 10); setAttr ($controlOrient[0] + ".localScaleZ") ($radius / 10); parent $curveNode $controlOrient; copyMatrixAddFK ($targetName, $controlOrient[0], 1); // Set proper rotation order. setAttr ($curveNode + ".rotateOrder") (`getAttr ($targetName + ".rotateOrder")`); return $curveNode; } global proc copyMatrixAddFK( string $sourceObj, string $targetObj, int $worldSpace){ string $command; float $sourceMatrix[]; if($worldSpace == 1){ $sourceMatrix = `xform -q -ws -m $sourceObj`; $command = "xform -ws -m "; } else { $sourceMatrix = `xform -q -os -m $sourceObj`; $command = "xform -os -m "; } string $matrix; string $a; for($a in $sourceMatrix){ $matrix += $a; $matrix += " "; } $command += $matrix; $command += $targetObj; eval($command); } Spróbuj sobie użyć tego skryptu. Może będzie działał, nie używałem go niestety od bardzo dawna więc nie ręczę za wyniki. Po zaznaczeniu jointa i odpaleniu tego cuda powinno ci się okienko otworzyć z możliwością stworzenia kontrolera do FK :)
Kroopson Napisano 9 Listopad 2010 Napisano 9 Listopad 2010 A jeszcze parę słów na temat tego dlaczego w maya tak się dzieje jak się dzieje. Otóż jointy w Maya mają 2 macierze - jedną zwykłą macierz transformacji oraz drugą - która często się nazywa "joint orient ", i jest ona swego rodzaju pre-transformem, ustawiającym jointa tak, żeby np jego oś X wskazywała na jointy potomne (taką operację dokonuje właśnie funkcja orient joint). Dlatego własnie mówiłem o innej przestrzeni transformacji dla jointów, innej dla kontrolera. Kiedy aplikujesz orient constraint to ten node (orient constraint) operuje w przestrzeni world space - kopiuje macierz rotacji z obiektu znajdującego się w world space do obiektu znajdującego się w zupełnie innej przestrzeni transformacji. Jeśli masz włączoną opcję "maintaint offset" (mogę nie pamiętać dokładnej nazwy) to Maya będzie musiała skompensować rotację targetu dla constraina przez co ustawia jakąś wartość rotacji na nim (np. 180, 180, 0 itp.). Spróbuj sobie nałożyć orient constraint z wyłączoną opcją maintaint offset, mając włączone wyświetlanie osi na joincie i na obiekcie kontrolującym jointa - zobacz jak się zachowają. Jeśli chcemy sobie zrobić kontrolki niezależne od jointów (które mogłyby służyć np do kontroli FK) to musimy sobie odtworzyć ten pretransfowm dodając transform node'a będącego rodzicem naszego wymarzonego fk kontrolera. Oczywiście nie jest to jedyna metoda rozwiązania tego problemu ale napewno jest skuteczna. W sumie może wystarczyłoby skopiować transformację jointa i zafreezować transformację na kontrolerze - może to by podziałało. 1
guzikk Napisano 9 Listopad 2010 Autor Napisano 9 Listopad 2010 Co do skryptu: wyrzuca mi syntax error. Mój ulubiony error z czasów pisania w C ;P. I szukaj tu teraz błędu składni. To ja już wolę Jave ;] Przejżę ten kod i jak znajdę przyczynę erroru to dam znać. Serdeczne dzięki za wyjaśnienie problemu - zdecydowanie przyda mi się ta wiedza. Poświęcę jej niebawem więcej uwagi by dokładnie przeanalizować i zrozumieć zagadnienie interakcji constrainta na obiekt constraintowany na tyle dobrze by umieć wytłumaczyć komuś innemu.
guzikk Napisano 9 Listopad 2010 Autor Napisano 9 Listopad 2010 (edytowane) dobra, znalazłem błąd. w 4 linii kodu if(`windowPref -exists "addFKControl") brakowało gravisa przed nawiasem zamykającym if(`windowPref -exists "addFKControl"`) EDIT oho, widzę tu więcej błędów. Prawdopodobnie przez to że zmieniły się flagi metod. Postaram się to poprawić i przesłać wersję działającą na aktualnym oprogramowaniu. Edytowane 9 Listopad 2010 przez guzikk
guzikk Napisano 9 Listopad 2010 Autor Napisano 9 Listopad 2010 Oto działający kod: if(`window -exists "addFKControl"`) deleteUI "addFKControl"; if(`windowPref -exists "addFKControl"`) windowPref -r "addFKControl"; window -rtf true -title "Add FK Controller" addFKControl; columnLayout -rowSpacing 5 addFKControlColumn1; intSliderGrp -label "Number of sides" -field true -minValue 3 -maxValue 32 -value 4 FKnumber; intSliderGrp -label "Height divisions" -field true -minValue 1 -maxValue 32 -value 1 FKheight; floatSliderGrp -label "Radius" -field true -minValue .0001 -maxValue 2 -value 1 FKradius; text -label "Controller Orientation"; separator -ann "Controller Orientation" -w 250; radioCollection addFKRadioGrp1; rowLayout -numberOfColumns 3 addFKControlRow1; radioButton -label "+X" posX; radioButton -label "+Y" posY; radioButton -label "+Z" posZ; setParent ..; rowLayout -numberOfColumns 3 addFKControlRow2; radioButton -label "-X" negX; radioButton -label "-Y" negY; radioButton -label "-Z" negZ; setParent ..; separator -w 250; button -c "addFKControlPrep" -label "Create"; setParent ..; showWindow addFKControl; radioCollection -e -sl posX addFKRadioGrp1; // Preparation phase global proc addFKControlPrep(){ $sel = `ls -sl`; string $a; float $length; // See if we have anything selected if (size($sel) == 0){ error "Select a target"; } // Recurence trough selection for($a in $sel){ $child = `listRelatives -c $a`; if (size($child) > 0 && nodeType($child[0]) == "joint"){ // If the target is a joint calculate the length float $componentX = `getAttr ($child[0] + ".tx")`; float $componentY = `getAttr ($child[0] + ".ty")`; float $componentZ = `getAttr ($child[0] + ".tz")`; $length = `mag (>)`; } else { // If not - set length to 1 $length = 1; } int $nGon = `intSliderGrp -q -value "FKnumber"`; // Read values int $height = `intSliderGrp -q -value "FKheight"`; float $rad = `floatSliderGrp -q -value "FKradius"`; string $orient = `radioCollection -q -sl addFKRadioGrp1`; addFKControl( $nGon, $height, $length, $rad, $a, $orient); // Make the main function } } global proc string addFKControl ( int $nGon, int $height, float $len , float $radius, string $targetName, string $orient) { string $name = $targetName + "_FK_control"; float $vertCoords[] = {}; string $command = "curve -d 1 "; float $step = 360/$nGon; float $angle = 0 - ($step/2); string $endcommand = " "; for ($a = 0; $a $angle +=$step; float $resultX = (`cos (deg_to_rad($angle))`) * $radius; float $resultY = (`sin (deg_to_rad($angle))`) * $radius; $vertCoords[($a*2)] = $resultX; $vertCoords[($a*2) + 1] = $resultY; } $vertCoords[$nGon*2] = $vertCoords[0]; $vertCoords[($nGon*2)+1] = $vertCoords[1]; for ($n = 0; $n float $div = 1.0; float $flHeight = ($height/$len) * 1.0; int $count = 0; for ($a = 0; $a float $div = `floor($n/$nGon)`; $command += "-p " + $vertCoords[($a*2)] + " " + ($n/$flHeight) + " " + $vertCoords[($a*2) + 1] + " "; $command += "-p " + $vertCoords[(($a+1)*2)] + " " + ($n/$flHeight) + " " + $vertCoords[(($a+1)*2) + 1] + " "; $command += "-p " + $vertCoords[(($a+1)*2)] + " " + (($n+1)/$flHeight) + " " + $vertCoords[(($a+1)*2) + 1] + " "; $command += "-p " + $vertCoords[($a*2)] + " " + (($n+1)/$flHeight) + " " + $vertCoords[($a*2) + 1] + " "; $command += "-p " + $vertCoords[($a*2)] + " " + ($n/$flHeight) + " " + $vertCoords[($a*2) + 1] + " "; $count = $a; } $command += "-p " + $vertCoords[($count*2)] + " " + (($n + 1)/$flHeight) + " " + $vertCoords[($count*2) + 1] + " "; } $command += $endcommand; $command += " -n "; $command += $name; $curveNode = `eval ($command)`; $curveNodeShape = `listRelatives -c $curveNode`; rename $curveNodeShape ($curveNode + "Shape"); if ($orient == "posX"){ setAttr ($curveNode + ".rotateZ") -90; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } if ($orient == "negX"){ setAttr ($curveNode + ".rotateZ") 90; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } if ($orient == "negY"){ setAttr ($curveNode + ".rotateZ") 180; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } if ($orient == "posZ"){ setAttr ($curveNode + ".rotateX") 90; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } if ($orient == "negZ"){ setAttr ($curveNode + ".rotateZ") -90; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $curveNode; } $controlOrient = `group -em -n ($targetName + "_FK_control_orient")`; setAttr ($controlOrient + ".scalePivotX") ($radius / 10); setAttr ($controlOrient + ".scalePivotY") ($radius / 10); setAttr ($controlOrient + ".scalePivotZ") ($radius / 10); parent $curveNode $controlOrient; copyMatrixAddFK ($targetName, $controlOrient, 1); // Set proper rotation order. setAttr ($curveNode + ".rotateOrder") (`getAttr ($targetName + ".rotateOrder")`); return $curveNode; } global proc copyMatrixAddFK( string $sourceObj, string $targetObj, int $worldSpace){ string $command; float $sourceMatrix[]; if($worldSpace == 1){ $sourceMatrix = `xform -q -ws -m $sourceObj`; $command = "xform -ws -m "; } else { $sourceMatrix = `xform -q -os -m $sourceObj`; $command = "xform -os -m "; } string $matrix; string $a; for($a in $sourceMatrix){ $matrix += $a; $matrix += " "; } $command += $matrix; $command += $targetObj; eval($command); }; Wszystko pięknie bangla. Istny miodek. Big Thx Kroopson za skrypt.
Kroopson Napisano 9 Listopad 2010 Napisano 9 Listopad 2010 (edytowane) No tak - ja to pisałem jeszcze w Maya 7 chyba albo w 2008 czyli jakąś epokę temu. Generalnie jak teraz widzę ten faszystowski kod MEL'a to mnie słabi. Autodesk powinien pomyśleć trochu nad API pythona w majce bo nawet Blender wyprzedza ją pod tym względem o lata świetlne. Np. dziś potrzebowałem skryptu który w stabilny, przewidywalny sposób exportował by dane kamery z XSI do After Effects z zachowaniem pixel aspektu. Jako że nie lubię rozwiązań których nie rozumiem wziąłem sobie skrypt który niedawno powstał do Blendera. Zaadaptowanie go do XSI zajęło jakieś 3h. Z majką już by tak super nie było ponieważ nie ma ona domyślnie w pythonie żadnych operacji macierzowych (natywnych dla maya), i ogólnie sam python nie potrafi dostać się do danych obiektu inaczej niż przez zwrapowanego w nim Mel'a (no chyba że coś się ostatnio w tej materii zmieniło) Edytowane 9 Listopad 2010 przez Kroopson
guzikk Napisano 9 Listopad 2010 Autor Napisano 9 Listopad 2010 z tego co wiem nic się nie zmieniło. Jakiś czas temu podjąłem się próby pisania w pythonie pod mayą i zrezygnowałem po tym jak się okazało że i tak i tak sprowadza się to do operowania na MELu. A - tak jak mówisz - przydałoby się móc pisać w innym języku niż MEL. Wręcz możnaby się pokusić o aplikację typu Eclipse albo NetBeans dla Mayi. To by dopiero było. Wygodniejsze skryptowanie i tworzenie GUI. Ehh...
beny Napisano 10 Listopad 2010 Napisano 10 Listopad 2010 Problem w tym że Maya w 80% polega całkowicie na MELu i przepisanie jej natywnie pod pythona zajmie jeszcze trochę czasu.
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się