Forum: Mikrocontroller und Digitale Elektronik Gesucht: 3D Rendering Routinen in C


von Sean G. (atmega318)


Lesenswert?

Hallo
Hat jemand von euch eine Ahnung, woher ich eine 3D Rendering Bibliothek 
bekommen könnte, die folgenden Anforderungen genügt?:
-Rendern von Objekten bestehend aus verbundenen Punkten (Flächen mit 
Texturen sind nicht zwingend nötig, ein "Stabgerüst" würde reichen!)
-Geschrieben in C, C++ wäre auch ok aber C ist mir lieber
-Opensource (nur zum Basteln, nix mit kommerziell)
-Schön wäre, wenn es nicht hochoptimiert ist, sondern so geschrieben 
dass es nachvollziehbar ist.
-Muss weder schnell noch schlank sein, ich habe einen STM32F4, und das 
LCD hat nur 64*96 Pixel, S/W ohne Graustufen...
Vielen Dank, Sean

PS: Falls es so etwas nicht gibt, immer nur her mit jeglichen Tutorials 
oder Ansätzen, die helfen könnten das selbst zu programmieren.

von Axel J. (axeljaeger)


Lesenswert?


von Sean G. (atmega318)


Lesenswert?

Axel Jäger schrieb:
> Sowas zum Beispiel:
> 
http://blogs.msdn.com/b/davrous/archive/2013/06/13/tutorial-series-learning-how-to-write-a-3d-soft-engine-from-scratch-in-c-typescript-or-javascript.aspx
>
> Stichwort: 3D Software Rendering.

Danke, eigentlich sieht das ja super aus, wenn nur das eine Problem 
nicht wäre: Da wird SharpDX verwendet, und mir ist nicht ganz klar WAS 
das SharpDX alles macht? Weil wenn es nur Punkte und Linien zeichnen 
wäre wäre es ja ok, aber es ist ja eben mehr. Gibt es da eine schnelle 
Lösung, oder muss ich halt einfach jede Funktion anschauen und 
Portieren?

von Sean G. (atmega318)


Lesenswert?

@Axel Jäger (axeljaeger)
Ich habe mir das jetzt mal genauer angeschaut, und denke, dass ich das 
grundsätzlich auch implementieren könnte. Mein Problem ist aber der 
letzte Schritt (die Matrix um die Perspektive, Öffnungswinkel der Kamera 
und Ausrichtung selbiger anzuwenden). Die wird nämlich bei allem was ich 
finden konnte, auch in den Tutorials immer mittels einer Lib berechnet, 
welche nicht für uC gemacht ist. Selber schreiben sollte ja eigentlich 
gehen, aber ich finde nirgends eine "Formel" um das zu berechnen.
Weiss da jemand mehr?
LG, Sean

von U8glib (Gast)


Lesenswert?

Wenn Du mit "Formel" die 3D nach 2D Projektion meinst, das ist ein 
einfacher Dreisatz:

x_bildschirm = x_3d * entfernung_auge_bildschirm / z_3d

Entsprechend gilt die Berechnung für y. Mit Festkomma-Arithmetik auf dem 
Microcontroller muss man etwas shiften. Erfahrungsgemäß benötigt man 
mindestens 16 Bit Genauigkeit.

Siehe auch hier:
http://www.arcsynthesis.org/gltut/Positioning/Tut04%20Perspective%20Projection.html

Oliver

von Дуссель дук (Gast)


Lesenswert?

Mit einem controller ? Entweder sind die zu rechnenden Formen trivial, 
oder der controller hat einiges an dampf

von Sean G. (atmega318)


Lesenswert?

Дуссель дук schrieb:
> Mit einem controller ? Entweder sind die zu rechnenden Formen trivial,
> oder der controller hat einiges an dampf

Ja hat schon ordentlich Dampf, ist ein STM32F4 mit 168MHz, 32 Bit.

von Lukey S. (lukey3332)


Lesenswert?

Da gabs mal ne wolfenstein 3d Demo fuer Die r0ket. Weis grad net wie 
viel "Dampf" die hat, aber hier sind die 
sourcen:https://github.com/gasman/wolfy

von David .. (volatile)


Lesenswert?

Lukas Straub schrieb:
> Da gabs mal ne wolfenstein 3d Demo fuer Die r0ket. Weis grad net wie
> viel "Dampf" die hat, aber hier sind die
> sourcen:https://github.com/gasman/wolfy

Nicht schlecht! Erinnert mich an meine Star Wars: Dark Forces Zeit als 
Schueler damals mit dem anschliessenden Versuch, die Levels automatisch 
in 3DS max zu parsen und zu bauen... (Starb aus Zeitgruenden, aber 
funktionierte)

von Sean G. (atmega318)


Angehängte Dateien:

Lesenswert?

Lukas Straub schrieb:
> Da gabs mal ne wolfenstein 3d Demo fuer Die r0ket. Weis grad net wie
> viel "Dampf" die hat, aber hier sind die
> sourcen:https://github.com/gasman/wolfy

