Textur verteilt auf eine Kugel projizieren?

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Krischan

Betreff: Textur verteilt auf eine Kugel projizieren?

BeitragDi, Okt 11, 2005 13:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

ich möchte für eine Erdkugel eine grössere Textur als 1024x512 verwenden (z.B. 2048x1024). Da die Texturgrösse in Blitz3D ja begrenzt ist (oder von der Graka abhängt), könnte man doch die Textur teilen, also z.B. in vier einzelne Teile auf vier Viertelkugeln. Fragen:

- geht das überhaupt mit Blitz3D? falls ja:

- wie projiziert man die einzelnen Texturteile so auf eine Kugel, dass es nachher wieder eine richtige Erde ergibt?

- könnte man auch zwei Halbkugeln nehmen und die Hälfte der Textur (dann quadratisch) auf je eine Halbkugel mittig projizieren und die Kugeln dann am Nullmeridian verkleben?

- oder mit vier Viertelkugeln?

user posted image

Ich habe das mal in irgendeinem Programm gesehen, leider mit unschönen Nähten, aber der hatte das irgendwie hinbekommen. Leider waren meine Versuche mit Kugeln, Halbkugeln und Viertelkugeln in Blitz3D nicht besonders ergiebig, auch die Referenz gibt da nichts her.

Vielleicht weiss das jemand von Euch, wäre klasse![img][/img]
 

Ava

Gast

BeitragDi, Okt 11, 2005 15:34
Antworten mit Zitat
Ja, das ist alles möglich was Du da aufzählst.

Natürlich wäre es am einfachsten, ein entsprechendes Modell mit einem 3D-Editor zu erstelllen. Aber auch direkt in Blitz kannst Du das tun, indem Du Dir eine eigene Funktion schreibst, die Dir diese Kugel (oder eben ihre Einzelteile) berechnet und erstellt. Bei einer einzelnen Kugel musst Du dann eben vier Surfaces erstellen, die Du mit den jeweils unterschiedlichen Texturen bemalst. Wenn Du einzelne Kugelteile verwenden möchtest, dann bekommst Du die unschönen "Narben" an den Übergängen dadurch weg, indem Du die Kanten-Normalen miteinander verrechnest.
 

Krischan

BeitragDi, Okt 11, 2005 15:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Oh, so schnell eine Antwort , prima Forum Smile Schön dass das geht, Blitzbasic scheint echt eine feine Sache zu sein, kein Fehlkauf Wink

Hmm, auf die Gefahr hin mich unbeliebt zu machen: wie würde so eine Funktion aussehen? Ich denke, die 4-Kugelteile-Methode wäre die beste, da man dann theoretisch Texturen bis 4096x2048 hinbekäme (reicht für NASA-Grafiken aus denke ich Wink, oder? Ich habe leider erst mit B3D angefangen (irgendwann Mitte der 90er mit QB45 aufgehört), vielleicht irgendeinen Tip/Beispiel/Tutorial/Suchbegriff zu diesem Thema?

Was ich mich auch frage: angenommen ich habe so eine Viertelkugel, die hat ja ausser der runden Seite noch drei glatte Flächen. Würde die Textur sich nicht auch da herum wrappen und verzerren? Die Textur sollte natürlich nur auf der runden Planetenoberfläche gewrapped werden. Wie programmiert man so etwas? Und was sind Kantennormalen? *grübel*

Kann man denn so ein zusammengeklebtes Objekt dann auch als einzelne Entity behandeln, also Turn, Scale usw... oder muss man die vier Objekte dann synchron ansprechen?
 

Ava

Gast

BeitragDi, Okt 11, 2005 16:21
Antworten mit Zitat
Du kannst das "zusammengebastelte" Objekt (also die vier einzelnen Kugelteile) als ein einzelnes Objekt verwenden, wenn Du ihm bspw. einen "Pivot-Kern" gibst. Das heisst in etwa soviel, dass Du im Zentrum der vier Kugelteile einen Pivot (das ist ein einfacher unsichtbarer Punkt im 3D-Raum) erstellst und anschliessend die Kugelteile als Childs an diesen Pivot "anheftest". Wenn Du nun den Pivot bewegst, rotierst oder skalierst, dann hat das auch Auswirkung auf seine Childs (also die Kugelteile).

Eine Normale besitzt jeder Vertex. Die ist auschlaggebend dafür, wie das Licht auf Deinem 3D-Objekt berechnet wird. Die "Kanten-Normalen" sind eben die Normalen der Vertices, die direkt an den Kanten der Kugeteile liegen. Diese müssen mit den Kanten der jeweils anschliessenden Kugelteile verrechnet werden, damit letztendlich die Lichtberechnung auch stimmt und keine hässlichen "Narben" an den Kanten zu sehen sind.

Puh, und wie Du diese Theorie nun genau in die Praxis umsetz... ein direktes Tutorial wüsste ich da nicht. Am besten machst Du dich mal mit diesen Befehl vertraut: http://blitzbase.de/menu/3r.htm und probierst dann einfach mal damit rum. Letzendlich wirst Du Dir dann irgendwie Deine Kugel mit Cos()/Sin() berechnen müssen und einen Weg finden, die 2D-Koordinaten Deiner Textur in UV-Koordinaten umzurechnen.

8)
 

