3D Objekte mit Seilen rendern

    • Tut- Complete

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • 3D Objekte mit Seilen rendern


      Wie wir alle wissen, ist es extrem schwierig und aufwändig eigene Modelle in Arma zu importieren. Da will man nur eben mal eine Mission bauen und plötzlich fällt einem auf, dass ein Objekt, dass man jetzt unbedingt für die Story bräuchte, etwa ein Raumschiff oder ein Tempotaschentuch, weder im eigenen Modset noch in Vanilla-Arma enthalten ist. Oft hört man dann das Argument, man könne doch einfach createSimpleObject nutzen, doch erfahrene Modder und Missionsbauer wissen, dass die einfachsten und schnellsten Lösungen nicht immer die besten sind. Deswegen habe ich mir heute etwas Zeit genommen, um dieses Problem ein für alle Mal zu beseitigen und ich denke, das ist mir durchaus gelungen.

      Im Folgenden werde ich kurz Schritt für Schritt erklären, wie ich dabei vorgegangen bin. Zunächst müssen wir wissen, das Seile am besten mit Helikopterobjekten funktionieren. Ihr könnt dafür jede beliebige Helikopterklasse nehmen, ich empfehle jedoch "B_UAV_01_F" oder, falls ihr ACE benutzt, "ace_fastroping_helper". Letztere Klasse scheint eine etwas bessere Performance zu bieten.
      Wie wahrscheinlich bereits bekannt bestehen 3D Objekte aus Eckpunkten, sogenannten Vertices, die (meist) zu dritt eine Fläche bilden. Fangen wir also mit den Punkten an, das ist relativ trivial:
      Spoiler anzeigen

      Quellcode

      1. private _fn_renderVertex = {
      2. private _vertex = "ace_fastroping_helper" createVehicle [0, 0, 0];
      3. _vertex hideObject true;
      4. _vertex setPosWorld _this;
      5. _vertex
      6. };


      Erwähnenswert ist vielleicht, dass ich hier setPosWorld nutze. Dies dient schlichtweg der Präzsision, denn setPostWorld orientiert sich am Zentrum des Objektes, also genau der Punkt, an dem nachher die Seile befestigt werden. Als nächstes rendern wir die Kanten mit Seilen:
      Spoiler anzeigen

      Quellcode

      1. private _fn_renderLine = {
      2. params ["_from", "_to"];
      3. private _line = ropeCreate [
      4. _from, [0, 0, 0],
      5. _to, [0, 0, 0],
      6. _from distance _to
      7. ];
      8. _line
      9. };
      Alles anzeigen


      Auch das hier ist zunächst simpel. Überlegt man nun noch einmal, erkennt man jedoch, dass zwei aneinandergrenzende Flächen sich eine Kante teilen, jedoch beim stupiden rendern aller Kanten doppelt gerendert würden. Da Seile etwas performancehungrig sind, sollte man also unbedingt jede Kante nur einmal rendern, dies erreichen wir, in dem wir allen Kanten einen eindeutigen Namen geben (bestehend aus den beiden Endpunkten) und diesen zwischenspeichern:
      Spoiler anzeigen

      Quellcode

      1. private _lineCache = createLocation ["NameVillage", [-1000, -1000, 0], 0, 0];
      2. private _fn_renderLine = {
      3. params ["_from", "_to"];
      4. private _libNameFT = format ["%1_%2", _from, _to];
      5. private _libNameTF = format ["%2_%1", _from, _to];
      6. if (_libNameFT in allVariables _lineCache) exitWith {
      7. _lineCache getVariable _libNameFT
      8. };
      9. if (_libNameTF in allVariables _lineCache) exitWith {
      10. _lineCache getVariable _libNameTF
      11. };
      12. private _line = ropeCreate [
      13. _from, [0, 0, 0],
      14. _to, [0, 0, 0],
      15. _from distance _to
      16. ];
      17. _lineCache setVariable [_libNameFT, _line];
      18. _line
      19. };
      Alles anzeigen


      Nun kommen wir zum finalen Schritt, dem Rendern der Dreicke, was auch nicht schwer ist:
      Spoiler anzeigen

      Quellcode

      1. private _fn_renderTriangle = {
      2. private _vertices = _this apply {
      3. _x call _fn_renderVertex
      4. };
      5. private _lines = [0, 1, 2] apply {
      6. [_vertices#_x, _vertices#((_x + 1) mod 3)] call _fn_renderLine;
      7. };
      8. [_vertices, _lines]
      9. };
      Alles anzeigen


      Jetzt können wir bereits jedes beliebige 3D Objekt rendern, jedoch ist das Eingeben der Koordinaten von Hand doch sehr umständlich. Stattdessen habe ich noch einen kleinen STL-Datei-Parser geschrieben, der beliebige 3D Objekte im STL-ASCII Format lesen kann:
      Spoiler anzeigen

      Quellcode

      1. private _fn_loadSTL = {
      2. params ["_file"];
      3. private _lines = (loadFile _file) splitString endl;
      4. private _triangles = [];
      5. private _currentTriangle = [];
      6. {
      7. private _tokens = _x splitString (" " + toString [9]);
      8. switch (_tokens#0) do {
      9. case "endfacet": {
      10. _triangles pushBack _currentTriangle;
      11. _currentTriangle = [];
      12. };
      13. case "vertex": {
      14. _currentTriangle pushBack ((_tokens select [1, 3]) apply {
      15. parseNumber _x
      16. });
      17. };
      18. }
      19. } forEach _lines;
      20. _triangles
      21. };
      Alles anzeigen


      Hier nun der vollständige Quellcode:


      Und zum Abschluss noch ein paar Beispiele, wie die Ergebnisse aussehen können (Quelle Bär, Quelle Fuchs):


    • echt cool jedoch würde ich anstatt STL Wavefront-OBJ nehmen, das ist auch ein klar text format und auch weit aus häufiger genutzt.
      Spoiler anzeigen

      C-Quellcode: OBJ Parser

      1. private _fn_loadOBJ = {
      2. params ["_file"];
      3. private _lines = (loadFile _file) splitString endl;
      4. private _verts = [];
      5. private _triangles = [];
      6. {
      7. private _tokens = _x splitString (" ");
      8. switch (_tokens select 0) do {
      9. case "v": {
      10. _verts pushback ((_tokens select [1,3]) apply {
      11. parseNumber _x;
      12. });
      13. };
      14. case "f": {
      15. _triangles ((_tokens select [1,3]) apply {
      16. parseNumber _x;
      17. });
      18. };
      19. }
      20. } forEach _lines;
      21. _triangles apply { _x apply { _verts select _x } };
      22. };
      Alles anzeigen

      Sollte so gehen, nicht getested!
      SIGNATUR START
      Wer Rechtschreibfehler findet darf sie behalten
      ACE3 Core Developer
      CBA A3 Developer
      Developer of Dynasound, Enhance SoundScape, Immerse, Suppress and Align
      SIGNATUR ENDE