3D Kugel aus einzelnen Quadraten erstellen

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von Nino »

Der Fachausdruck dafür heißt "Parkettierung". Vielleicht findest Du irgendwo im Internet etwas über Parkettierung einer Kugeloberfläche mit Vierecken. Das geht. Aber mit Quadraten geht's nicht ( auch wenn es sich 2-dimensional so darstellen lässt, als ob es ginge -- 2-dimensional kann man bekanntlich z.B. sogar einen Fluß darstellen, der im Kreis fleßt. :-) ).
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von Danilo »

dige hat geschrieben:Scheint jedenfalls doch nicht so einfach zu sein, Vierecke
räumlich so anzuordnen, das sie eine Kugel ergeben.

Ich glaube mal irgendwo ein Beispiel einer Kugel aus
Punkten gesehen zu haben. Vielleicht kann man über
den Punkt im Raum die Lage für ein Viereck errechnen.
Mit ein bissl Sinus und Cosinus kannst Du doch einen Kreis berechnen, und eine 3D-Kugel
auf dem Bildschirm besteht auch nur aus solchen Kreisen. Einmal in XY-Richtung und einmal
für den Z-Wert.
Gibt bestimmt optimierte Berechnungen, aber das ist wohl am einfachsten zu verstehen.
Die letzten Punkte an den Polen sind dann halt nur Dreiecke.

Schau Dir mal das folgende Beispiel an und spiele mit den Schrittweite (Tasten F1/F2 und F3/F4): Wireframe-Kugel erstellen
Um so mehr Zwischenschritte, desto mehr sieht es wie eine Kugel aus.

EDIT:
Hier nochmal alle Codes meiner damaligen Serie, da es das PureBoard-Archiv nicht mehr gibt:

1.) Einen Kreis auf der Z-Achse zeichnen und alle Punkte mit einem Mittelpunkt verbinden. Ergibt einen Kegel.

Code: Alles auswählen

Procedure.f GSin(winkel.f)
   ProcedureReturn Sin(winkel*(2*3.14159265/360))
EndProcedure 
 
Procedure.f GCos(winkel.f) 
   ProcedureReturn Cos(winkel*(2*3.14159265/360))
EndProcedure 

;-----

#sw = 1280
#sh = 1024
#sn = "Sinus"

#hsw = #sw/2
#hsh = #sh/2


