Panzerkettentutorial für C4D 8



Hier nun mein erstes Tutorial. Ich hoffe es ist nicht allzu konfus geworden :-)

Es soll mit einigen COFFEE-Expressions eine halbwegs realitätsnahe Bewegung einer Gleiskette erzeugt werden.
Prinzipiell sollte es auch mit den Versionen 6 und 7 funktionieren. Da sich COFFEE seit dieser Zeit nicht mehr weiterentwickelt hat. Ausporbiert hab ich es aber nicht.

Zuvor ein kleiner Exkurs über Gleisketten.
Grundsätzlich gibt es zwei Arten von Gleisketten.

Kettenarten

Die Linke heißt Double Pin. Das Kettenglied hat zwei Achsen die über ein eigenes Verbindungsglied miteinander verbunden werden.
Es wird fast ausschließlich bei schweren Panzern verwendet.

Die Rechte heißt Single Pin. Das Kettenglied ist direkt über eine Achse mit den Nachbarkettengliedern verbunden.
Diese Art findet sich meißt bei den leichten Panzern und bei Baufahrzeugen.
Beim Single-Pin muß die Achse nicht unbedingt auf der Ebene der Lauffläche sein. Oft liegt sie weiter innen.

In diesem Tutorial wird ein Kettenlaufwerk mit Double-Pin Kettengliedern behandelt.

Grundobjekte Zuerst brauchen wir einige Objekte die so ein Laufwerk ausmachen.
Das Objekt mit dem Namen Guide wird benötigt um später die Kette zu bewegen. Da wir nur die Rotation benötigen, ist es unsichtbar.
KettenpfadR ist das Spline auf dem dann die Kettenglieder bewegt werden.
Die diversen Lauf-, Umlenk- und Stützrollen und schließlich das Zahnrad.

Bei einer Double-Pin Kette ist es so auszuführen, daß zwischen die Zähne das Verbindungsglied paßt und der Zahn selbst genauso breit ist wie der Zwischenraum den jeweils zwei der Verbindungsglieder freilassen.
Alle Rollen und Räder drehen sich um ihre Z-Achse.

Als nächstes wird das Bezier-Spline für die Kette erzeugt.

Spline

