Autor Beitrag
elk
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Do 08.06.06 12:40 
HI, Ich soll für die Schule eine 3D Kugel programmieren. Ich habe leider keine Ahnung was ich machen soll.

Wo bekommt man Informationen zu dem Thema?

Wie erstelle ich ein 3D Objekt?

Kennt jemand ne tolle Seite?
mkinzler
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 4106
Erhaltene Danke: 13


Delphi 2010 Pro; Delphi.Prism 2011 pro
BeitragVerfasst: Do 08.06.06 12:59 

_________________
Markus Kinzler.
elk Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Mo 12.06.06 12:41 
So

Ich habe nun ein Problem.

Wir sollen KEINE Engines oder ähnliches benutzen(Direct X ..). Das Einziege was bleibt ist delphi.

Gibts da gute Seiten bzw. Algorithmen?
Ivo@CoMRoK
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 258

Win XP
D3 Prof., D7 Pe.
BeitragVerfasst: Mo 12.06.06 13:44 
Ja es gibt da ne Komponente, ist fast in jeder anderen komponente drin ... wie hieß das nochmal? Moment ...
Ach ja :!: ... Canvas :wink: .
Musst halt was rechnen.

Ne mal ernsthaft:
Müsst ihr Perspektivisch darstellen? Weil 3D darstellungen können doch eigentlich auch 2D sein
[Vorne,Hinten,Oben,Unten,Rechts,Links] wie in vielen Programmen (wie 3DsMax).
mfg Ivo

_________________
Fällt der Bauer tot vom Traktor, stand am Waldrand ein Reaktor.
Ein altes indianisches Sprichwort besagt:Es kann gefährlich sein gelben Schnee zu essen.
LLCoolDave
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 212

Win XP
Delphi 2005
BeitragVerfasst: Mo 12.06.06 14:12 
user profile iconIvo@CoMRoK hat folgendes geschrieben:

Müsst ihr Perspektivisch darstellen? Weil 3D darstellungen können doch eigentlich auch 2D sein
[Vorne,Hinten,Oben,Unten,Rechts,Links] wie in vielen Programmen (wie 3DsMax).
mfg Ivo


Wäre das nicht recht unsinnig, die Kugel sieht doch sowieso aus allen Richtungen gleich aus...

Die entscheidende Frage ist doch erstmal, was mit der Kugel gemacht werden soll. Textur drauflegen und drehen? Schattierung? Schattenwurf der Kugel? Bewegung im Raum? Etwas konkreter müsste die Aufgabenstellung schon sein, sonst gehen unsere Tips noch in die falsche Richtung.
elk Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Mo 12.06.06 14:19 
Nun ja.

Wie weit wir kommen, sollen wir dann selbst entscheiden (ist ein Projekt). Texturen drehen Schatten usw würden wir gerne machen. Wir haben jedoch keine Ahnung wie. Das einzige 3d mäßige was wir gemacht haben war ein Punkt der sich um bellibige Achsen drehen kann. Der sah jedoch 2d mäßig aus. Was wir brauchen ist ja ein "richtiges" 3d. Die Mathematik dazu haben wir größten teils, nur von der Umsetzung haben wir halt 0 Ahnung.

Das "Wie?" ist unser größtes problem.


---
Ach ja wir haben erfahren das es nicht nur ne Kugel, sondern auch Andere Simple Objekte sein sollen.
Gandalfus
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 129



BeitragVerfasst: Mo 12.06.06 23:30 
Es gibt 2 Probbleme:

3d zu 2d Projektion (siehe Matrizen)

Wenn die Kugel dann an der richtigen Stelle gezeichnet ist sieht sie immernoch nicht 3 dimensional aus.
Dafür muss man die Licht reflektion beachten. Also die Kugel ist nicht überall gleich hell das muss man umsetzten.

Also Grundlagen wären Matrizen und Vektoren.

_________________
Wennn man feststellt, dass es drei Moeglichkeiten gibt, die einen Vorgang schiefgehen lassen koennen und man diese ausschaltet, entstehen automatisch drei neue Moeglichkeiten.
elk Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Di 13.06.06 08:42 
Ja das dürfte kein Problem sein- das haben wir schon in Mathe gemacht ( Auch in bezug auf computer - mit beobachter usw.)

Ich weiß nur nicht, wie ich das anstellen soll.
Wo fange ich an?
P_G
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 75

Win XP
Delphi 7 / 8 Enterprise
BeitragVerfasst: Mi 14.06.06 09:16 
Hi Elk,

rein interessehalber - wird das Projekt benotet?

Gruß, P_G
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mi 21.06.06 00:43 
Liegt zwar schon eine Woche zurück; Hier eine mögliche Lösung.

