Autor Beitrag
Andreas95
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 36



BeitragVerfasst: Mi 19.01.11 22:49 
im opengl tutorial: wiki.delphigl.com/in...tion_3#Weltenformeln

Verstehe ich (im kapitel WeltenFormeln) nicht wie man es schafft, die einzelnen objekte (in diesem fall die erde und der Mond) ihre eigenen Rotationsbahnen zu geben. So das der Mond um die Erde Kreist, und die Erde um die sonne (bzw uns, das wir in diesem beispiel von der sonne aus alles beobachten).

Beispiele und erklärungen wären toll :)
danke


Zuletzt bearbeitet von Andreas95 am Fr 21.01.11 16:25, insgesamt 1-mal bearbeitet
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Mi 19.01.11 23:55 
Hey,

stell dir vor die Planeten sind alle in einem Baum:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Sonne
  Erde
    Mond
  Jupiter
    Mond 1
    Mond 2
    Mond 3
  ...

Die Sonne ist der Mittelpunkt (des Universums :) ) also brauchen wir da noch nix zu verschieben sondern können einfach zo zeichnen. Dann nehmen wir uns das 1. Kind der Sonne (im Baum). Das ist die Erde. Zunächste speichert man die Position der Sonne mit glPushMatrix auf dem Stack (Achtung: MatrixMode muss hierbei GL_MODELMATRIX sein). Da sich die Erde um die Sonne drehen soll drehen wir erst unseren Zeichenstift mit glRotatef(x, 0, 1, 0) um die y-Achse und verschieben ihn dann mit glTranslate(r, 0, 0); um den Radius der Umlaufbahn in Richtung pos. X-Achse. Da wir den zeichenstift vorher schon gedreht haben entsteht der Kreis nun von ganz allein. Das selbe machst du mit den Kindern der Erde (dem Mond). Wenn das beendet ist kannst du mit glPopMatrix die Position der Sonne wieder vom Stack laden und dann das nächste Kind der Sonne bearbeiten. Das machst du genauso, wie du es mit der Erde gemacht hast. So ist jedes Kind an die Position des Elternteils geknüpft. Vlt solltest du dir auch mal das Matrix-Tutorial angucken, das is eigentlich die Grundlage zu dem was du vor hast.

MfG Bergmann

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
Andreas95 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 36



BeitragVerfasst: Fr 21.01.11 16:30 
Hm ok des hat mich schon mal sehr weit gebracht :) danke.
aber ich habe das problem das wenn ich zb gltranslatef(0,0,-6); im tform1.render tuhe und dann im timer bzw onidle render; mache, varändert es ja andauernd meine position (wenn ich es richtig verstanden habe, multipliziert es jedes intervall die z coordinate des matrix um 6). also verstehe ich nicht wie ich meine position ändern soll, um die teile zu zeichnen (planeten).

Hast jemand vielleicht ein Beispiel-code den ich anschauen könnte, wo sowas deutlich gezeigt wird? oder eine idee was ich falsch mache?
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Fr 21.01.11 18:13 
Hey,

normalerweiße ist es üblich die Einheitsmatrix vor dem Zeichnen zu laden:
ausblenden Delphi-Quelltext
1:
2:
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;

damit wird der Zeichenstift wieder auf die 0-Position gesetzt. Wenn du das nicht machst, dann rückt er ihn bei jedem aufruf von Render um 6 Einheiten weiter. Zur Übung würde ich das so machen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
  
  glPushMatrix;
    RenderSonne;
    glPushMatrix;
      glRotatef(WinkelErde, 010);
      glTranslate(ErdeRadius, 00);
      RenderErde;
      glPushMatrix;
        glRotatef(WinkelMond, 010);
        glTranslatef(MondRadius, 00);
        RenderMond;
      glPopMatrix;
    glPopMatrix;
  glPopMatrix;

Wenn du allerdings ein richtiges Sonnensystem basteln willst, dann würde ich das ganze in eine Klasse schreiben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
type
  TPlanet = class(TObject)
  private
    fChildren: TObjectList; //speichert andere TPlanet-Objekte, die um diesen Kreisen
    fRadius: Single; //Abstand zum Planeten der umkreist wird
    fAngle: Single; //aktueller RotationsWinkel
  public
    procedure Render; //zeichnet das Objekt und alle Kinder
    procedure Progress(DeltaTime: Single); //berechnet die Bewegungen (Timebases Movement) DeltaTime: vergangene Zeit in ms
  end;

procedure TPlanet.Render;
var i: Integer;
begin
  glPushMatrix;
    glRotatef(fAngle, 010);
    glTranslatef(fRadius, 00);
    RenderKugel;
    for i := 0 to fChildren.Count-1 do
      TPlanet(fChildren[i]).Render;  
  glPopMatrix;
end;

procedure TPlanet.Progress(DeltaTime: Single);
begin
  fAngle := fAngle + DeltaTime/1000//1 Einheit/Sekunde bewegen
end;
Wenn du das so aufbaust, dann brauchst du nur noch die Baumstruktur der Planeten erstellen, den rest erledit die Klasse wenn du Sonne.Render; aufrufst.

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^