;
; fix for fullscreen multi monitor bug in PB DirectX9
;
; Fullscreen problem with dualscreen monitor:
; http://www.purebasic.fr/english/viewtopic.php?f=4&t=41281
;
CallFunction(OpenLibrary(#PB_Any,"dwmapi.dll"),"DwmEnableComposition",0)


If InitSprite()=0 Or InitKeyboard()=0
  MessageRequester("ERROR","Cant init game engine !"):End
EndIf

If OpenScreen(#sw,#sh,32,#sn)=0
  If OpenScreen(#sw,#sh,24,#sn)=0
    If OpenScreen(#sw,#sh,16,#sn)=0
      If OpenScreen(#sw,#sh,08,#sn)=0
        MessageRequester("ERROR","Cant open screen !"):End
EndIf:EndIf:EndIf:EndIf
 

Procedure Point3Dto2D(x.f,y.f,z.f,*pt.POINT)
  ;If x < 0.0 : x2.f = -0.9 : Else : x2.f = 0.9 : EndIf
  ;If y < 0.0 : y2.f = -0.9 : Else : y2.f = 0.9 : EndIf
;   z = -z
;   *pt\x = ((#hsw + x * #hsw)*0.998999)+z*#hsw
;   *pt\y = ((#hsh + y * #hsh))+z*#hsh
  z + 1
  proj.f = 500
  *pt\x = (x/z)*proj+#hsw
  *pt\y = (y/z)*-proj+#hsh
EndProcedure


Procedure Line3D(x1.f,y1.f,z1.f,x2.f,y2.f,z2.f,color)
  Point3Dto2D(x1,y1,z1,p1.POINT)
  Point3Dto2D(x2,y2,z2,p2.POINT)
  If color = -1
    LineXY(p1\x,p1\y,p2\x,p2\y)
  Else
    LineXY(p1\x,p1\y,p2\x,p2\y,color)
  EndIf
EndProcedure


If CreateSprite(1,500,500)=0
  CloseScreen()
  MessageRequester("ERROR","Cant create sprite !"):End
Else
  ;DrawCircle(3,0)
EndIf

schrittweite = 8

Repeat 
    ExamineKeyboard() 
    FlipBuffers()
    If IsScreenActive()
      ;ClearScreen (0, 0, 0)
      ClearScreen(0)


      If StartDrawing(ScreenOutput())
;         Line3D(-0.5,-0.5,z, 0.5,-0.5,z,$00FFFF)
;         Line3D(-0.5,-0.5,z,-0.5, 0.5,z,$00FFFF)
;         Line3D(-0.5, 0.5,z, 0.5, 0.5,z,$00FFFF)
;         Line3D( 0.5, 0.5,z, 0.5,-0.5,z,$00FFFF)
; 
;         Line3D(-0.5,-0.5,z-0.5, 0.5,-0.5,z-0.5,$00FFFF)
;         Line3D(-0.5,-0.5,z-0.5,-0.5, 0.5,z-0.5,$00FFFF)
;         Line3D(-0.5, 0.5,z-0.5, 0.5, 0.5,z-0.5,$00FFFF)
;         Line3D( 0.5, 0.5,z-0.5, 0.5,-0.5,z-0.5,$00FFFF)
; 
;         Line3D(-0.5,-0.5,z,-0.5,-0.5,z-0.5,$00FFFF)
;         Line3D( 0.5,-0.5,z, 0.5,-0.5,z-0.5,$00FFFF)
;         Line3D(-0.5, 0.5,z,-0.5, 0.5,z-0.5,$00FFFF)
;         Line3D( 0.5, 0.5,z, 0.5, 0.5,z-0.5,$00FFFF)

        Point3Dto2D(0.0,0.0,0.0,pt2.POINT)

        FrontColor(RGB($FF,$FF,$00))
        grad.f = 90.0
        Point3Dto2D(gSin(grad)*0.5,-0.7,0-GCos(grad)*0.08,pt.POINT)
        old_x = pt\x
        old_y = pt\y
        While grad =< 360+91
          Point3Dto2D(gSin(grad)*0.5,-0.7,0-GCos(grad)*0.08,pt.POINT)
          ;Plot(pt\x,pt\y)
          LineXY(pt\x,pt\y,pt2\x,pt2\y)
          LineXY(pt\x,pt\y,old_x,old_y)
          old_x = pt\x
          old_y = pt\y
          grad + 360/schrittweite
        Wend
        
        FrontColor(RGB(255, 255, 255)) 
        DrawingMode(1) 
        ;Locate(50,30)
        DrawText(50,30,"Schrittweite (F1/F2): " + Str(Schrittweite))
        StopDrawing()
      EndIf

      If KeyboardPushed(#PB_Key_F1) And keypressed = 0
        Schrittweite + 1
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_F2) And keypressed = 0
        Schrittweite - 1
        If Schrittweite < 3 : Schrittweite = 3 : EndIf
        keypressed = 5
      EndIf
      If keypressed : keypressed - 1 : EndIf     

      ;Delay(20)

    EndIf
Until KeyboardPushed(#PB_Key_Escape)
2.) 2 Kreise auf der Z-Achse zeichnen und alle Punkte verbinden. Ergibt einen Zylinder.

Code: Alles auswählen

Procedure.f GSin(winkel.f)
   ProcedureReturn Sin(winkel*(2*3.14159265/360))
EndProcedure 
 
Procedure.f GCos(winkel.f) 
   ProcedureReturn Cos(winkel*(2*3.14159265/360))
EndProcedure 

;-----

#sw = 1024
#sh = 768
#sn = "Sinus"

#hsw = #sw/2
#hsh = #sh/2

If InitSprite()=0 Or InitKeyboard()=0
  MessageRequester("ERROR","Cant init game engine !"):End
EndIf

If OpenScreen(#sw,#sh,32,#sn)=0
  If OpenScreen(#sw,#sh,24,#sn)=0
    If OpenScreen(#sw,#sh,16,#sn)=0
      If OpenScreen(#sw,#sh,08,#sn)=0
        MessageRequester("ERROR","Cant open screen !"):End
EndIf:EndIf:EndIf:EndIf
 

Procedure Point3Dto2D(x.f,y.f,z.f,*pt.POINT)
  #proj = 200 ; gewöhnlich 100
  z + 1
  *pt\x = Round((x/z)* #proj+#hsw,1)
  *pt\y = Round((y/z)*-#proj+#hsh,1)
EndProcedure


Procedure Line3D(x1.f,y1.f,z1.f,x2.f,y2.f,z2.f,color)
  ; draw a line in 3D space
  Point3Dto2D(x1,y1,z1,p1.POINT)
  Point3Dto2D(x2,y2,z2,p2.POINT)
  If color = -1
    LineXY(p1\x,p1\y,p2\x,p2\y)
  Else
    LineXY(p1\x,p1\y,p2\x,p2\y,color)
  EndIf
EndProcedure

schrittweite = 5
z.f     = 0
obj_y.f = 0
obj_x.f = 0
obj_z.f = -0.5

Repeat 
    ExamineKeyboard() 
    FlipBuffers()
    If IsScreenActive()
      ClearScreen (0)

      If StartDrawing(ScreenOutput())
        FrontColor(RGB($FF,$FF,$00))
        grad.f = 90.0
        Point3Dto2D(obj_x+gSin(grad)*0.5,obj_y+0.5,(obj_z+0-GCos(grad)*0.1),pt.POINT)
        old_x1 = pt\x : old_y1 = pt\y
        Point3Dto2D(obj_x+gSin(grad)*0.5,obj_y-0.5,(obj_z-0-GCos(grad)*0.1),pt.POINT)
        old_x2 = pt\x : old_y2 = pt\y
        While grad =< 360+90+360/schrittweite
          Point3Dto2D(obj_x+gSin(grad)*0.5,obj_y+0.5,(obj_z+0-GCos(grad)*0.1),pt.POINT )
          Point3Dto2D(obj_x+gSin(grad)*0.5,obj_y-0.5,(obj_z-0-GCos(grad)*0.1),pt2.POINT)
          LineXY(pt\x ,pt\y ,pt2\x ,pt2\y )
          LineXY(pt\x ,pt\y ,old_x1,old_y1)
          LineXY(pt2\x,pt2\y,old_x2,old_y2)
          old_x1 = pt\x  : old_y1 = pt\y
          old_x2 = pt2\x : old_y2 = pt2\y
          grad + 360/schrittweite
        Wend
        
        FrontColor(RGB(255, 255, 255)) 
        DrawingMode(1) 
        DrawText(50,30, "Schrittweite (F1/F2): " + Str(Schrittweite))
        DrawText(50,50, "Cursor Keys left/right & up/down to move object")
        DrawText(50,70, "Keypad +/- to z00m object")
        StopDrawing()
      EndIf

      If KeyboardPushed(#PB_Key_F1) And keypressed = 0
        Schrittweite + 1
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_F2) And keypressed = 0
        Schrittweite - 1
        If Schrittweite < 3 : Schrittweite = 3 : EndIf
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_Up)
        obj_y + 0.01
      ElseIf KeyboardPushed(#PB_Key_Down)
        obj_y - 0.01
      ElseIf KeyboardPushed(#PB_Key_Left)
        obj_x - 0.01
      ElseIf KeyboardPushed(#PB_Key_Right)
        obj_x + 0.01
      ElseIf KeyboardPushed(#PB_Key_Add)      ; keypad +
        obj_z - 0.01
      ElseIf KeyboardPushed(#PB_Key_Subtract) ; keypad -
        obj_z + 0.01
      EndIf
      If keypressed : keypressed - 1 : EndIf     

      Delay(10)

    EndIf
Until KeyboardPushed(#PB_Key_Escape)
3.) Nun das ganze mit 3 Kreisen auf der Z-Achse:

Code: Alles auswählen

Procedure.f GSin(winkel.f)
   ProcedureReturn Sin(winkel*(2*3.14159265/360))
EndProcedure 
 
Procedure.f GCos(winkel.f) 
   ProcedureReturn Cos(winkel*(2*3.14159265/360))
EndProcedure 

;-----

#sw = 1024
#sh = 768
#sn = "Sinus"

#hsw = #sw/2
#hsh = #sh/2

If InitSprite()=0 Or InitKeyboard()=0
  MessageRequester("ERROR","Cant init game engine !"):End
EndIf

If OpenScreen(#sw,#sh,32,#sn)=0
  If OpenScreen(#sw,#sh,24,#sn)=0
    If OpenScreen(#sw,#sh,16,#sn)=0
      If OpenScreen(#sw,#sh,08,#sn)=0
        MessageRequester("ERROR","Cant open screen !"):End
EndIf:EndIf:EndIf:EndIf
 

Procedure Point3Dto2D(x.f,y.f,z.f,*pt.POINT)
  #proj = 400 ; gewöhnlich 100
  z + 1
  *pt\x = Round((x/z)* #proj+#hsw,1)
  *pt\y = Round((y/z)*-#proj+#hsh,1)
EndProcedure


Procedure Line3D(x1.f,y1.f,z1.f,x2.f,y2.f,z2.f,color)
  ; draw a line in 3D space
  Point3Dto2D(x1,y1,z1,p1.POINT)
  Point3Dto2D(x2,y2,z2,p2.POINT)
  If color = -1
    LineXY(p1\x,p1\y,p2\x,p2\y)
  Else
    LineXY(p1\x,p1\y,p2\x,p2\y,color)
  EndIf
EndProcedure

schrittweite = 20
z.f     = 0
obj_y.f = 0
obj_x.f = 0
obj_z.f = -0.1

Repeat 
    ExamineKeyboard() 
    FlipBuffers()
    If IsScreenActive()
      ClearScreen(0)

      If StartDrawing(ScreenOutput())
        FrontColor(RGB($FF,$FF,$00))
        grad.f = 90.0
        Point3Dto2D(obj_x+gSin(grad)*0.3,obj_y+0.3,(obj_z+0-GCos(grad)*0.1),pt.POINT)
        old_x1 = pt\x : old_y1 = pt\y
        Point3Dto2D(obj_x+gSin(grad)*0.5,obj_y    ,(obj_z-0-GCos(grad)*0.1),pt.POINT)
        old_x2 = pt\x : old_y2 = pt\y
        Point3Dto2D(obj_x+gSin(grad)*0.3,obj_y-0.3,(obj_z-0-GCos(grad)*0.1),pt.POINT)
        old_x3 = pt\x : old_y3 = pt\y
        While grad =< 360+90+360/schrittweite
          Point3Dto2D(obj_x+gSin(grad)*0.3,obj_y+0.3,(obj_z+0-GCos(grad)*0.1),pt.POINT )
          Point3Dto2D(obj_x+gSin(grad)*0.5,obj_y    ,(obj_z-0-GCos(grad)*0.1),pt2.POINT)
          Point3Dto2D(obj_x+gSin(grad)*0.3,obj_y-0.3,(obj_z-0-GCos(grad)*0.1),pt3.POINT)
          LineXY(pt\x  ,pt\y  ,pt2\x ,pt2\y )
          LineXY(pt3\x ,pt3\y ,pt2\x ,pt2\y )
          LineXY(pt\x ,pt\y ,old_x1,old_y1)
          LineXY(pt2\x,pt2\y,old_x2,old_y2)
          LineXY(pt3\x,pt3\y,old_x3,old_y3)
          old_x1 = pt\x  : old_y1 = pt\y
          old_x2 = pt2\x : old_y2 = pt2\y
          old_x3 = pt3\x : old_y3 = pt3\y
          grad + 360/schrittweite
        Wend
        
        FrontColor(RGB(255, 255, 255))
        DrawingMode(1) 
        DrawText(50,30, "Schrittweite (F1/F2): " + Str(Schrittweite))
        DrawText(50,50, "Cursor Keys left/right & up/down to move object")
        DrawText(50,70, "Keypad +/- to z00m object")
        StopDrawing()
      EndIf

      If KeyboardPushed(#PB_Key_F1) And keypressed = 0
        Schrittweite + 1
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_F2) And keypressed = 0
        Schrittweite - 1
        If Schrittweite < 3 : Schrittweite = 3 : EndIf
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_Up)
        obj_y + 0.01
      ElseIf KeyboardPushed(#PB_Key_Down)
        obj_y - 0.01
      ElseIf KeyboardPushed(#PB_KEY_LEFT)
        obj_x - 0.01
      ElseIf KeyboardPushed(#PB_KEY_RIGHT)
        obj_x + 0.01
      ElseIf KeyboardPushed(#PB_KEY_ADD)      ; keypad +
        obj_z - 0.01
      ElseIf KeyboardPushed(#PB_KEY_SUBTRACT) ; keypad -
        obj_z + 0.01
      EndIf
      If keypressed : keypressed - 1 : EndIf     

      Delay(10)

    EndIf
Until KeyboardPushed(#PB_Key_Escape)
4.) Nochmal mit 3D Kreisen. Zusätzlich verbinden wir die Pole, es entstehen dort Dreiecke.

Code: Alles auswählen

Procedure.f GSin(winkel.f)
   ProcedureReturn Sin(winkel*(2*3.14159265/360))
EndProcedure 
 
Procedure.f GCos(winkel.f) 
   ProcedureReturn Cos(winkel*(2*3.14159265/360))
EndProcedure 

;-----

#sw = 1024
#sh = 768
#sn = "Sinus"

#hsw = #sw/2
#hsh = #sh/2

If InitSprite()=0 Or InitKeyboard()=0
  MessageRequester("ERROR","Cant init game engine !"):End
EndIf

If OpenScreen(#sw,#sh,32,#sn)=0
  If OpenScreen(#sw,#sh,24,#sn)=0
    If OpenScreen(#sw,#sh,16,#sn)=0
      If OpenScreen(#sw,#sh,08,#sn)=0
        MessageRequester("ERROR","Cant open screen !"):End
EndIf:EndIf:EndIf:EndIf
 

Procedure Point3Dto2D(x.f,y.f,z.f,*pt.POINT)
  #proj = 400 ; gewöhnlich 100
  z + 1
  *pt\x = Round((x/z)* #proj+#hsw,1)
  *pt\y = Round((y/z)*-#proj+#hsh,1)
EndProcedure


Procedure Line3D(x1.f,y1.f,z1.f,x2.f,y2.f,z2.f,color)
  ; draw a line in 3D space
  Point3Dto2D(x1,y1,z1,p1.POINT)
  Point3Dto2D(x2,y2,z2,p2.POINT)
  If color = -1
    LineXY(p1\x,p1\y,p2\x,p2\y)
  Else
    LineXY(p1\x,p1\y,p2\x,p2\y,color)
  EndIf
EndProcedure

schrittweite = 20
z.f     = 0
obj_y.f = 0
obj_x.f = 0
obj_z.f = -0.1

Repeat 
    ExamineKeyboard() 
    FlipBuffers()
    If IsScreenActive()
      ClearScreen(0)

      If StartDrawing(ScreenOutput())
        FrontColor(RGB($FF,$FF,$00))
        grad.f = 90.0
        Point3Dto2D(obj_x+gSin(grad)*0.3,obj_y+0.3,(obj_z+0-GCos(grad)*0.1),pt.POINT)
        old_x1 = pt\x : old_y1 = pt\y
        Point3Dto2D(obj_x+gSin(grad)*0.5,obj_y    ,(obj_z-0-GCos(grad)*0.1),pt.POINT)
        old_x2 = pt\x : old_y2 = pt\y
        Point3Dto2D(obj_x+gSin(grad)*0.3,obj_y-0.3,(obj_z-0-GCos(grad)*0.1),pt.POINT)
        old_x3 = pt\x : old_y3 = pt\y
        Point3Dto2D(obj_x,obj_y+0.4,obj_z,m1.POINT)
        Point3Dto2D(obj_x,obj_y-0.4,obj_z,m2.POINT)
        While grad =< 360+90+360/schrittweite
          Point3Dto2D(obj_x+gSin(grad)*0.3,obj_y+0.3,(obj_z+0-GCos(grad)*0.1),pt.POINT )
          Point3Dto2D(obj_x+gSin(grad)*0.5,obj_y    ,(obj_z-0-GCos(grad)*0.1),pt2.POINT)
          Point3Dto2D(obj_x+gSin(grad)*0.3,obj_y-0.3,(obj_z-0-GCos(grad)*0.1),pt3.POINT)
          LineXY(pt\x  ,pt\y  ,pt2\x ,pt2\y )
          LineXY(pt3\x ,pt3\y ,pt2\x ,pt2\y )
          LineXY(pt\x  ,pt\y  ,m1\x  ,m1\y )
          LineXY(pt3\x ,pt3\y ,m2\x  ,m2\y )
          LineXY(pt\x ,pt\y ,old_x1,old_y1)
          LineXY(pt2\x,pt2\y,old_x2,old_y2)
          LineXY(pt3\x,pt3\y,old_x3,old_y3)
          old_x1 = pt\x  : old_y1 = pt\y
          old_x2 = pt2\x : old_y2 = pt2\y
          old_x3 = pt3\x : old_y3 = pt3\y
          grad + 360/schrittweite
        Wend
        
        FrontColor(RGB(255, 255, 255)) 
        DrawingMode(1) 
        DrawText(50,30, "Schrittweite (F1/F2): " + Str(Schrittweite))
        DrawText(50,50, "Cursor Keys left/right & up/down to move object")
        DrawText(50,70, "Keypad +/- to z00m object")
        StopDrawing()
      EndIf

      If KeyboardPushed(#PB_Key_F1) And keypressed = 0
        Schrittweite + 1
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_F2) And keypressed = 0
        Schrittweite - 1
        If Schrittweite < 3 : Schrittweite = 3 : EndIf
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_Up)
        obj_y + 0.01
      ElseIf KeyboardPushed(#PB_Key_Down)
        obj_y - 0.01
      ElseIf KeyboardPushed(#PB_Key_Left)
        obj_x - 0.01
      ElseIf KeyboardPushed(#PB_Key_Right)
        obj_x + 0.01
      ElseIf KeyboardPushed(#PB_Key_Add)      ; keypad +
        obj_z - 0.01
      ElseIf KeyboardPushed(#PB_Key_Subtract) ; keypad -
        obj_z + 0.01
      EndIf
      If keypressed : keypressed - 1 : EndIf     

      Delay(10)

    EndIf
Until KeyboardPushed(#PB_Key_Escape)
5.) Als letztes mit beliebig vielen Kreisen auf der Z-Achse:

Code: Alles auswählen

Procedure.f GSin(winkel.f)
   ProcedureReturn Sin(winkel*(2*3.14159265/360))
EndProcedure
 
Procedure.f GCos(winkel.f)
   ProcedureReturn Cos(winkel*(2*3.14159265/360))
EndProcedure

;-----
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows
   Structure POINT
     x.l
     y.l
   EndStructure
CompilerEndIf


#sw = 1024
#sh = 768
#sn = "Sinus"

#hsw = #sw/2
#hsh = #sh/2

If InitSprite()=0 Or InitKeyboard()=0
  MessageRequester("ERROR","Cant init game engine !"):End
EndIf

If OpenScreen(#sw,#sh,32,#sn)=0
  If OpenScreen(#sw,#sh,24,#sn)=0
    If OpenScreen(#sw,#sh,16,#sn)=0
      If OpenScreen(#sw,#sh,08,#sn)=0
        MessageRequester("ERROR","Cant open screen !"):End
EndIf:EndIf:EndIf:EndIf
 

Procedure Point3Dto2D(x.f,y.f,z.f,*pt.POINT)
  #proj = 400 ; gewoehnlich 100
  z + 1
  *pt\x = Round((x/z)* #proj+#hsw,1)
  *pt\y = Round((y/z)*-#proj+#hsh,1)
EndProcedure


Procedure Line3D(x1.f,y1.f,z1.f,x2.f,y2.f,z2.f,color)
  ; draw a line in 3D space
  Point3Dto2D(x1,y1,z1,p1.POINT)
  Point3Dto2D(x2,y2,z2,p2.POINT)
  If color = -1
    LineXY(p1\x,p1\y,p2\x,p2\y)
  Else
    LineXY(p1\x,p1\y,p2\x,p2\y,color)
  EndIf
EndProcedure

Procedure DrawObject(Radius.f,schrittweite1,schrittweite2,obj_x.f,obj_y.f,obj_z.f)
  If Schrittweite1 < 3 : Schrittweite1 = 3 : EndIf
  If Schrittweite2 < 1 : Schrittweite2 = 1 : EndIf
  gradschritte.f = 90.0 / Schrittweite2
  sincos.f    = 90.0
  For i = 1 To schrittweite2
    grad.f = 90.0
    Point3Dto2D(obj_x+gSin(grad)*(Radius*GSin(sincos)), obj_y-Radius*GCos(sincos), (obj_z+0-(Radius*GSin(sincos))*GCos(grad)*0.1), pt1.POINT)
    Point3Dto2D(obj_x+gSin(grad)*(Radius*GSin(sincos)), obj_y+Radius*GCos(sincos), (obj_z+0-(Radius*GSin(sincos))*GCos(grad)*0.1), pt2.POINT)
    old_x1 = pt1\x : old_y1 = pt1\y
    old_x2 = pt2\x : old_y2 = pt2\y
    While grad =< 360+90+360/schrittweite1
      Point3Dto2D(obj_x+gSin(grad)*(Radius*GSin(sincos)), obj_y-Radius*GCos(sincos), (obj_z+0-(Radius*GSin(sincos))*GCos(grad)*0.1), pt1.POINT )
      Point3Dto2D(obj_x+gSin(grad)*(Radius*GSin(sincos)), obj_y+Radius*GCos(sincos), (obj_z+0-(Radius*GSin(sincos))*GCos(grad)*0.1), pt2.POINT )
      If i = schrittweite2
        Point3Dto2D(obj_x,obj_y+Radius,obj_z,m1.POINT)
        Point3Dto2D(obj_x,obj_y-Radius,obj_z,m2.POINT)
        LineXY(pt1\x  ,pt1\y  ,m1\x  ,m1\y )
        LineXY(pt2\x  ,pt2\y  ,m2\x  ,m2\y )
      EndIf
      LineXY(pt1\x ,pt1\y ,old_x1,old_y1)
      If i>1
        LineXY(pt2\x ,pt2\y ,old_x2,old_y2)

        Point3Dto2D(obj_x+gSin(grad)*(Radius*GSin(sincos-gradschritte)), obj_y-Radius*GCos(sincos-gradschritte), (obj_z+0-(Radius*GSin(sincos-gradschritte))*GCos(grad)*0.1), pt3.POINT )
        LineXY(pt1\x,pt1\y,pt3\x,pt3\y)
        Point3Dto2D(obj_x+gSin(grad)*(Radius*GSin(sincos-gradschritte)), obj_y+Radius*GCos(sincos-gradschritte), (obj_z+0-(Radius*GSin(sincos-gradschritte))*GCos(grad)*0.1), pt4.POINT )
        LineXY(pt2\x,pt2\y,pt4\x,pt4\y)
      EndIf
      old_x1 = pt1\x  : old_y1 = pt1\y
      old_x2 = pt2\x  : old_y2 = pt2\y
      grad + 360/schrittweite1
    Wend
    sincos + gradschritte
    doit = 1
  Next i
EndProcedure

schrittweite1 = 25
schrittweite2 = 8
z.f     = 0
obj_y.f = 0
obj_x.f = 0
obj_z.f = -0.1

Repeat
    ExamineKeyboard()
    FlipBuffers()
    If IsScreenActive()
      ClearScreen (RGB(0,0,0))

      If StartDrawing(ScreenOutput())
        FrontColor(RGB($FF,$FF,$00))
        DrawObject(0.7,Schrittweite1,Schrittweite2,obj_x,obj_y,obj_z)
       
        FrontColor(RGB(255,255,255))
        DrawingMode(1)
        DrawText(50,30,"Schrittweite 1 (F1/F2): " + Str(Schrittweite1))
        DrawText(50,50,"Schrittweite 2 (F3/F4): " + Str(Schrittweite2))
        DrawText(50,80,"Cursor Keys left/right & up/down to move object")
        DrawText(50,100,"Keypad +/- to z00m object")
        StopDrawing()
      EndIf

      If KeyboardPushed(#PB_Key_F1) And keypressed = 0
        Schrittweite1 + 1
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_F2) And keypressed = 0
        Schrittweite1 - 1
        If Schrittweite1 < 3 : Schrittweite1 = 3 : EndIf
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_F3) And keypressed = 0
        Schrittweite2 + 1
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_F4) And keypressed = 0
        Schrittweite2 - 1
        If Schrittweite2 < 1 : Schrittweite2 = 1 : EndIf
        keypressed = 5
      ElseIf KeyboardPushed(#PB_Key_Up)
        obj_y + 0.01
      ElseIf KeyboardPushed(#PB_Key_Down)
        obj_y - 0.01
      ElseIf KeyboardPushed(#PB_Key_Left)
        obj_x - 0.01
      ElseIf KeyboardPushed(#PB_Key_Right)
        obj_x + 0.01
      ElseIf KeyboardPushed(#PB_Key_Add)      ; keypad +
        obj_z - 0.01
      ElseIf KeyboardPushed(#PB_Key_Subtract) ; keypad -
        obj_z + 0.01
      EndIf
      If keypressed : keypressed - 1 : EndIf     

      Delay(10)

    EndIf
Until KeyboardPushed(#PB_Key_Escape)
Zuletzt geändert von Danilo am 02.02.2013 14:22, insgesamt 1-mal geändert.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von STARGÅTE »

So, nun melde ich mich noch mal.
Es gibt genau 5 möglichkeiten, aus regelmäßigen Flächen eine "Kugel" zu bauen, und dass sind die platonischen Körper:
Bild

Dort hat man also bis zu 20 Flächen/Ecken, die alle zueinander den gleichen Abstand und Größe haben.

Natürlich kann man nun weiter gehen und "Ecken eindrücken" und erhält so weitere Flächen, aber diese sind dann nie wieder alle gleich.

@dige: Du hast halt immer noch nicht gesagt was du willst, ist es ok, wenn die Vierecke in den Polen zu vielen Dreiecken werden?
Ist es ok, wenn alles Quadrate sind, und sich damit überschneiden?
Was ist wenn die Texturen nicht zu lesen sind, weil es gedreht wurde?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von DarkDragon »

Also hier mal meine vorgeschlagene Lösung auf die schnelle zusammengekugelt - äh - gewürfelt (Haha .. was für'n Wortwitz):

Code: Alles auswählen

InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()

OpenWindow(0, 0, 0, 1024, 768, "")
OpenWindowedScreen(WindowID(0), 0, 0, 1024, 768)

; Testtextur generieren
CreateTexture(0, 512, 512)

Define bx.i, by.i

StartDrawing(TextureOutput(0))
For bx = 0 To OutputWidth() - 1 Step 32
  For by = 0 To OutputHeight() - 1 Step 32
    DrawingMode(#PB_2DDrawing_Default)
    Box(bx, by, 32, 32, RGB(bx * 255 / OutputWidth(), 255, by * 255 / OutputHeight()))
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(bx, by, 32, 32, RGB(255, 0, 0))
  Next by
Next bx
StopDrawing()

; Material erstellen
CreateMaterial(0, TextureID(0))

; Kugel erstellen
CreateSphere(0, 1.0, 32, 32)
CreateEntity(0, MeshID(0), MaterialID(0))

; Kamera erstellen
CreateCamera(0, 0, 0, 100, 100)
MoveCamera(0, 0, 0, 5.0)

; Licht erstellen
CreateLight(0, RGB(255, 255, 255), 0.0, 1.0, -3.0)

Define x.d, y.d

Repeat
  ExamineMouse()
  x + MouseDeltaX() * 0.001
  y + MouseDeltaY() * 0.001
  
  ScrollMaterial(0, x, y, #PB_Material_Fixed)
  
  ClearScreen(0)
  RenderWorld()
  FlipBuffers()
  
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape) Or WindowEvent() = #PB_Event_CloseWindow
End
Die Bilder müssten dann halt in eine Textur rein.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von STARGÅTE »

@DarkDragon:

Na so hab ich mir das Ding was dige haben will überhaupt nicht vorgestellt.
Aber ok, das ist natürlich eine mögliche Lösung.
So ist die vordere Texture immer gleich, weil du das Material drehst und nicht die "Drahtkugel".
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von NicTheQuick »

Wieso stürzt unter Linux eigentlich immer noch das Executable ab, wenn da irgendwo 3D verwendet wird?
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von DarkDragon »

STARGÅTE hat geschrieben:So ist die vordere Texture immer gleich
Ja, aber nicht bei Rotation um die Y Achse.

@NicTheQuick: Keine Ahnung, ich habe schon einige Zeit kein Desktop-Linux am laufen (wollte ich mal wieder ändern, aber mir fehlt die Zeit). Was sagt denn das Log?
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
dige
Beiträge: 1239
Registriert: 08.09.2004 08:53

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von dige »

@Stargate:
Bild
Bild

Das Bild ist vermutlich eine Kugel mit einer Bild Index Textur.
Mir schwebt aber vor, jedes Bild als separates Objekt zu zeichnen,
so das Zwischenraum zwischen den Bildern bleibt.

Das Bild das räumlich gesehen am nächsten zur
Bildschirmfläche gelegen ist soll vergrößert dargestellt
werden und dem Nutzer als aktuell auswählbares
Bild angezeigt werden.

Wenn jedes Viereck ein Objekt ist, können immer
wieder Bilder nachgeladen werden, je nach Richtung
in die die Kugel gedreht wird. Und somit kann durch
riesige Bildbestände navigiert werden.

Deshalb ist das Texturscrolling vermutlich keine Variante...
Zuletzt geändert von dige am 02.02.2013 20:02, insgesamt 1-mal geändert.
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von STARGÅTE »

Oke, damit lässt es sich schon mal arbeiten.
Aber was ist nun wenn man den Ball nicht nach links/rechts dreht, sondern nach oben/unten, "welche" Bilder sollen dann nachgeladen werden?

Natürlich kann man ein "unendlich" ausgedehntes Raster in einem ausschnitt so krümmen, dass es wie eine Kugel aussieht, dass ist vermutlich das, was du willst.
Einfach ein Raster von Bilder, wo ich in alle Seiten scrollen kann, nur dass dieses Raster halt im lokalen Bereich gekrümmt ist.
Richtig?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
dige
Beiträge: 1239
Registriert: 08.09.2004 08:53

Re: 3D Kugel aus einzelnen Quadraten erstellen

Beitrag von dige »

Das nachladen ist erstmal sekundär. Mich interessiert ersteinmal
ob es bspw. mit Sprite3D möglich ist die Bilder in Form
einer Kugel anzuordnen.

Das mit dem Raster und der Krümmung verstehe ich leider nicht :-/
"Papa, ich laufe schneller - dann ist es nicht so weit."
Antworten