Im Prinzip rechnest du aus den X,Y Koordinaten des Bildschirmes die Z-Koordinate auf der Kugel aus (Pythagoras). Die X,Y,Z-Werte transformierst du dann in Kugelkoordinaten und erhältst phi/theta. Phi/Theta sind jetzt quasi Längen/Breitengrade. Das heisst du musst jetzt nur noch die Texturfarbe an der Stelle Phi/Theta aus deinem Texturbitmap rauslesen und fertig. Das ganze ist dann natürlich nicht perspektivisch sonst wird es etwas komplizierter.

Kurzgefasst:
Pixels[x,y] := Texture(phi(x,y,z(x,y)),theta(x,y,z(x,y))

Die Formel für phi und theta erhältst du aus Wikipedia (siehe Link oben) und die Formel für z ist der Pythagoras nach z aufgelöst (x^2+y^2+z^2=r^2).

Das ganze lässt sich in gerade mal 156 Zeilen realisieren. Mit Textur und Beleuchtung und ohne OpenGl ;).

Unit1.pas
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:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
unit Unit1;

interface

uses Windows, Messages, Graphics, Forms, Classes, Controls, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    P0, T0: PDWord;
    Texture: TBitmap;
    W, H, W2, H2, t: Integer;
    function getPixelTexBase(x, y: Integer): PDWord;
    procedure WMEraseBkgnd(var Message:TWMEraseBkgnd); message WM_ERASEBKGND;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses math;

