Autor |
Beitrag |
elk
Hält's aus hier
Beiträge: 13
|
Verfasst: 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
      
Beiträge: 4106
Erhaltene Danke: 13
Delphi 2010 Pro; Delphi.Prism 2011 pro
|
Verfasst: Do 08.06.06 12:59
_________________ Markus Kinzler.
|
|
elk 
Hält's aus hier
Beiträge: 13
|
Verfasst: 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
      
Beiträge: 258
Win XP
D3 Prof., D7 Pe.
|
Verfasst: 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  .
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
      
Beiträge: 212
Win XP
Delphi 2005
|
Verfasst: Mo 12.06.06 14:12
Ivo@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 
Hält's aus hier
Beiträge: 13
|
Verfasst: 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
      
Beiträge: 129
|
Verfasst: 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 
Hält's aus hier
Beiträge: 13
|
Verfasst: 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
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Mi 14.06.06 09:16
Hi Elk,
rein interessehalber - wird das Projekt benotet?
Gruß, P_G
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: 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
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; TextureWidth = 512; TextureHeight = 512; Light: array[0..2] of 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..3] of Byte absolute color; ColorB: array[0..3] of Byte absolute Result; begin intensity := max(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); 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*2) xor 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-40) div 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
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 
Hält's aus hier
Beiträge: 13
|
Verfasst: 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
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Do 22.06.06 21:19
Ohne alle zugehörigen Units (Grafikobjekte und Mathe) und die dfm-Dateien bringt das niemand zum laufen...
|
|
elk 
Hält's aus hier
Beiträge: 13
|
Verfasst: Fr 23.06.06 12:00
ok hier 
Einloggen, um Attachments anzusehen!
|
|
Christian R.
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: 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
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: 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 
Hält's aus hier
Beiträge: 13
|
Verfasst: 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
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: 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 
Hält's aus hier
Beiträge: 13
|
Verfasst: 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!
|
|