3D Würfel ohne Ogre

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

3D Würfel ohne Ogre

Beitrag von Xaby »

Code: Alles auswählen

EnableExplicit

Structure p3D
  x.l
  y.l
  z.l
  x2D.l
  y2D.l
EndStructure

Global NewList E3D.p3D()

Procedure AddE3DPoint(x,y,z)
  AddElement(E3D())
  E3D()\x=x
  E3D()\y=y
  E3D()\z=z 
EndProcedure


;/ Wurfel vorn
AddE3DPoint(100, 100,100); oben rechts 0
AddE3DPoint(100,-100,100); unten rechts 1
AddE3DPoint(-100,-100,100); unten links 2
AddE3DPoint(-100,100,100); oben links 3

;/ genau gegenüber 
AddE3DPoint(100,100,-100) ; 4
AddE3DPoint(100,-100,-100) ; 5
AddE3DPoint(-100,-100,-100) ; 6
AddE3DPoint(-100,100,-100) ; 7

AddE3DPoint(-150,0,0)

;/ Ground
#Breite=64

AddE3DPoint(-#Breite,-100,-#Breite)
AddE3DPoint( #Breite,-100,-#Breite)
AddE3DPoint( #Breite,-100, #Breite)
AddE3DPoint(-#Breite,-100, #Breite)

;/ Damit Verzerrungen minimiert werden, müssen Flächen
;/ in kleinere Flächen geteilt werden!



Global cos.f, sin.f, temp.f, angle.f=0, ZeitMessung=0, scaleFactor.f=1, PI.f=3.1415926999999; gerundet

Procedure UpDateVerts()
  Protected rx, ry, rz
  
  rx=((E3D()\x*cos)-(E3D()\z*sin))
  ry=E3D()\y
  rz=((E3D()\z*cos)+(E3D()\x*sin))
  E3D()\x2D=240-(rx/(1+((rz*scaleFactor)/500)))
  E3D()\y2D=160-(ry/(1+((rz*scaleFactor)/500)))
  
EndProcedure

Procedure Calc()
  ;/If (angle>PI) ;/ Schlüssel
  If (angle<PI)
    If angle<(0.5*PI)
      temp=((angle*(2/PI))-0.5)
      sin=(0.75-((temp*temp)-temp))
      cos=(0.75-((temp*temp)+temp))
    Else  
      temp=((((PI-angle)*(2/PI)))-0.5)
      sin=(0.75-((temp*temp)-temp))
      cos=(-0.75+((temp*temp)+temp)) 
    EndIf
  Else  ;/ ohne Sonst sieht es ganz schön schlimm aus
    If angle<(1.5*PI)
      temp=(((angle-PI)*(2/PI))-0.5)
      sin=(-0.75+((temp*temp)-temp))
      cos=(-0.75+((temp*temp)+temp))
    Else  
      temp=((((2*PI)-angle)*(2/PI))-0.5)
      sin=(-0.75+((temp*temp)-temp))
      cos=(0.75-((temp*temp)+temp)) 
    EndIf 
  EndIf
  
EndProcedure


Procedure V2DLine(E1,E2)
  Protected x, y
  If E1 < CountList(E3D()) And  E2 < CountList(E3D())
  SelectElement(E3D(),E1)
  x=E3D()\x2D
  y=E3D()\y2D
  SelectElement(E3D(),E2)
  LineXY(x,y,E3D()\x2D,E3D()\y2D,RGB(0,255,0)) ;/ grüne Linie
  EndIf 
EndProcedure



Procedure Draw2D()
  StartDrawing(ImageOutput(0))
  Box(0,0,480,360,0)
  Plot(240,180,RGB(255,255,255))
  
  ForEach E3D()
    Calc()
    UpDateVerts()
    Circle(E3D()\x2D,E3D()\y2D,4,RGB(255,0,0))
  Next
  
  
  V2DLine(0,1)
  V2DLine(1,2)
  V2DLine(2,3)
  V2DLine(3,0)
  
  V2DLine(0,4)
  V2DLine(1,5)
  V2DLine(2,6)
  V2DLine(3,7)
  
  V2DLine(4,5)
  V2DLine(5,6)
  V2DLine(6,7)
  V2DLine(7,4)
  
  V2DLine(8,2)
  V2DLine(8,3)
  V2DLine(8,6)
  V2DLine(8,7)
  
  StopDrawing()
  SetGadgetState(0,ImageID(0))
EndProcedure




Procedure createGadgets()
  CreateImage(0,480,360)
  
  ImageGadget(0,10,5,480,360,ImageID(0),#PB_Image_Border)
  
EndProcedure

Procedure fortlaufend()
  If (ElapsedMilliseconds()-ZeitMessung)>(1000/50)
  angle+0.05
  If (angle<0)
    angle+(2*PI)
  EndIf
  If (angle>(2*PI))
    angle-(2*PI)
  EndIf
  Draw2D()
  ZeitMessung=ElapsedMilliseconds()
  EndIf
EndProcedure


Procedure CreateSprites()
  Protected x,y
  CreateSprite(0,128,128,#PB_Sprite_Texture)
  CreateSprite(1,128,128,#PB_Sprite_Texture)
  
  StartDrawing(SpriteOutput(0))
    Box(0,0,SpriteWidth(0),SpriteHeight(0),RGB(255,64,0))
    Box(5,5,40,15,RGB(0,64,100))
    LineXY(0,0,SpriteWidth(0),SpriteHeight(0),RGB(0,0,255))
    LineXY(0,SpriteHeight(0),SpriteWidth(0),0,RGB(0,0,255))
  StopDrawing()
    
  
  StartDrawing(SpriteOutput(1))
  Box(0,0,SpriteWidth(0),SpriteHeight(0),RGB(0,64,0))
  For y=0 To 10
    For x=0 To 10
      Box(12*x,12*y,8,8,RGB(0,64+Random(40),100))
    Next  
  Next  
  
  StopDrawing()
    
    
  CreateSprite3D(0,0)  
  CreateSprite3D(1,1)  
EndProcedure

Procedure X2D(E)
  SelectElement(E3D(),E)
  ProcedureReturn E3D()\x2D
EndProcedure
Procedure Y2D(E)
  SelectElement(E3D(),E)
  ProcedureReturn E3D()\y2D
EndProcedure

Procedure DrawSprites()
  Start3D()
  
  TransformSprite3D(1,X2D(9),Y2D(9),X2D(10),Y2D(10),X2D(11),Y2D(11),X2D(12),Y2D(12))
  DisplaySprite3D(1,0,0)
  
  TransformSprite3D(0,X2D(0),Y2D(0),X2D(1),Y2D(1),X2D(5),Y2D(5),X2D(4),Y2D(4))
  DisplaySprite3D(0,0,0)
  
  TransformSprite3D(0,X2D(0),Y2D(0),X2D(4),Y2D(4),X2D(7),Y2D(7),X2D(3),Y2D(3))
  DisplaySprite3D(0,0,0)
  
   
  TransformSprite3D(0,X2D(4),Y2D(4),X2D(5),Y2D(5),X2D(6),Y2D(6),X2D(7),Y2D(7))
  DisplaySprite3D(0,0,0)
  
  TransformSprite3D(0,X2D(0),Y2D(0),X2D(1),Y2D(1),X2D(2),Y2D(2),X2D(3),Y2D(3))
  DisplaySprite3D(0,0,0) 
  
  TransformSprite3D(0,X2D(0),Y2D(0),X2D(4),Y2D(4),X2D(5),Y2D(5),X2D(1),Y2D(1))
  DisplaySprite3D(0,0,0) 
  
  Stop3D()
EndProcedure

If OpenWindow(0,0,0,600,750,"FL 3D - ACHTUNG! Bei Window-Events wird 3D mit Texturen unterbrochen!",#PB_Window_ScreenCentered | #PB_Window_SystemMenu) And CreateGadgetList(WindowID(0))
  
  InitSprite()
  OpenWindowedScreen(WindowID(0),10,380,480,360,0,0,0)
  InitSprite3D()
  CreateSpriteS()
  Sprite3DQuality(1)
  
  
  createGadgets() 
  Draw2D()
  
  Define Event.l, Quit, GadgetNr
  
  Repeat
  
  Repeat
    
    Event=WaitWindowEvent(20)
    
     If Event=16
      Quit=1
      
    ElseIf Event=#PB_Event_Gadget
      GadgetNr=EventGadget() 
      
      
    EndIf
    
    ;/ fortlaufend
    fortlaufend()
    
  Until Event=0
  
  FlipBuffers()
  ClearScreen(0)
  
  DrawSprites()
    
    
  Until Quit  
  
  
EndIf
Hat jemand eine Idee, wie ich meinen Code vereinfachen kann, Z-Buffer ordentlich einbinde und die Texturen richtig verformt werden?

Wie muss ich die 3D-Koordinaten richtig in Transformsprite3D einbringen, damit mein Würfel wie ein würfel mit richtig verformten Texturen aussieht?

:shock:
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Beitrag von Scarabol »

Hi,

also das Z-Buffern kannst du realisieren indem du alle Sprites in eine Liste schreibst und diese sortierst, nach ihrem Z-Wert und dann anzeigst.
Das funktioniert aber nur für komplette Sprites....

Der Z-Parameter wird nur benutzt um die Textur richtig darzustellen....

Gruß
Scarabol
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Soweit so gut.

Z-Buffering ist ja auch nicht unbedingt das Problem.

Schwieriger wird es zu verstehen, wie eine Transformation aussehen muss, dass sie die Diagonalen vernünftig "realistisch" darstellt.

Wenn du meinen Code ausprobiert hast, solltest du sehen, dass die blauen Linien sich merkwürdig verhalten an der linken Seite.

Wie müsste die Transformation korrekt sein?

:?
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Beitrag von Scarabol »

Die blauen Linien werden nur richtig dargestellt wenn du den Z-Parameter bei Transformsprite3D mit angibst....

Gruß
Scarabol
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

die x/y die du angibst, sind die aufm screen.
die z die du angibst, stellt eine virtuelle tiefe dar, die hilft, verzerrungen zu vermeiden.
wenn du also ein trapez hast, um eine schräg-aufsicht zu simulieren,
gibst du den oberen (hinteren) punkten ne koordinate von z.b. z=-20,
den unteren (vorderen) von z.b. z=0.
mit ein bissel probieren findest du das richtige verhältnis.
(oder das vorzeichen umgedreht, bin jetzt nicht sicher)

ich kann dir grad kein beispiel coden, kann keinen screen öffnen,
weil ich im Hintergrund ein Game laufen hab.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Genau das habe ich erwartet.

Rumprobieren kann ich auch selbst, dazu brauche ich hier nichts posten.
Hab schon einiges probiert.

@Scarabol

Nein sag an ....

ich kann ja auch lesen. Aber wenn du auf meine Frage zweimal das selbe schreibst, hilft das nicht weiter. Ich habe verstanden, dass die Z-Angabe etwas mit der falschen Darstellung zu tun hat. Aber eine phylosophische Erläuterung hilft mir nicht weiter.

Sag konkret wie es aussehen muss, alles andere gehört in die Laberecke.
Ist nicht böse gemeint, aber ich habe Code gepostet, das Problem geschildert, mich damit auseinander gesetzt und ich komme nicht weiter.

Was soll ich mit den Angaben also anfangen, die du machst, wenn sie meine Unwissenheit nicht verringern?

Wenn du mir helfen magst, würde ich mich sehr freuen, wenn du vielleicht meine falsche Stelle durch einen richtigen Code hier postest.

Dank euch im Voraus.

@Kaeru German ...

dann warte ich, bis das Spiel gespielt wurde :roll:
Kinder an die Macht http://scratch.mit.edu/
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

soweit ich das verstanden habe, sind die koordinaten eben keine raumkoordinaten,
sondern bildkoordinaten, und die z-koordinaten "nur" virtuelle hilfskoordinaten.

wie genau die dann aussehen müssen, weiß ich auch nicht.

> Rumprobieren kann ich auch selbst, dazu brauche ich hier nichts posten.

ich müßte auch rumprobieren.

bei einem kurzen test habe ich das rausbekommen:

Code: Alles auswählen

InitSprite()
InitSprite3D()
OpenWindow(0, #PB_Ignore, #PB_Ignore, 600, 200, "Transform Sprite", #PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0),0,0,600,200,0,0,0)

CreateSprite(0,128,128,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(0))
  Box(0,0,128,128,$40C000)
  For n=0 To 15
    Line(0,n*8+3,128,0,$402010)
    Line(n*8+3,0,0,128,$402010)
  Next
StopDrawing()

Sprite3DQuality(1)

CreateSprite3D(1,0)
TransformSprite3D(1,-32,-32,       32,-32,       64, 64,      -64, 64)
;                    x1  y1   z1   x2  y2   z2   x3  y3   z3   x4  y4   z4
CreateSprite3D(2,0)
TransformSprite3D(2,-32,-32,  64,  32,-32,  64,  64, 64, -32, -64, 64, -32)

Repeat
  EvID = WaitWindowEvent(50)

  ClearScreen($300030)
    DisplaySprite(0,36,36)

Start3D()
    DisplaySprite3D(1,300,100)
    DisplaySprite3D(2,500,100)
Stop3D()

  FlipBuffers()

Until EvID = #PB_Event_CloseWindow
wieso jetzt aber die werte mit eben diesem verhältnis genau hinhaun, weiß ich auch nicht.
aber wenn du dich mit Projektionen auskennst, dein beispiel macht zumindest den eindruck,
dann kannst du dir bestimmt ausfitzeln, wie das zusammenhängt...

PS:
nachdem ich deinen code mal aufmerksamer gelesen hab...
du hast ja gar keine z-koordinaten bei den transform-befehlen angegeben!

scarabols einwand war also 100pro berechtigt.
hast du denn mal ausprobiert, korrekte 3D-koordinaten für die transformation anzugeben?
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Beitrag von Scarabol »

Hi,

nochmal der Z-Parameter ist die Entfernung zum Bildschirm, diese musst du so oder so berechnen, daher sollte es auch kein Problem sein diesen in Wert in TransformSprite3D einzusetzen....

Hast du ernsthaft vor dir ne 3D Engine zu basteln oder willst du nur ne Sprite3D Grafikdemo erstellen?

Ich habs auch mal versucht, damit ne kleinere Engine zu schreiben, aber das funktioniert leider nicht so wie es soll, denn selbst wenn du einen Z-Paramter angibst verschiebt der lediglich die Textur an die korrekte Position. Also funktioniert das Z-Buffering nur Spritewise was nachher wirklich mies aussieht....

Hier mal mein damaliger Versuch: (inzwischen bin ich zu OpenGl übergegangen)
http://uploaded.to/?id=8h59xi

Gruß
Scarabol
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

Wieso überhaupt Sprite3D?
Mit einem Renderer ist das sicher besser möglich...
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Ich hatte mal Z-Koordinaten eingesetzt, aber das führte halt zu keinem befriedigendem Ergebnis, hatte wohl die falsche Kombination und das Ergebnis, was ich so erzielte, war besser als mit (falschen) Z-Koordinatenangaben.

OpenGL wäre natürlich besser, magst mich unterstützen, mich aufklären, einen Würfel-Code mit OpenGL-Posten? Danielo hatte mal einen, der ist aber noch aus PureBasic Uralt Zeiten, gibt es auf der PureBasic Seite, aber leider nur eine EXE soweit ich weiß.

Ein Renderer :D Am besten einen Raytracer :allright:

@Kaeru German

Ich weiß einfach nicht, wozu die Z-Koordinaten da sind. Es steht zwar in der PB-Hilfe, dass sie optional sind, aber rein theorethisch, müsste meine Verzerrung korrekt sein. Denn wenn ich die ganze Sache selbst erledige, Software mäßig und meine Textur aus Voxeln zusammensetze, sieht es auch so aus.

Oder sagen wir nicht Voxel, denn die haben ja auch eine Z-Koordinate, sondern wenn ich einfach 2D-Pixel nach einem bestimmtem Allgorithmus oben zusammen schiebe ...

>>>>>>>>>>>>>>>
Woher kommt also dieser Clipping-Effect, will den jemand oder kann man den PureBasic-Befehl so umschreiben, dass bei OHNE Z-Koordinaten es immer so aussieht wie bei Kaeru Germans Beispiel.

Das wäre prima. Es sei denn, es steckt ein tieferer Sinn dahinter, den ich noch nicht erschlossen habe :roll: :allright: :allright: :allright: :allright: :allright: :allright:
Kinder an die Macht http://scratch.mit.edu/
Antworten