const
 R = 64// radius of the sphere
 TextureWidth = 512;
 TextureHeight = 512;
 Light: array[0..2of Single = (1,-1,0.8);

function calcPhiTheta(x,y,z: Single; var phi, theta: Single): Boolean;
var temp: Single;
begin
 temp := sqr(x)+sqr(y);
 if temp > 0 then
 begin
  temp := 1/sqrt(temp);
  theta := arccot(z*temp);
  temp := max(min(x*temp,1),-1);
  if y >= 0 then
   phi := arccos(temp) else
   phi := 2*pi-arccos(temp);
  Result := True;
 end else
  Result := False;
end;

function calcZ(x,y: Single): Single;
var temp: Single;
begin
 temp := sqr(R)-sqr(x)-sqr(y);
 if temp >= 0 then
  Result := sqrt(temp) else
  Result := NaN;
end;

procedure rotate(var x, y: Single; angle: Single);
var tx, s, c: Extended;
begin
 sincos(angle, s, c);
 tx := c*x-s*y;
 y := s*x+c*y;
 x := tx;
end;

function mixLight(color: DWord; intensity: Single): DWord;
var
 ColorA: array[0..3of Byte absolute color;
 ColorB: array[0..3of Byte absolute Result;
begin
 intensity := max(intensity,0.1); // minimum intensity = 0.1
 colorB[0] := Round(colorA[0]*Intensity);
 colorB[1] := Round(colorA[1]*Intensity);
 colorB[2] := Round(colorA[2]*Intensity);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
 x0, y0: Integer;
 wx, wy, wz, x, y, z, phi, theta, LightN: Single;
 P: PDWord;
begin
 P := P0;
 LightN := 1/sqrt(sqr(Light[0])+sqr(Light[1])+sqr(Light[2]));
 for y0 := H-1 downto 0 do
  for x0 := 0 to W-1 do
  begin
   wx := x0-W2; x := wx;
   wy := y0-H2; y := wy;
   wz := calcZ(wx,wy); z := wz;
   if not isNan(Z) then
   begin
    rotate(y,z,-t*0.02);
    rotate(z,x,-t*0.03);
    if calcPhiTheta(x,y,z,phi,theta) then
      P^ := mixLight(getPixelTexBase(Round(phi/pi/2*TextureWidth),
                     Round((theta/pi)*TextureHeight))^,
                     (Light[0]*wx+Light[1]*wy+Light[2]*wz)*LightN/R);
   end;
   inc(P);
  end;
 Image1.Invalidate;
 inc(t);
end;

procedure TForm1.FormCreate(Sender: TObject);
var x, y: Integer;
begin
 W := ClientWidth;
 H := ClientHeight;
 W2 := W div 2;
 H2 := H div 2;
 Image1.Picture.Bitmap.Width := W;
 Image1.Picture.Bitmap.Height := H;
 Image1.Picture.Bitmap.PixelFormat := pf32bit;
 P0 := Image1.Picture.Bitmap.ScanLine[H-1];
 FillChar(P0^, W*H*SizeOf(DWord), 0); // black background
 Texture := TBitmap.Create;
 Texture.Width := TextureWidth;
 Texture.Height := TextureHeight;
 Texture.PixelFormat := pf32bit;
 T0 := Texture.ScanLine[TextureHeight-1];
 for x := 0 to TextureWidth-1 do
  for y := 0 to TextureHeight-1 do
   getPixelTexBase(x,y)^ := (((x*2xor y) and $FF) * $010000;
 Texture.Canvas.Font.Color := clWhite;
 Texture.Canvas.Brush.Style := bsClear;
 Texture.Canvas.Font.Name := 'Arial';
 Texture.Canvas.Font.Size := 40;
 Texture.Canvas.TextOut(0,(TextureHeight-40div 2,'www.delphi-forum.de');
end;

function TForm1.getPixelTexBase(x, y: Integer): PDWord;
begin
 Result := T0;
 inc(Result, ((x+TextureWidth) mod TextureWidth)+
             ((y+TextureHeight) mod TextureHeight)*TextureHeight);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 Texture.Free;
end;

procedure TForm1.WMEraseBkgnd(var Message:TWMEraseBkgnd);
begin
 Message.result := 1;
end;

end.


Unit1.dfm
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
object Form1: TForm1
  Left = 192
  Top = 114
  BorderStyle = bsDialog
  Caption = 'Form1'
  ClientHeight = 128
  ClientWidth = 128
  Color = clBtnFace
  Position = poMainFormCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  object Image1: TImage
    Width = 128
    Height = 128
    Align = alClient
  end
  object Timer1: TTimer
    Interval = 50
    OnTimer = Timer1Timer
  end
end
Einloggen, um Attachments anzusehen!
elk Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Do 22.06.06 14:19 
So danke danke danke, aber- ich denk mal wenn ich das kopiere wird unser lehrer nciht ganz einverstanden sein.

Wir haben inzwischen ein bischen mehr Ahnung und es müsste eigendlich auch funktionieren, aber macht irgendwie nen Fehler.

Ka wie ich hier quelltext posten kann, deshalb mal der anhang.

einfach unter Kugel schaun!
Einloggen, um Attachments anzusehen!
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 22.06.06 21:19 
Ohne alle zugehörigen Units (Grafikobjekte und Mathe) und die dfm-Dateien bringt das niemand zum laufen...
elk Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Fr 23.06.06 12:00 
ok hier :)
Einloggen, um Attachments anzusehen!
Christian R.
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 23.06.06 12:19 
Ich hatte mal bei der Perspektivischen Darstellung folgende Probleme:

1. Methode: Strahlensatz;
Ich habe versucht mittels Strahlensatz die X,Y Koordinaten zu skalieren. Das Problem war z. Bsp. bei identischen Quadern, das sie in der Tiefe immer länger wurden, je tiefer sie im Raum positioniert waren.

2. Methode: Prozentuales Abnehmen wie bei Zinsrechnung
Orginal X,Y sind 100%. Bei einem Punkt Z mntw. 0,2% abziehen. Ergibt 99,8%. Beim zweiten Punkt Z aber wieder als 100% annehmen und davon 0,2 %. Problem: Die Tiefenkanten, die eigentlich gerade sein sollten wurden krumm.

3. Methode: Abziehen eines festen Wertes
Soll heißen, im Verhältnis zu Z wird immer der gleiche Wert von X und Y abgezogen. Somit wird eine gerade Tiefe erreicht und die Objekte werden wie in der Realität in "verschiedenen Tiefen" nur noch als Punkt gezeichnet.

Vielleicht hilft das.

//Edit: Grundsätzlich bin ich auch der Meinung, dass mit Matrizen gearbeitet werden sollte.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Sa 24.06.06 00:07 
Für Perspektive gibt's nur eine Lösung: x und y durch die Tiefenkoordinaten teilen ;)
Mit Vorteil rechnet man dann mit homogenen Koordinaten und Matrizen. Das ist aber im Prinzip eine rein formale Vereinfachung.. Die ist aber recht nützlich, man kann mit einer Matrix-Multiplikation die Welt in die Kamerasicht umrechnen; inkl. Verschiebung, Drehung und "Öffnungswinkel" der Kamera.
elk Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: So 25.06.06 13:44 
Hm habt ihr euch die rar mal gedownloaded?

Versteht ihr wie wir an das Problem herangegangen sind?

dann schaut mal warum das prog nciht läuft. Das müsste es nämlich eigendlich.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 25.06.06 20:01 
Nun das ist offensichtlich ein programmtechnischer Fehler. Das Debuggen von Code überlasse ich dem Autor. Dafür bietet Delphi ja gute "Tools" an. Der Fehler liegt (wie auch gemeldet wird) in der Datei Grafik3DObjekte Zeile 431. Das Array PF ist von der Länge Null und du versuchst auf den i-ten Eintrag zuzugreifen. Damit generierst du natürlich eine Exception. Was du dort genau erreichen willst weiss ich nicht.
elk Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Mo 26.06.06 13:08 
hier die aktuelle version

Nur mal interessehalber:
Wie kann ich das Array "PX" aus CKugel aus Grafik3DObjekte.pas in Leinwand.pas aufrufen um mir z.b. die werte anzeigen zu lassen nachdem er gerechnet hat.

Er kennt in Leinwand.pas das Array ja nicht - wie sag ich ihm das er es aus Grafik3DObjekte aus dem CKugel-teil nehmen soll?
Einloggen, um Attachments anzusehen!