Das Spline muß so gelegt werden daß der Abstand zu den diversen Rollen genau so groß ist wie der Abstand Ketteninnenseite zu Mitte Verbindungsachse.
Die beiden Punkte in der Mitte sind notwendig um die exakte Aufteilung der Kettenglieder sicherzustellen. Bei langen Splinestücken ohne Stützpunkte oder wenn Tangenten sehr kurz geraten sind, scheint die Berechnung der Splines nicht ganz astrein zu sein. Daher diese zusätzlichen Punkte.
Der Anfang des Splines sollte beim Zahnrad liegen. Es macht die Positionierung etws leichter.
Dann wird dem Spline ein COFFEE-Tag zugewiesen in das der nachfolgende Text kopiert wird:

 
main(doc,weg) { weg->InitLength(0); var guide=doc->FindObject("Guide"); var name; var len=weg->GetLength(); var off_verb=11.8/len; // Länge Verbinder var off_kett=12.0/len; // Länge Kettenglied var kette=weg->GetDown(); var anz=0; do { anz++; kette=kette->GetNext(); } while (kette); kette=weg->GetDown(); var off_verb2=off_verb/(off_verb+off_kett)/(anz/2); var off_kett2=off_kett/(off_verb+off_kett)/(anz/2); var rot=guide->GetRotation(); var offs=Modulo(rot.z,2*PI)/(2*PI); var offs2=0; var pos,pos2,richt,m_kette; do { pos=weg->GetSplinePoint(weg->UniformToNatural(Modulo(offs,1)),0); kette->SetPosition(pos); name=kette->GetName(); if (strcmp(name,"Kette")) { offs2=offs+off_verb; //Verbinder offs+=off_verb2; } else { offs2=offs+off_kett; // Kette offs+=off_kett2; } pos2=pos-weg->GetSplinePoint(weg->UniformToNatural(Modulo(offs2,1)),0); pos2=vnorm(pos2); m_kette=kette->GetMl(); richt=vnorm(vcross(vector(1,0,0),pos2)); m_kette->SetV2(pos2); m_kette->SetV3(richt); kette->SetMl(m_kette); kette->Message(MSG_UPDATE); kette=kette->GetNext(); } while (kette); weg->FreeLength(); }

Die erste Markierung ist der Name des Objektes dessen Rotation wir für die Bewegung der Kette benötigen.
Wenn dieses Objekt einmal um 360 Grad gedreht wurde, dann hat auch jedes Kettenglied einen vollen Umlauf abgeschlossen.
Die nächsten Beiden definieren die Abstände der Achsen bei den Kettengliedern, bzw. bei den Verbindungsgliedern.
Die Letzte definiert den Namen eines Kettengliedes.
Das Kettenglied muß so heißen. Alles andere wird als Verbindungsglied interpretiert.
Wenn man also nur Kettenglieder verwendet, ergibt sich automatisch eine Single-Pin Kette. Wobei man dann allerdings die beiden Abstandswerte gleichsetzen muß.

Ausrichtung
Hier noch einmal die Ausrichtung aller beteiligten Bauteile. Die Einhaltung ist wichtig, weil sich sonst die Kettenglieder einer interessanten Verformung unterziehen.

Kettengliederanordnung

Die Beiden Teile eines Kettengliedes legt man dann unter das Spline.
Das Erste Objekt das die Expression unter dem Spline findet, wird auf den Anfang des Splines gelegt. Alle nachfolgenden werden mit gleichen Abständen auf dem Spline verteilt. Bei Zwei ist der Verbinder dann irgendwo weit links.
Die Ausrichtung erfolgt so, daß der Usprung des Objektes genau auf dem Spline liegt. Der Punkt der durch den Abstand in der Espression definiert wird, wird ebenfalls genau auf das Spline gelegt. Es gibt dabei eine kleine mathematische Ungenauigkeit. Aber solange der kleinste Radius des Splines größer als 3-4 Kettengliederbreiten ist, ist der Fehler zu vernachlässigen.
Das Päärchen wird jetzt so oft kopiert bis sich die Kette beim Anfang wieder schließt. Das können sehr viele werden. Bei dieser Kette sind es 178. Das Ganze ist also nicht unbedingt für Massenszenen geeignet.
Wenn man jetzt das Guide-Objekt um seine Z-Achse dreht, dann bewegt sich die Kette schon um das Spline herum.

Die gleichmäßige Aufteilung ist günstiger, weil bei einer Animation der Kette (für Bremsen, Beschleunigen oder ähnliches) die Splinelänge möglichst gleich gehalten werden muß. Da das aber nicht immer geht, ist die gleichmäße Anordung für Fehler noch am tolerantesten, weil der Fehlbetrag auf alle Kettenglieder aufgeteilt wird, und daher nicht auffällt.

Es gibt von dieser Expression noch eine Variante die die Kettenglieder unmittelbar aneinanderhängt (funktioniert dann wie ein Zug, wofür man es auch verwenden kann). Bei Längenänderungen klafft dann eine Lücke zwischen dem ersten und letzten Kettenglied auf.

"Zugvariante"
 
main(doc,weg) { weg->InitLength(0); var guide=doc->FindObject("Guide"); var name; var len=weg->GetLength(); var off_verb=11.8/len; // Länge Verbinder var off_kett=12.0/len; // Länge Kettenglied var kette=weg->GetDown(); var rot=guide->GetRotation(); var offs=Modulo(rot.z,2*PI)/(2*PI); var pos,pos2,richt,m_kette; do { pos=weg->GetSplinePoint(weg->UniformToNatural(Modulo(offs,1)),0); kette->SetPosition(pos); name=kette->GetName(); if (strcmp(name,"Kette")) offs+=off_verb; //Verbinder else offs+=off_kett; // Kette pos2=pos-weg->GetSplinePoint(weg->UniformToNatural(Modulo(offs,1)),0); pos2=vnorm(pos2); m_kette=kette->GetMl(); richt=vnorm(vcross(vector(1,0,0),pos2)); m_kette->SetV2(pos2); m_kette->SetV3(richt); kette->SetMl(m_kette); kette->Message(MSG_UPDATE); kette=kette->GetNext(); } while (kette); weg->FreeLength(); }

So sieht dann die geschlossene Kette aus.

fertige Kette

Wenn es nicht schon paßt, wird das Zahnrad ausgerichtet bis die Zähne richtig liegen, und dann das Koordinatensystem so ausgerichtet wie weiter oben gezeigt.


Als Letztes werden noch allen Rädern und Rollen die notwendigen Expressions zugewiesen damit die sich richtig mit der Kette mitdrehen.

Die hier kommt zum Zahnrad:

 
main(doc,op) { var guide=doc->FindObject("Guide"); var rot=guide->GetRotation(); var zahn=11; // Anzahl Zähne var pfad=doc->FindObject("KettenpfadR"); //Name des Kettensplines var glieder=0; var kette=pfad->GetDown(); do { glieder++; kette=kette->GetNext(); } while (kette); glieder /= 2; var offs=(2*PI)/glieder; var rad=(Modulo((rot.z/offs/zahn),1))*2*PI; var rrot=op->GetRotation(); rrot.z=rad; op->SetRotation(rrot); op->Message(MSG_UPDATE); }

Die erste Markierung ist wieder der Name des Objektes das die Rotation vorgibt.
Die Zweite gibt an Wieviele Zähne es hat.
Und die Letzte schließlich wie das Spline heißt auf dem sich die Kette bewegt.

Die hier kommt an alle anderen Rollen:

 
main(doc,op) { var weg=doc->FindObject("KettenpfadR"); //Name des Kettensplines weg->InitLength(0); var guide=doc->FindObject("Guide"); var rot=guide->GetRotation(); var umf=52.07*2*PI; // Umfang Rad var pfad_l=weg->GetLength(); var offs=umf/pfad_l*2*PI; var rad=(Modulo((rot.z/offs),1))*2*PI; var rrot=op->GetRotation(); rrot.z=rad; op->SetRotation(rrot); op->Message(MSG_UPDATE); weg->FreeLength(); }

Hier ist die erste Markierung wieder der Pfad für die Kette.
Die Zweite ist wieder das Guide-Objekt.
Die Letzte gibt den Abstand zwischen Achse und Spline an. Dieser Wert muß für jede der Rollen entsprechend angepaßt werden.

   

Und hier das Ergebnis.
Das Endergebnis

Und hier ein kleines Filmchen was man damit alles machen kann ;-)

© 2003, Kommentare bitte an: Markus Brenner