Das ist aber leider eine Raycasting-Engine, nicht was ich suche (kann 
kein "echtes 3D")

Ich habe jetzt aber mal ein kleines Programm geschrieben, welches einen 
Würfel rotieren lässt. Rendering funktioniert soweit gut, aber der 
Würfel wird beim Drehen plattgedrückt :(
Ich mache das folgendermassen: Jedes Frame rufe ich folgendes auf:
1
 
2
    vector3.z=500;
3
4
    translate(&vertice1, vector3);
5
    translate(&vertice2, vector3);
6
    translate(&vertice3, vector3);
7
    translate(&vertice4, vector3);
8
    translate(&vertice5, vector3);
9
    translate(&vertice6, vector3);
10
    translate(&vertice7, vector3);
11
    translate(&vertice8, vector3);
12
13
    rotate_y(&vertice1, angle);
14
    rotate_y(&vertice2, angle);
15
    rotate_y(&vertice3, angle);
16
    rotate_y(&vertice4, angle);
17
    rotate_y(&vertice5, angle);
18
    rotate_y(&vertice6, angle);
19
    rotate_y(&vertice7, angle);
20
    rotate_y(&vertice8, angle);
21
    
22
    rotate_x(&vertice1, angle);
23
    rotate_x(&vertice2, angle);
24
    rotate_x(&vertice3, angle);
25
    rotate_x(&vertice4, angle);
26
    rotate_x(&vertice5, angle);
27
    rotate_x(&vertice6, angle);
28
    rotate_x(&vertice7, angle);
29
    rotate_x(&vertice8, angle);
30
    
31
  
32
    vector3.z=-500;
33
34
    translate(&vertice1, vector3);
35
    translate(&vertice2, vector3);
36
    translate(&vertice3, vector3);
37
    translate(&vertice4, vector3);
38
    translate(&vertice5, vector3);
39
    translate(&vertice6, vector3);
40
    translate(&vertice7, vector3);
41
    translate(&vertice8, vector3);
Ausgangsposition ist, dass der Mittelpunkt des Würfels sich auf 0,0,-500 
befindet. Er wird dann auf den Nullpunkt geschoben, rotiert und 
zurückbewegt. Rotieren mache ich folgendermassen:
1
void rotate_x(vertice *vertice_ptr, int angle)
2
{
3
  float sinangle = 0.0174524;
4
  float cosangle = 0.9998477;
5
  vertice_ptr -> y = cosangle * (vertice_ptr -> y) - sinangle * (vertice_ptr -> z);
6
  vertice_ptr -> z = cosangle * (vertice_ptr -> z) + sinangle * (vertice_ptr -> y);
7
8
}
9
void rotate_y(vertice *vertice_ptr, int angle)
10
{
11
  float sinangle = 0.05547298;
12
  float cosangle = 0.99846019;
13
  vertice_ptr -> x = cosangle * (vertice_ptr -> x) + sinangle * (vertice_ptr -> z);
14
  vertice_ptr -> z = cosangle * (vertice_ptr -> z) - sinangle * (vertice_ptr -> x);
15
16
}
Also noch keine Matritzen, und Sinus/Kosinus als Konstanten. Alle 
Koordinaten sind Floats.

Auf dem Video sieht man was mit dem Würfel passiert, sorry für die 
schlechte Qualität, aber das LCD lässt sich nicht gerne filmen. Ich kann 
sonst schon noch den ganzen Code anhängen, aber eigentlich muss es an 
dem Teil bzw. einem grundlegenden Denkfehler liegen. Der Rest des Codes 
ist vermutlich nur verwirrend (schön ist der nicht...)

Danke für eure Hilfe, Sean

von Sean G. (atmega318)


Lesenswert?

Hat sich erledigt! Hier noch die Lösung, falls jemand ein ähnliches 
Problem hat:
Wenn man das so berechnet, wird "vertice_ptr -> y" bearbeitet, bevor es 
im 2. Befehl verwendet wird. Dadurch entsteht ein riesiger Fehler!
1
void rotate_x(vertice *vertice_ptr, int angle)
2
{
3
  float sinangle = 0.0174524;
4
  float cosangle = 0.9998477;
5
  vertice_ptr -> y = cosangle * (vertice_ptr -> y) - sinangle * (vertice_ptr -> z);
6
  vertice_ptr -> z = cosangle * (vertice_ptr -> z) + sinangle * (vertice_ptr -> y);
7
}
Richtig wäre es so:
1
void rotate_x(vertice *vertice_ptr, int angle)
2
{
3
  float sinangle = 0.0174524;
4
  float cosangle = 0.9998477;
5
  float y = cosangle * (vertice_ptr -> y) - sinangle * (vertice_ptr -> z);
6
  vertice_ptr -> z = cosangle * (vertice_ptr -> z) + sinangle * (vertice_ptr -> y);
7
  vertice_ptr -> y = y;
8
}
In dem fall bleibt "vertice_ptr -> y" unverändert bis am Schluss.
Wenn man es richtig macht, also mit Matrizen dann erübrigt sich das eh.
Trotzdem Danke, Sean

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.