Krischan

BeitragDi, Okt 11, 2005 17:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok, dann werde ich mich damit mal beschäftigen. Sieht auf den ersten Blick etwas verwirrend aus, wenn ich was braucbares zusammengezimmert habe, poste ich das hier später. Vielen Dank!
 

BIG BUG

BeitragMi, Okt 12, 2005 21:34
Antworten mit Zitat
Benutzer-Profile anzeigen
So, hab Dir die Arbeit abgenommen Smile:
Code: [AUSKLAPPEN]

;CreateSpherePart by Robert Hierl 12.10.2005
Graphics3D 640,480,16,2

SetBuffer BackBuffer()

camera=CreateCamera()
light=CreateLight()

CameraZoom camera, 2
PositionEntity camera,0,0,-6
RotateEntity light,90,0,0

tex=LoadTexture("Earth.tga")

mesh   = CreateSpherePart(-90, 90, 0, 360, 8)
sphere = CreateSphere(8)

EntityTexture mesh,   tex
EntityTexture sphere, tex

PositionEntity mesh,   -1.5,0,0
PositionEntity sphere,  1.5,0,0

While Not KeyHit(1)


RotateMesh mesh,  KeyDown(203)-KeyDown(205),KeyDown(200)-KeyDown(208),KeyDown(44)-KeyDown(45)
RotateMesh sphere,KeyDown(203)-KeyDown(205),KeyDown(200)-KeyDown(208),KeyDown(44)-KeyDown(45)

RenderWorld

;ShowVertices(mesh,   camera, $030303)
;ShowVertices(sphere, camera, $030303)

Flip
Wend
End




