Cube zu Sphere Transformation

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

 

Krischan

Betreff: Cube zu Sphere Transformation

BeitragMi, Jul 22, 2009 14:47
Antworten mit Zitat
Benutzer-Profile anzeigen
Dies ist eine Demo einer Cube zu Sphere Transformation. Die sechs Seiten (Patches) eines unterteilten Cubes werden so verformt, dass der Cube wie eine Sphere aussieht, und zwar ohne Verzerrung an den Polen - und die Patches passen perfekt zusammen!

Es basiert auf einem Code from Birdie und etwas Mathematik von "Math Proofs".

Man kann es es vielseitig verwenden, für eine sehr runde Sphere oder sogar einen prozeduralen Planeten mit fraktaler Unterteilung (ich weiss zwar nicht wie, aber Infinity verwendet diese Methode). Man kann damit auch sehr detaillierte Spheres durch Ändern der "detail" Variable erstellen.

Wenn einer weiss, wie man das mit den fraktalen Planeten hierauf anwenden kann als her damit!

Screenshot:
user posted image

Code: [AUSKLAPPEN]
AppTitle "Cube to Sphere Transformation"

Graphics3D 800,600,32,2

; detail of the cube/sphere
detail=10

Global transform$[1] : transform[0]="Sphere" : transform[1]="Cube"

pivot=CreatePivot()

; Camera
cam=CreateCamera(pivot)
CameraRange cam,0.01,1000
PositionEntity cam,0,0,-3

; create segmented Cube
cube=CreateSegCube(detail)
EntityColor cube,0,255,0
EntityFX cube,1+16

MoveMouse 400,300

WireFrame 1

While Not KeyHit(1)
   
   ; movement / rotating
   mxs#=MouseXSpeed()
   mys#=MouseYSpeed()
   TurnEntity cube,0,mxs,0
   TurnEntity pivot,mys,0,0
   MoveEntity cam,0,0,(KeyDown(200)-KeyDown(208))*1.0/60
   
   ; W = Wireframe
   If KeyHit(17) Then wf=1-wf : WireFrame 1-wf
   
   ; SPACE = transform
   If KeyHit(57) Then
      
      switch=1-switch
      
      If switch=1 Then
         
         ; transforms cube to sphere
         Cube2Sphere(cube)
         
      Else
         
         ; creates a new cube
         FreeEntity cube
         cube=CreateSegCube(detail)
         EntityColor cube,0,255,0
         EntityFX cube,1+16
         
         
      EndIf
      
   EndIf
   
   RenderWorld
   
   Text 0,0,TrisRendered()+" Tris"
   Text 0,15,"W for Wireframe"
   Text 0,30,"SPACE for "+transform[switch]
   
   Flip
   
Wend

End

; transform a cube patch to sphere patch
Function Cube2Sphere(mesh%)
   
   Local s%,surf%,v%
   Local vx#,vy#,vz#
   
   For s=1 To CountSurfaces(mesh)
      
      surf=GetSurface(mesh,s)
      
      For v=0 To CountVertices(surf)-1
         
         vx=VertexX(surf,v)
         vy=VertexY(surf,v)
         vz=VertexZ(surf,v)
         
         VertexCoords surf,v,SphericalX(vx,vy,vz)*1.333333,SphericalY(vx,vy,vz)*1.333333,SphericalZ(vx,vy,vz)*1.333333
         
      Next
      
   Next
   
End Function

; calculate spherical X
Function SphericalX#(x#,y#,z#)
   
   Return x*Sqr(1.0-y*y*0.5-z*z*0.5+y*y*z*z*1.0/3)
   
End Function

; calculate spherical Y
Function SphericalY#(x#,y#,z#)

   Return y*Sqr(1.0-z*z*0.5-x*x*0.5+z*z*x*x*1.0/3)

End Function

; calculate spherical Z
Function SphericalZ#(x#,y#,z#)
   
   Return z*Sqr(1.0-x*x*0.5-y*y*0.5+x*x*y*y*1.0/3)
   
End Function