Für diesen Beitrag haben gedankt: Andreas95
Andreas95 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 36



BeitragVerfasst: Sa 22.01.11 13:48 
danke nochmal
also ich habe mal ein bisschen rumprobiert und gespielt, aber es haut immernoch nicht hin...
ich bekomme zwar, wenn ich glLoadIdentity von den timer entferne, und glrotatef(10,1,0,0) vor swapbuffers(dc) setze, eine rotation, aber die bewegen sich dann nur mit meinen gesetzten glrotatef, also bewegen sie sich alle genau gleich und rotieren nur um den mittelpunkt(sonne).

hier mein (unstrukturierter, da ich nur rumprobiere)(die werte sind irgendwelche, da egal wie ich den radius oder winkel setze, bewegt es sich nicht, wie es sollte); mache ich was falsch? (ja, ich bin immernoch absoluter anfänger in sache opengl, bitte verzeih die dumme fragen :) außerdem benutze ich im moment dreiecke, da ich nicht weit genug bin für kreise usw.
quelltext:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
unit Tut;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,dglopengl, StdCtrls, ExtCtrls, Buttons;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  DC, RC:HDC;
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin

  DC:=GetDC(Handle);
  RC:=CreateRenderingContext(DC,          //Device Contest     //renderkontext (wo wird gezeichnet)
                             [opDoubleBuffered], //Optionen   (was wird benutzt)
                             32,          //ColorBits
                             24,          //ZBits
                             0,           //StencilBits
                             0,           //AccumBits
                             0,           //AuxBuffers
                             0);          //Layer
  ActivateRenderingContext(DC, RC);
  glMatrixMode(GL_PROJECTION);
 glLoadIdentity;
  gluPerspective(60, ClientWidth/ClientHeight, 0.1100);





  gltranslatef(0,0,-15);

end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity;

  glPushMatrix;
    glbegin(gl_triangles);
         glColor3f(100); glVertex3f(-1,-10);
  glColor3f(001); glVertex3f( 1,-10);
  glColor3f(010); glVertex3f( 010);
 glEnd;
    glPushMatrix;
      glRotatef(35010);
      glTranslatef(200);
      glbegin(gl_triangles);
         glColor3f(100); glVertex3f(-1,-10);
  glColor3f(001); glVertex3f( 1,-10);
  glColor3f(010); glVertex3f( 010);
 glEnd;;
      glPushMatrix;
        glRotatef(35010);
        glTranslatef(200);
        glbegin(gl_triangles);
         glColor3f(100); glVertex3f(-1,-10);
  glColor3f(001); glVertex3f( 1,-10);
  glColor3f(010); glVertex3f( 010);
 glEnd;;
      glPopMatrix;
    glPopMatrix;
  glPopMatrix;
  swapbuffers(dc);
end;

end.
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Sa 22.01.11 17:01 
Hey,

bei dir bewegt sich nix, weil du jedesmal die selber Werte nimmst. Also zechnet er auch jedesmal das selbe bild. Du musst dir für die Rotationswinkel Variablen definieren, die du dann mit der Zeit langsam vergrößerst. Dann kommt da auch die Bewegung rein:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
procedure TForm1.Render;

  procedure DrawCircle(count: Integer);
  var
    i: Integer;
  begin
    glBegin(GL_TRIANGLE_FAN);
      glVertex3f(000);
      for i := 0 to count do
        glVertex3f(cos(2*Pi*i/count), sin(2*Pi*i/count), 0);
    glEnd;
  end;

begin
  glClearColor(0,0,0,0);
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;


  glTranslatef(00, -15);
  glPushMatrix;
    glColor3f(110);
    DrawCircle(64);
    glPushMatrix;
      glRotatef(EarthAngle, 001);
      glTranslatef(500);
      glScalef(0.50.50.5);
      glColor3f(001);
      DrawCircle(32);
      glPushMatrix;
        glRotatef(MoonAngle, 001);
        glTranslatef(200);
        glScalef(0.50.50.5);
        glColor3f(0.250.250.25);
        DrawCircle(16);
      glPopMatrix;
    glPopMatrix;
  glPopMatrix;

  SwapBuffers(RC.DC);
end;

Ich denke du verwechselst da noch was. Wenn du ein glRotate direkt vor das SwapBuffers(DC); setzt beweirkt das rein gar nix. Die ganzen Transformationen (glRotate, glTranslate, glScale, ...) beeinflussen nur den "Zeichenstift". Sobald du was mit glBegin-glEnd zeichnest wird es an der Position gezeichnet, an der der zeichenstift steh. Wenn du danach nochmal eine Transformation aufrufst, dann wird der Zeichenstifgt weiter gerückt. Auf das bereits gezeichnete hat das keinerlei Auswirkung ;)

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^

Für diesen Beitrag haben gedankt: Andreas95
Andreas95 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 36



BeitragVerfasst: Sa 22.01.11 17:56 
Wow, jetzt blick ich mein Fehler!
Danke für die ausführliche Hilfe! War wirklich Hilfreich :)