Function CreateSpherePart(start_pitch,end_pitch, start_yaw, end_yaw, segments, radius#=1, parent=0)

   Local nx#, ny#, nz#
   Local yaw#, pitch#, step_yaw#, step_pitch#
   Local step_u#, step_v#
   Local seg_pitch, seg_yaw, vert_pitch, vertex

   Local yaw_i, pitch_i
   Local mesh, surface


   seg_pitch  = segments
   vert_pitch = seg_pitch + 1
   seg_yaw    = segments * 2

   step_yaw#   = (end_yaw   - start_yaw)   / Float#(seg_yaw)
   step_pitch# = (end_pitch - start_pitch) / Float#(seg_pitch)
   step_u#    = 1 / Float#(seg_yaw)
   step_v#    = 1 / Float#(seg_pitch)

   mesh    = CreateMesh(parent)
   surface = CreateSurface(mesh)     

   yaw#   = start_yaw
   pitch# = start_pitch
   For yaw_i = 0 To seg_yaw

      If yaw_i = seg_yaw Then yaw# = end_yaw

      For pitch_i = 0 To seg_pitch

         If pitch_i = seg_pitch Then pitch# = end_pitch

         ny# = Sin#(pitch#)/Cos#(pitch#)
         nx# = Sin#(yaw#)
         nz# = Cos#(yaw#)

        ;Vektor auf Länge 1
         faktor# = Sqr((nx# * nx#)+(ny# * ny#)+(nz# * nz#))
         nx# = nx# / Abs(faktor#)
         ny# = ny# / Abs(faktor#)
         nz# = nz# / Abs(faktor#)

         If Abs(pitch#) = 90 Then
            nx# = 0
            ny# = Sgn(pitch#)
            nz# = 0
         EndIf

         vertex = AddVertex (surface, nx#*radius#, ny#*radius#, nz#*radius, 1 - step_u# * yaw_i, 1 - step_v# * pitch_i) 
         VertexNormal surface, vertex, nx#, ny#, nz#
 
;       ;Vertices verbinden
         If yaw_i > 0 And pitch_i > 0
           
            AddTriangle surface, yaw_i * vert_pitch + pitch_i, (yaw_i-1) * vert_pitch + pitch_i-1, (yaw_i)   * vert_pitch + pitch_i-1
            AddTriangle surface, yaw_i * vert_pitch + pitch_i, (yaw_i-1) * vert_pitch + pitch_i,   (yaw_i-1) * vert_pitch + pitch_i-1             

         EndIf
         
         pitch# = pitch# + step_pitch#
      Next
      pitch# = start_pitch
      yaw# = yaw# + step_yaw#
   Next



   Return mesh

End Function



Function ShowVertices(entity,camera, col = $00FF00)

   Local surface, startx, starty, vx#, vy#, vz#

   surface=GetSurface(entity,1)

   For i=0 To CountVertices(surface)-1

      TFormPoint VertexX# (Surface, i), VertexY# (Surface, i),VertexZ# (Surface, i), entity,0
      vx# = TFormedX#()
      vy# = TFormedY#()
      vz# = TFormedZ#()

      CameraProject camera, VX#, VY#, VZ#

      WritePixel ProjectedX#(),ProjectedY# (), col

   Next

End Function


Der Pitchwinkel geht bei einer Kugel von -90 bis +90, der Yawwinkel von 0 bis 360.

Mit z.B. Pitch 0 - 90 und Yaw 0 - 180 könntest Du dann ein Kugelviertel erstellen.
Natürlich solltest Du dann auch die Anzahl der Segmente vierteln.

Jetzt bräuchte man nur noch ne Heightmap von der Erde...
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)
 

Krischan

BeitragMi, Okt 12, 2005 22:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Uiiiiiiiii, und ich habe mich noch mit dem Addvertex herumgeschlagen und erstmal aus Frust einen Saturn gebastelt Smile Vielen Dank! Können bestimmt auch andere hier gebrauchen, ist ja quasi was unverselles Smile Ich habe Deinen Code auch gleich mal auf mein Problem "umgesetzt", funktioniert auch soweit ganz gut, ich hab da nur noch zwei Probleme:

1. die Nahtstellen: wie verklebe ich die beiden Halbkugeln miteinander?
2. es scheint so, als ob die Texturen zu den Rändern hin verzerren, ich habe Deinen Code zu Demozwecken mal etwas abgeändert (oberer Teil ohne Funktionen):

BlitzBasic: [AUSKLAPPEN]
;CreateSpherePart by Robert Hierl 12.10.2005 
Graphics3D 800,600,16,2

SetBuffer BackBuffer()

camera=CreateCamera()
light=CreateLight()

CameraZoom camera, 2
PositionEntity camera,0,0,-4
RotateEntity light,90,0,0

tex1=LoadTexture(\"erde_links.bmp\")
RotateTexture tex1,180
tex2=LoadTexture(\"erde_rechts.bmp\")
RotateTexture tex2,180

mesh1 = CreateSpherePart(90, -90, 0, 180,32)
mesh2 = CreateSpherePart(90, -90, 180, 360,32)


pivot=CreatePivot()
EntityParent mesh1,pivot
EntityParent mesh2,pivot

EntityTexture mesh1, tex1
EntityTexture mesh2, tex2

PositionEntity mesh1, 0,0,0
PositionEntity mesh2, 0,0,0

While Not KeyHit(1)

TurnEntity pivot,0,.25,-.1

RenderWorld

Flip
Wend
End


Wir haben hier zwei Halbkugeln, die sich am Nullmeridian (Greenwich) treffen. Ich habe eine 2048x1024 grosse Textur der Erde genommen und diese in zwei gleich grosse Hälften geteilt. Mit den Turnentity-Werten oben merkt man nix, erhöht man diese aber um Faktor 10 sieht das lustig aus, fast wie Kontinentaldrift. Hmm wie soll man das besser erklären, also z.B. Afrika. Wenn das langsam nach links wandert zieht es sich immer mehr in die Länge. Woran könnte das liegen?

Die Texturen poste ich hier nicht, da kann man jede beliebige Grafik nehmen (z.B. diese hier: http://www.space-graphics.com/download.php?1, einfach auf 2048x1024 verkleiner und zerschnipseln)

Wäre doch gelacht wenn man da draus nicht einen superdetailreichen Planeten hinbekäme Smile
 

BIG BUG

BeitragMi, Okt 12, 2005 23:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Du musst bei CreateSphere erst -90 und dann 90 angeben.
Ansonsten erstellst Du einen runden Hohlraum und keine Kugel Smile.

Wegen den Rändern muss ich mal kucken...
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)
 

Krischan

BeitragDo, Okt 13, 2005 7:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Oops, genau das wars Embarassed Hatte mich schon gewundert, dass ich die Textur erst drehen musste weil die auf dem Kopf stand. War spät gestern Shocked Wäre prima, wenn man diese Naht noch loswerden könnte, dann wäre sie perfekt Wink

Ich habe auch noch ein Beispiel mit 8 Texturen à 1024x1024 gemacht, also für eine Gesamttextur von 4096x2048! Beim Durchzählen muss man allerdings aufpassen, ich habe zunächst die vier nördlichen von oben links angefangen ( 1 , 2 , 3 , 4 ) und dann die vier südlichen von unten links angefangen ( 5 , 6 , 7 , 8 ) genommen:

BlitzBasic: [AUSKLAPPEN]
;CreateSpherePart by Robert Hierl 12.10.2005 
Graphics3D 800,600,16,2

SetBuffer BackBuffer()

Dim tex(8),mesh(8)

camera=CreateCamera()
light=CreateLight()

CameraZoom camera, 2
PositionEntity camera,0,0,-4
RotateEntity light,90,0,0

tex(1)=LoadTexture(\"erde05.bmp\")
tex(2)=LoadTexture(\"erde08.bmp\")
tex(3)=LoadTexture(\"erde07.bmp\")
tex(4)=LoadTexture(\"erde06.bmp\")
tex(5)=LoadTexture(\"erde01.bmp\")
tex(6)=LoadTexture(\"erde04.bmp\")
tex(7)=LoadTexture(\"erde03.bmp\")
tex(8)=LoadTexture(\"erde02.bmp\")

pivot=CreatePivot()

For j=0 To 270 Step 90
c=c+1
mesh(c)=CreateSpherePart(-90, 0, j, j+90,32)
EntityParent mesh(c),pivot
EntityTexture mesh(c),tex(c)
PositionEntity mesh(c),0,0,0
Next

For j=0 To 270 Step 90
c=c+1
mesh(c)=CreateSpherePart(0, 90, j, j+90,32)
EntityParent mesh(c),pivot
EntityTexture mesh(c),tex(c)
PositionEntity mesh(c),0,0,0
Next

While Not KeyHit(1)
TurnEntity pivot,0,1,0
RenderWorld
Flip
Wend

End


Das wäre dann das nonplusultra (wenn auch sehr speicherintensiv, als BMP belegen die Texturen 25,1MB!!!) Leider konnte ich auf die schnelle nicht beide Schleifen in eine packen, da muss noch der Schwenk von -90,0 auf 0,90 gemacht werden, so gehts aber auch.
 

BIG BUG

BeitragDo, Okt 13, 2005 21:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Wegen den Rändern hat bei mir die Textureoption 48 = Clamp U+V Abhilfe geschafft:
Code: [AUSKLAPPEN]

LoadTexture("erde_links.jpg", 48)


evtl. müssen hier die Texturen aber quadratisch sein und in einer 2er-Potenz-Auflösung gespeichert sein. z.B. 1024x1024.
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)
 

Krischan

BeitragFr, Okt 14, 2005 7:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, mit quadratischen Texturen funzt das prima - die Ränder sind mit 48 weg! Klasse, Problem gelöst! Jetzt muss ich mir daraus nur noch eine Universalfunktion für grosse Texturen auf Kugeln basteln, die mir die 2/4/8 Bitmaps auf eine Kugel haut.

[gesang]Lobeeeet und preiset Biiig Buuuuug![/gesang]

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group