; creates a segmented cube
Function CreateSegCube(segs=1,parent=0)
   
   Local side%,surf%
   Local stx#,sty#,stp#,y#
   Local a%,x#,v#,b%,u#
   Local v0%,v1%,v2%,v3%
   Local mesh%=CreateMesh(parent)
   
   ; sides
   For side=0 To 3
      
      surf=CreateSurface( mesh )
      stx=-.5
      sty=stx
      stp=Float(1)/Float(segs)
      y=sty
      
      For a=0 To segs
         
         x=stx
         v=a/Float(segs)
         
         For b=0 To segs
            
            u=b/Float(segs)
            AddVertex(surf,x,y,0.5,u,v)
            x=x+stp
            
         Next
         
         y=y+stp
         
      Next
      
      For a=0 To segs-1
         
         For b=0 To segs-1
            
            v0=a*(segs+1)+b:v1=v0+1
            v2=(a+1)*(segs+1)+b+1:v3=v2-1
            AddTriangle( surf,v0,v1,v2 )
            AddTriangle( surf,v0,v2,v3 )
            
         Next
         
      Next
      
      RotateMesh mesh,0,90,0
      
   Next
   
   ;top and bottom
   RotateMesh mesh,0,90,90
   
   For side=0 To 1
      
      surf=CreateSurface( mesh )
      stx#=-.5
      sty#=stx
      stp#=Float(1)/Float(segs)
      y#=sty
      
      For a=0 To segs
         x#=stx
         v#=a/Float(segs)
         For b=0 To segs
            u#=b/Float(segs)
            AddVertex(surf,x,y,0.5,u,v)
            x=x+stp
         Next
         y=y+stp
      Next
      
      For a=0 To segs-1
         For b=0 To segs-1
            v0=a*(segs+1)+b:v1=v0+1
            v2=(a+1)*(segs+1)+b+1:v3=v2-1
            AddTriangle( surf,v0,v1,v2 )
            AddTriangle( surf,v0,v2,v3 )
         Next
      Next
      
      RotateMesh mesh,180,0,0
      
   Next
   
   ; scale uniform to -1 to +1 space in X/Y/Z dimensions
   FitMesh mesh,-1,-1,-1,2,2,2,1
   
   Return mesh
   
End Function

Triton

BeitragDo, Jul 23, 2009 16:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab mich auch schonmal mit sowas ähnlichem befasst und versucht eine Methode zu finden, eine
Kugel verzerrungsfrei aufzufalten. Also quasi der umgekehrte Weg. Bin dann letztendlich bei der Geosphere gelandet, die ja ein unterteiltes Tetraeder darstellt quasi.

Die könnte man zwar verzerrungsfrei Auffalten, die UV-Map wäre dann aber nicht quadratisch, praktisch, gut, wie hier Smile

Jedenfalls eine elegante Lösung. Sehr schön.
Coding: silizium-net.de | Portfolio: Triton.ch.vu
 

Krischan

BeitragDo, Jul 23, 2009 17:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Achso wichtig ist noch, dass der Cube innerhalb der X/Y/Z-Koordinaten -1 bis 1 liegt, sonst klappt es nicht.
 

Krischan

BeitragFr, Jul 24, 2009 10:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Hmm zum Thema "Kugel verzerrungsfrei auffalten" kann ich noch mit einer Formel aus dem Buch "Texturing and Modeling - A procedural approach" dienen, allerdings habe ich Probleme, diese korrekt zu lesen. Es handelt sich hierbei um das "equalangular mapping":

U=(TAN^-1(X,Y)) / (2*Pi)
V=(SIN^-1(Z/SQR(x^2+y^2+z^2) / (2*Pi))+0.5

Originalseite (sofern das klappt): Auszug bei Google Books S. 198

Das sollte die korrekten UV-Koordinaten anhand der XYZ Koordinaten liefern. Ich bin mir jetzt aber nicht sicher, wie das im Code aussehen muss, also z.B. das TAN^-1(x,y)???

Umgekehrt sieht es wie folgt aus, das berechnet aus einer 2D-Karte die 3D Koordinaten auf der Kugel:

X = COS((V-0.5)*2*Pi)*SIN(U*2*Pi)
Y = COS((V-0.5)*2*Pi)*COS(U*2*Pi)
Z = SIN((V-0.5)*2*Pi)

DaysShadow

BeitragFr, Jul 24, 2009 11:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Edit: Hm, args, stimmt da war was....

MfG DaysShadow
Blessed is the mind too small for doubt
  • Zuletzt bearbeitet von DaysShadow am Fr, Jul 24, 2009 11:45, insgesamt 3-mal bearbeitet

Holzchopf

Meisterpacker

BeitragFr, Jul 24, 2009 11:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Tan^-1 ist normalerweise der Arcustangenz (und so wie die Parameter dort stehen, also Komma getrennt, würd ich mal denken, dass du in Blitz dafür einfach ATan2 nehmen könntest, müsstest wohl nur die Parameter tauschen).
Und sin^-1 wäre dann wohl der Arcussinus, ASin.

mfG
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group