November 25, 2020, 07:57:11 AM

Author Topic: [bb] 3D Single Surface Spiral Galaxy by Krischan [ 1+ years ago ]  (Read 1019 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : 3D Single Surface Spiral Galaxy
Author : Krischan
Posted : 1+ years ago

Description : I've been playing around with single surface techniques and this is the result. A nice procedural galaxy in 3D - "only" 24.000 stars visible but you can increase the number to the vertex/surface limit of a mesh, if your CPU/GFX card can handle it. The galaxy itself is being generated using a customized <a href="http://en.wikipedia.org/wiki/Archimedean_spiral" target="_blank">archimedean spiral[/url] algorithm. You can play around with the constant parameters, by default it looks Andromeda-like, for example: our own Milkyway has only two arms. The number of stars spread over the whole galaxy, so even lower numbers show the shape (but with less detail).

The single surface technique used here creates virtual "quads" with 4 vertices each and uses two tformvector commands to align the vertices representing a virtual quad to the cam. There is only one entity (the galaxy) with one or more surfaces (max. 32000 vertices=32000/4=8000 stars/quads per surface). The star texture is generated procedurally on the fly.

Steering: Arrows and mouse, but you won't notice any movement until you press one (fast) or both (very fast) mousebuttons. If you encounter a star field you should release both buttons and use only one button for faster travel to "visit" single stars until a certain distance.



Code :
Code: BlitzBasic
  1. Graphics3D 800,600,32,2
  2.  
  3. SetBuffer BackBuffer()
  4.  
  5. Const TurnSpeed#    = 4.000        ; cam turn speed
  6. Const RollSpeed#    = 0.500        ; cam roll speed
  7. Const CameraSpeed#  = 0.005        ; cam move speed
  8. Const Stars%        = 24000        ; number of stars
  9. Const Spiralarms%   = 4            ; number of spiral arms
  10. Const Spread#       = 20.0         ; star spread
  11. Const Rotation#     = 4.0          ; how many spiral rotations
  12. Const Range#        = 100.0        ; milkyway radius
  13.  
  14. Global WIDTH%=GraphicsWidth()
  15. Global HEIGHT%=GraphicsHeight()
  16. Global TIMER%=CreateTimer(60)
  17. Global Scale#=WIDTH/3.0            ; star scale
  18.  
  19. Global total%,vis%
  20.  
  21. Local cam%,galaxy%,tex%
  22.  
  23. Type quad
  24.        
  25.         Field surf%
  26.         Field x#,y#,z#
  27.         Field v%
  28.         Field scale#
  29.         Field r%,g%,b%
  30.        
  31. End Type
  32.  
  33. ; init galaxy
  34. galaxy=InitGalaxy(Stars,Spiralarms,Spread,Rotation,Range)
  35. EntityFX galaxy,1+2
  36. EntityBlend galaxy,3
  37. tex=CreateSunTexture(256,128,128,128)
  38. TextureBlend tex,3
  39. EntityTexture galaxy,tex
  40.  
  41. ; init camera
  42. cam=CreateCamera()
  43. CameraRange cam,0.1,1000
  44. PositionEntity cam,0,90,150
  45. PointEntity cam,galaxy
  46.  
  47. MoveMouse WIDTH/2,HEIGHT/2
  48.  
  49. ; main loop
  50. While Not KeyHit(1)
  51.        
  52.         Local ms%,me%
  53.        
  54.         Movement(cam)
  55.        
  56.         ms=MilliSecs()
  57.         UpdateGalaxy(cam,Scale)
  58.         me=MilliSecs()-ms
  59.        
  60.         RenderWorld
  61.        
  62.         WaitTimer TIMER
  63.        
  64.         AppTitle vis+" Stars visible ["+total+" Stars total] "+me+"ms"
  65.        
  66.         Flip 0
  67.        
  68. Wend
  69.  
  70. End
  71.  
  72. ; update quads in single surface mesh
  73. Function UpdateGalaxy(cam%,scale#=256.0)
  74.        
  75.         Local cx#=EntityX(cam)
  76.         Local cy#=EntityY(cam)
  77.         Local cz#=EntityZ(cam)
  78.        
  79.         Local q.quad,d#,s#
  80.        
  81.         total=0
  82.         vis=0
  83.        
  84.         For q.quad = Each quad
  85.                
  86.                 ; check if star is visible
  87.                 TFormPoint qx,qy,qz,0,cam
  88.                
  89.                 ; in front of cam?
  90.                 If TFormedZ()>0 Then
  91.                
  92.                         ; adaptive size
  93.                         d#=Distance3D(qx,qy,qz,cx,cy,cz)
  94.                         s#=(qscale/d)+(d/scale)
  95.                         If s<d/scale Then s=d/scale
  96.                
  97.                         ; align single surface quads to cam
  98.                         UpdateQuad(q.quad,s,cam)
  99.                        
  100.                         vis=vis+1
  101.                
  102.                 EndIf
  103.                
  104.                 total=total+1
  105.                
  106.         Next
  107.        
  108. End Function
  109.  
  110. ; create galaxy
  111. Function InitGalaxy%(stars%=10000,arms%=4,spread#=40.0,rot#=2.0,range#=100.0)
  112.        
  113.         Local mesh%=CreateMesh()
  114.         Local surf%=CreateSurface(mesh)
  115.         Local q.quad
  116.         Local angle#,dist#,turb#
  117.         Local i%,col#,multi#,lum#,bulge%,counter%
  118.        
  119.         For i=1 To stars
  120.                
  121.                 q.quad = New quad
  122.                
  123.                 ; color
  124.                 col=Rnd(1)
  125.                 If col>0.90 And col<=1.00 Then q
  126. =255 : qg=  0 : q=  0
  127.                 If col>0.70 And col<=0.90 Then q
  128. =255 : qg=255 : q=  0
  129.                 If col>0.50 And col<=0.70 Then q
  130. =  0 : qg=  0 : q=255
  131.                 If col>0.00 And col<=0.50 Then q
  132. =255 : qg=255 : q=255
  133.                
  134.                 ; angle
  135.                 angle=Int(Floor(i*1.0/(stars/arms)))*(360.0/arms)
  136.                
  137.                 ; center / arm relation
  138.                 If Rnd(1)>0.5 Then multi=Rnd(0.1,1) Else multi=Rnd(1,2)
  139.                
  140.                 ; distance and turbulence
  141.                 dist=Rnd(0,range)*Rnd(1,Rnd(Rnd(multi)))
  142.                 turb=Rnd(0,Rnd(spread)) : If Rnd(1)>0.5 Then turb=-turb
  143.                
  144.                 ; more red/yellow stars in bulge
  145.                 lum=Rnd(1)
  146.                 If dist<range/2*lum Then
  147.                        
  148.                         If lum>0.75 Then
  149.                                
  150.                                 q
  151. =255 : qg=0 : q=0              ; red stars
  152.                                
  153.                         Else If lum>0.5 Then
  154.                                
  155.                                 q
  156. =255 : qg=255 : q=0    ; yellow stars
  157.                                
  158.                         EndIf
  159.                        
  160.                 Else
  161.                        
  162.                         If lum>0.75 Then
  163.                                
  164.                                 q
  165. =0 : qg=0 : q=255              ; blue stars
  166.                                
  167.                         Else If lum>0.5 Then
  168.                                
  169.                                 q
  170. =255 : qg=255 : q=255  ; white stars
  171.                                
  172.                         EndIf
  173.                        
  174.                 EndIf
  175.                
  176.                 ; star position x/z
  177.                 qx=dist*Cos(angle+(dist*rot))+Rnd(Rnd(Rnd(-spread)),Rnd(Rnd(spread)))
  178.                 qz=dist*Sin(angle+(dist*rot))+Rnd(Rnd(Rnd(-spread)),Rnd(Rnd(spread)))
  179.                
  180.                 ; star position y
  181.                 bulge=Normalize(Distance2D(qx,qz,0,0),0,range/2.0,0,180)/2.0
  182.                 If bulge>90 Then bulge=90
  183.                 qy=(Cos(bulge)*Rnd(Rnd(-spread),Rnd(spread))/2.0)+(turb/10.0)
  184.                
  185.                 ; scale
  186.                 qscale=Rnd(0.01,Rnd(0.02,Rnd(0.04,0.08)))
  187.                
  188.                 ; create new surface if too many vertices
  189.                 If counter+4>32000 Then surf=CreateSurface(mesh) : counter=0
  190.                 qsurf=surf
  191.                
  192.                 ; add vertices
  193.                 qv=AddVertex(qsurf,0,0,0,0,0)
  194.                 AddVertex(qsurf,0,0,0,1,0)
  195.                 AddVertex(qsurf,0,0,0,1,1)
  196.                 AddVertex(qsurf,0,0,0,0,1)
  197.                
  198.                 ; color vertices
  199.                 VertexColor qsurf,qv,q
  200. ,qg,q
  201.                 VertexColor qsurf,qv+1,q
  202. ,qg,q
  203.                 VertexColor qsurf,qv+2,q
  204. ,qg,q
  205.                 VertexColor qsurf,qv+3,q
  206. ,qg,q
  207.                
  208.                 ; add triangles
  209.                 AddTriangle(qsurf,qv,qv+1,qv+2)
  210.                 AddTriangle(qsurf,qv,qv+2,qv+3)
  211.                
  212.                 ; vertex counter
  213.                 counter=counter+4
  214.                
  215.         Next
  216.        
  217.         Return mesh
  218.        
  219. End Function
  220.  
  221. ; align single surface quad to cam
  222. Function UpdateQuad(q.quad,s#,target%)
  223.        
  224.         Local x1#,y1#,z1#,x2#,y2#,z2#
  225.        
  226.         TFormVector -s,0,0,target,0
  227.         x1=TFormedX()
  228.         y1=TFormedY()
  229.         z1=TFormedZ()
  230.        
  231.         TFormVector 0,-s,0,target,0
  232.         x2=TFormedX()
  233.         y2=TFormedY()
  234.         z2=TFormedZ()
  235.        
  236.         VertexCoords qsurf,qv+0,qx-x1-x2,qy-y1-y2,qz-z1-z2
  237.         VertexCoords qsurf,qv+1,qx-x1+x2,qy-y1+y2,qz-z1+z2
  238.         VertexCoords qsurf,qv+2,qx+x1+x2,qy+y1+y2,qz+z1+z2
  239.         VertexCoords qsurf,qv+3,qx+x1-x2,qy+y1-y2,qz+z1-z2
  240.        
  241. End Function
  242.  
  243. ; calculate 2D Distance
  244. Function Distance2D#(x1#,y1#,x2#,y2#)
  245.        
  246.         Local x#=x1-x2
  247.         Local y#=y1-y2
  248.        
  249.         Return Sqr((x*x)+(y*y))
  250.        
  251. End Function
  252.  
  253. ; calucate 3D Distance
  254. Function Distance3D#(x1#,y1#,z1#,x2#,y2#,z2#)
  255.        
  256.         Local x#=x1-x2
  257.         Local y#=y1-y2
  258.         Local z#=z1-z2
  259.        
  260.         Return Sqr((x*x)+(y*y)+(z*z))
  261.        
  262. End Function
  263.  
  264. ; normalize a value
  265. Function Normalize#(value#=128.0,vmin#=0.0,vmax#=255.0,nmin#=0.0,nmax#=1.0)
  266.    
  267.     Return ((value#-vmin#)/(vmax#-vmin#))*(nmax#-nmin#)+nmin#
  268.    
  269. End Function
  270.  
  271. ; camera movement
  272. Function Movement(cam%,sensitivity#=1.0)
  273.    
  274.     Local roll#,cz#,tx#,ty#,multi%=1
  275.    
  276.     ; arrows = move / LMB = Turbo / RMB = Lightspeed / LMB+RMB = incredible speed
  277.     cz=(KeyDown(200)-KeyDown(208))*CameraSpeed
  278.         roll=(KeyDown(203)-KeyDown(205))*RollSpeed
  279.     If MouseDown(1) Then multi=10
  280.         If MouseDown(2) Then multi=multi*10
  281.    
  282.     tx=Normalize(MouseX(),0,WIDTH , 1,-1)
  283.     ty=Normalize(MouseY(),0,HEIGHT,-1, 1)
  284.    
  285.     If ty<0 Then ty=(Abs(ty)^sensitivity)*-1 Else ty=ty^sensitivity
  286.     If tx<0 Then tx=(Abs(tx)^sensitivity)*-1 Else tx=tx^sensitivity
  287.    
  288.     TurnEntity cam,ty*TurnSpeed,tx*TurnSpeed,roll*TurnSpeed
  289.     MoveEntity cam,0,0,cz*multi
  290.        
  291. End Function
  292.  
  293. ; create a stunning sun texture
  294. Function CreateSunTexture(size%=512,r%=255,g%=255,b%=255)
  295.        
  296.         Local tex%=CreateTexture(size,size,3)
  297.         Local tb%=TextureBuffer(tex)
  298.        
  299.         Local i#,j%,col%,rgb%
  300.         Local x%,y%,xx%,yy%
  301.         Local a%
  302.        
  303.         LockBuffer tb
  304.        
  305.         For j=0 To (size/2)-1
  306.                
  307.                 col=255-Normalize(j,0,(size/2.0)-1,0,255)
  308.                 If col>255 Then col=255
  309.                 rgb=col*$1000000+col*$10000+col*$100+col
  310.                
  311.                 For i=0 To 360 Step 0.05
  312.                        
  313.                         WritePixelFast (size/2)+(Sin(i)*j),(size/2)+(Cos(i)*j),rgb,tb
  314.                        
  315.                 Next
  316.                
  317.         Next
  318.        
  319.         UnlockBuffer tb
  320.        
  321.         ; temp camera
  322.         Local tempcam%=CreateCamera()
  323.         CameraRange tempcam,1,WIDTH*2
  324.        
  325.         ; temp pivot
  326.         Local tempsun%=CreatePivot()
  327.        
  328.         ; create 4 layers
  329.         CreateQuad(tempsun,size/4.0,tex,3,1+8+16,r*1.00,g*1.00,b*1.00,1.00)
  330.         CreateQuad(tempsun,size/1.5,tex,3,1+8+16,r*1.00,g*1.00,b*1.00,1.00)
  331.         CreateQuad(tempsun,size/1.2,tex,3,1+8+16,r*0.75,g*0.75,b*0.50,0.75)
  332.         CreateQuad(tempsun,size/1.0,tex,3,1+8+16,r*0.50,g*0.50,b*0.50,0.50)
  333.        
  334.         PositionEntity tempsun,0,0,WIDTH
  335.    
  336.         ; render it
  337.     RenderWorld
  338.        
  339.         ; delete pivot
  340.         FreeEntity tempsun
  341.        
  342.         LockBuffer BackBuffer()
  343.         LockBuffer tb
  344.        
  345.         ; grab image
  346.         For x=0 To size-1
  347.                
  348.                 For y=0 To size-1
  349.                        
  350.                         xx=(WIDTH/2)-(size/2)+x
  351.                         yy=(HEIGHT/2)-(size/2)+y
  352.                        
  353.                         rgb=ReadPixelFast(xx,yy,BackBuffer())
  354.                        
  355.                         r=(rgb And $ff0000)/$10000
  356.                         g=(rgb And $ff00)/$100
  357.                         b=(rgb And $ff)
  358.                         a=255
  359.                        
  360.                         ; alpha
  361.                         If (r+g+b)/3 < 32 Then a=Normalize((r+g+b)/3,0,32,0,255)
  362.                        
  363.                         ; rgb
  364.                         rgb=(r+g+b)/3*$1000000+r*$10000+g*$100+b
  365.                        
  366.                         WritePixelFast x,y,rgb,tb
  367.                        
  368.                 Next
  369.                
  370.         Next
  371.        
  372.         UnlockBuffer tb
  373.         UnlockBuffer BackBuffer()
  374.        
  375.         RenderWorld
  376.        
  377.         ; delete temp cam
  378.         FreeEntity tempcam
  379.        
  380.         Return tex
  381.        
  382. End Function
  383.  
  384. ; advanced quad creation
  385. Function CreateQuad(parent%=False,scale#=1.0,tex%=False,blend%=False,fx%=False,r%=255,g%=255,b%=255,a#=1.0)
  386.        
  387.         Local mesh%=CreateMesh()
  388.         Local surf%=CreateSurface(mesh)
  389.        
  390.         Local v0%=AddVertex(surf, 1, 1,0,0,0)
  391.         Local v1%=AddVertex(surf,-1, 1,0,1,0)
  392.         Local v2%=AddVertex(surf,-1,-1,0,1,1)
  393.         Local v3%=AddVertex(surf, 1,-1,0,0,1)
  394.        
  395.         AddTriangle surf,v0,v1,v2
  396.         AddTriangle surf,v0,v2,v3
  397.        
  398.         If parent Then EntityParent mesh,parent
  399.         If fx Then EntityFX mesh,fx
  400.         If tex Then EntityTexture mesh,tex
  401.         If blend Then EntityBlend mesh,blend
  402.        
  403.         EntityColor mesh,r,g,b
  404.         EntityAlpha mesh,a
  405.        
  406.         VertexColor surf,v0,r,g,b,a
  407.         VertexColor surf,v1,r,g,b,a
  408.         VertexColor surf,v2,r,g,b,a
  409.         VertexColor surf,v3,r,g,b,a
  410.        
  411.         ScaleEntity mesh,scale,scale,scale
  412.        
  413.         Return mesh
  414.        
  415. End Function


Comments :


MCP(Posted 1+ years ago)

 Another great entry for the code archives Krischan. Well done! :)


Krischan(Posted 1+ years ago)

 Well I am unhappy with it. I tried to create billions of stars... 24000 is ridiculous ;-)


Krischan(Posted 1+ years ago)

 Well, at least with some quick and dirty optimizations it is now possible to show at least 240000 stars with a decent FPS rate here. Looks nicer now:
Code: [Select]
Graphics3D 800,600,32,2

SetBuffer BackBuffer()

Const TurnSpeed#    = 4.000        ; cam turn speed
Const RollSpeed#    = 0.500        ; cam roll speed
Const CameraSpeed#  = 0.005        ; cam move speed
Const Stars%        = 240000       ; number of stars
Const Spiralarms%   = 4            ; number of spiral arms
Const Spread#       = 20.0         ; star spread
Const Rotation#     = 4.0          ; how many spiral rotations
Const Range#        = 100.0        ; milkyway radius

Global WIDTH%=GraphicsWidth()
Global HEIGHT%=GraphicsHeight()
Global TIMER%=CreateTimer(60)
Global Scale#=WIDTH/3.0            ; star scale

Global meshes%[256]

Global total%,vis%

Local cam%,galaxy%,tex%

Type quad
   
    Field surf%
    Field x#,y#,z#
    Field v%
    Field scale#
    Field r%,g%,b%
    Field lastdist#
   
End Type

tex=CreateSunTexture(256,128,128,128)
TextureBlend tex,3

; init galaxy
galaxy=InitGalaxy(Stars,Spiralarms,Spread,Rotation,Range)

For i=0 To galaxy
   
    If meshes[i]>0 Then
   
    EntityFX meshes[i],1+2
    EntityBlend meshes[i],3
    EntityTexture meshes[i],tex
   
EndIf
   
Next

; init camera
cam=CreateCamera()
CameraRange cam,0.1,1000
PositionEntity cam,0,90,150
PointEntity cam,meshes[0]

; update galaxy once
Local cx#=EntityX(cam)
Local cy#=EntityY(cam)
Local cz#=EntityZ(cam)
Local q.quad,d#,s#
For q.quad = Each quad
    ; adaptive size
    d=Distance3D(qx,qy,qz,cx,cy,cz)
    s=(qscale/d)+(d/Scale)
    If s<d/Scale Then s=d/Scale
    ; align single surface quads to cam
    UpdateQuad(q.quad,s,cam)
    qlastdist=d
Next
   
MoveMouse WIDTH/2,HEIGHT/2

; main loop
While Not KeyHit(1)
   
    Local ms%,me%
   
    Movement(cam)
   
    ms=MilliSecs()
    i=i+1 : If i>=10 Then i=0
    UpdateGalaxy(cam,Scale,i)
    me=MilliSecs()-ms
       
    RenderWorld
   
    WaitTimer TIMER
   
    AppTitle vis+" Stars updated ["+total+" Stars total] "+me+"ms"
   
    Flip 0
   
Wend

End

; update quads in single surface mesh
Function UpdateGalaxy(cam%,scale#=256.0,part%)
   
    Local cx#=EntityX(cam)
    Local cy#=EntityY(cam)
    Local cz#=EntityZ(cam)
   
    Local q.quad,d#,s#,steps%,i%,start%,ende%
   
    total=0
    vis=0
   
    steps=Stars/10
   
    For q.quad = Each quad
       
        ; set start and end
        start=part*steps
        ende=(part+1)*steps
       
        ; check only current part or nearby stars
        If i>=start And i<ende Or qlastdist<5 Then
           
            TFormPoint qx,qy,qz,0,cam
           
            ; in front of cam?
            If TFormedZ()>0 Then
       
                ; adaptive size
                d#=Distance3D(qx,qy,qz,cx,cy,cz)
                s#=(qscale/d)+(d/scale)
                If s<d/scale Then s=d/scale
               
                ; store last distance calculation
                qlastdist=d
           
                ; align single surface quads to cam
                UpdateQuad(q.quad,s,cam)
       
                vis=vis+1
               
            EndIf
       
        EndIf
       
        i=i+1
       
        total=total+1
       
    Next
   
End Function

; create galaxy
Function InitGalaxy%(stars%=10000,arms%=4,spread#=40.0,rot#=2.0,range#=100.0)
   
    Local mesh%=CreateMesh()
    Local surf%=CreateSurface(mesh)
    Local q.quad
    Local angle#,dist#,turb#
    Local i%,col#,multi#,lum#,bulge%,counter%,surfs%=1,m%=0
   
    meshes[0]=mesh
   
    For i=1 To stars
       
        q.quad = New quad
       
        ; color
        col=Rnd(1)
        If col>0.90 And col<=1.00 Then q=255 : qg=  0 : q=  0
        If col>0.70 And col<=0.90 Then q=255 : qg=255 : q=  0
        If col>0.50 And col<=0.70 Then q=  0 : qg=  0 : q=255
        If col>0.00 And col<=0.50 Then q=255 : qg=255 : q=255
       
        ; angle
        angle=Int(Floor(i*1.0/(stars/arms)))*(360.0/arms)
       
        ; center / arm relation
        If Rnd(1)>0.5 Then multi=Rnd(0.1,1) Else multi=Rnd(1,2)
       
        ; distance and turbulence
        dist=Rnd(0,range)*Rnd(1,Rnd(Rnd(multi)))
        turb=Rnd(0,Rnd(spread)) : If Rnd(1)>0.5 Then turb=-turb
       
        ; more red/yellow stars in bulge
        lum=Rnd(1)
        If dist<range/2*lum Then
           
            If lum>0.75 Then
               
                q=255 : qg=0 : q=0        ; red stars
               
            Else If lum>0.5 Then
               
                q=255 : qg=255 : q=0    ; yellow stars
               
            EndIf
           
        Else
           
            If lum>0.75 Then
               
                q=0 : qg=0 : q=255        ; blue stars
               
            Else If lum>0.5 Then
               
                q=255 : qg=255 : q=255    ; white stars
               
            EndIf
           
        EndIf
       
        ; star position x/z
        qx=dist*Cos(angle+(dist*rot))+Rnd(Rnd(Rnd(-spread)),Rnd(Rnd(spread)))
        qz=dist*Sin(angle+(dist*rot))+Rnd(Rnd(Rnd(-spread)),Rnd(Rnd(spread)))
       
        ; star position y
        bulge=Normalize(Distance2D(qx,qz,0,0),0,range/2.0,0,180)/2.0
        If bulge>90 Then bulge=90
        qy=(Cos(bulge)*Rnd(Rnd(-spread),Rnd(spread))/2.0)+(turb/10.0)
       
        ; scale
        qscale=Rnd(0.01,Rnd(0.02,Rnd(0.04,0.08)))
       
        ; create new surface if too many vertices
        If counter+4>32000 Then
           
            If surfs+1>3 Then
                m=m+1
                mesh=CreateMesh()
                meshes[m]=mesh
                surfs=0
            EndIf
               
            surf=CreateSurface(mesh)
            counter=0
            surfs=surfs+1
           
        EndIf
       
        qsurf=surf
       
        ; add vertices
        qv=AddVertex(qsurf,0,0,0,0,0)
        AddVertex(qsurf,0,0,0,1,0)
        AddVertex(qsurf,0,0,0,1,1)
        AddVertex(qsurf,0,0,0,0,1)
       
        ; color vertices
        VertexColor qsurf,qv,q,qg,q
        VertexColor qsurf,qv+1,q,qg,q
        VertexColor qsurf,qv+2,q,qg,q
        VertexColor qsurf,qv+3,q,qg,q
       
        ; add triangles
        AddTriangle(qsurf,qv,qv+1,qv+2)
        AddTriangle(qsurf,qv,qv+2,qv+3)
       
        ; vertex counter
        counter=counter+4
       
    Next
   
    DebugLog m
   
    Return m
   
End Function

; align single surface quad to cam
Function UpdateQuad(q.quad,s#,target%)
   
    Local x1#,y1#,z1#,x2#,y2#,z2#
   
    TFormVector -s,0,0,target,0
    x1=TFormedX()
    y1=TFormedY()
    z1=TFormedZ()
   
    TFormVector 0,-s,0,target,0
    x2=TFormedX()
    y2=TFormedY()
    z2=TFormedZ()
   
    VertexCoords qsurf,qv+0,qx-x1-x2,qy-y1-y2,qz-z1-z2
    VertexCoords qsurf,qv+1,qx-x1+x2,qy-y1+y2,qz-z1+z2
    VertexCoords qsurf,qv+2,qx+x1+x2,qy+y1+y2,qz+z1+z2
    VertexCoords qsurf,qv+3,qx+x1-x2,qy+y1-y2,qz+z1-z2
   
End Function

; calculate 2D Distance
Function Distance2D#(x1#,y1#,x2#,y2#)
   
    Local x#=x1-x2
    Local y#=y1-y2
   
    Return Sqr((x*x)+(y*y))
   
End Function

; calucate 3D Distance
Function Distance3D#(x1#,y1#,z1#,x2#,y2#,z2#)
   
    Local x#=x1-x2
    Local y#=y1-y2
    Local z#=z1-z2
   
    Return Sqr((x*x)+(y*y)+(z*z))
   
End Function

; normalize a value
Function Normalize#(value#=128.0,vmin#=0.0,vmax#=255.0,nmin#=0.0,nmax#=1.0)
   
    Return ((value#-vmin#)/(vmax#-vmin#))*(nmax#-nmin#)+nmin#
   
End Function

; camera movement
Function Movement(cam%,sensitivity#=1.0)
   
    Local roll#,cz#,tx#,ty#,multi%=1
   
    ; arrows = move / LMB = Turbo / RMB = Lightspeed / LMB+RMB = incredible speed
    cz=(KeyDown(200)-KeyDown(208))*CameraSpeed
    roll=(KeyDown(203)-KeyDown(205))*RollSpeed
    If MouseDown(1) Then multi=10
    If MouseDown(2) Then multi=multi*10
   
    tx=Normalize(MouseX(),0,WIDTH , 1,-1)
    ty=Normalize(MouseY(),0,HEIGHT,-1, 1)
   
    If ty<0 Then ty=(Abs(ty)^sensitivity)*-1 Else ty=ty^sensitivity
    If tx<0 Then tx=(Abs(tx)^sensitivity)*-1 Else tx=tx^sensitivity
   
    TurnEntity cam,ty*TurnSpeed,tx*TurnSpeed,roll*TurnSpeed
    MoveEntity cam,0,0,cz*multi
   
End Function

; create a stunning sun texture
Function CreateSunTexture(size%=512,r%=255,g%=255,b%=255)
   
    Local tex%=CreateTexture(size,size,3)
    Local tb%=TextureBuffer(tex)
   
    Local i#,j%,col%,rgb%
    Local x%,y%,xx%,yy%
    Local a%
   
    LockBuffer tb
   
    For j=0 To (size/2)-1
       
        col=255-Normalize(j,0,(size/2.0)-1,0,255)
        If col>255 Then col=255
        rgb=col*$1000000+col*$10000+col*$100+col
       
        For i=0 To 360 Step 0.05
           
            WritePixelFast (size/2)+(Sin(i)*j),(size/2)+(Cos(i)*j),rgb,tb
           
        Next
       
    Next
   
    UnlockBuffer tb
   
    ; temp camera
    Local tempcam%=CreateCamera()
    CameraRange tempcam,1,WIDTH*2
   
    ; temp pivot
    Local tempsun%=CreatePivot()
   
    ; create 4 layers
    CreateQuad(tempsun,size/4.0,tex,3,1+8+16,r*1.00,g*1.00,b*1.00,1.00)
    CreateQuad(tempsun,size/1.5,tex,3,1+8+16,r*1.00,g*1.00,b*1.00,1.00)
    CreateQuad(tempsun,size/1.2,tex,3,1+8+16,r*0.75,g*0.75,b*0.50,0.75)
    CreateQuad(tempsun,size/1.0,tex,3,1+8+16,r*0.50,g*0.50,b*0.50,0.50)
   
    PositionEntity tempsun,0,0,WIDTH
   
    ; render it
    RenderWorld
   
    ; delete pivot
    FreeEntity tempsun
   
    LockBuffer BackBuffer()
    LockBuffer tb
   
    ; grab image
    For x=0 To size-1
       
        For y=0 To size-1
           
            xx=(WIDTH/2)-(size/2)+x
            yy=(HEIGHT/2)-(size/2)+y
           
            rgb=ReadPixelFast(xx,yy,BackBuffer())
           
            r=(rgb And $ff0000)/$10000
            g=(rgb And $ff00)/$100
            b=(rgb And $ff)
            a=255
           
            ; alpha
            If (r+g+b)/3 < 32 Then a=Normalize((r+g+b)/3,0,32,0,255)
           
            ; rgb
            rgb=(r+g+b)/3*$1000000+r*$10000+g*$100+b
           
            WritePixelFast x,y,rgb,tb
           
        Next
       
    Next
   
    UnlockBuffer tb
    UnlockBuffer BackBuffer()
   
    RenderWorld
   
    ; delete temp cam
    FreeEntity tempcam
   
    Return tex
   
End Function

; advanced quad creation
Function CreateQuad(parent%=False,scale#=1.0,tex%=False,blend%=False,fx%=False,r%=255,g%=255,b%=255,a#=1.0)
   
    Local mesh%=CreateMesh()
    Local surf%=CreateSurface(mesh)
   
    Local v0%=AddVertex(surf, 1, 1,0,0,0)
    Local v1%=AddVertex(surf,-1, 1,0,1,0)
    Local v2%=AddVertex(surf,-1,-1,0,1,1)
    Local v3%=AddVertex(surf, 1,-1,0,0,1)
   
    AddTriangle surf,v0,v1,v2
    AddTriangle surf,v0,v2,v3
   
    If parent Then EntityParent mesh,parent
    If fx Then EntityFX mesh,fx
    If tex Then EntityTexture mesh,tex
    If blend Then EntityBlend mesh,blend
   
    EntityColor mesh,r,g,b
    EntityAlpha mesh,a
   
    VertexColor surf,v0,r,g,b,a
    VertexColor surf,v1,r,g,b,a
    VertexColor surf,v2,r,g,b,a
    VertexColor surf,v3,r,g,b,a
   
    ScaleEntity mesh,scale,scale,scale
   
    Return mesh
   
End Function



ZJP(Posted 1+ years ago)

 Nice....again :)JP


ClayPigeon(Posted 1+ years ago)

 Awesome! I can't fathom how you managed to get that many stars on at once. I thought they were just points until I zoomed in. Nice work!PS: Where's the black hole? :D


_PJ_(Posted 1+ years ago)

 The mathematics here don't seem right at all... maybe I'm, just not following it properly, but what's this for?
Code: [Select]
       If bulge>90 Then bulge=90
        qy=(Cos(bulge)*Rnd(Rnd(-spread),Rnd(spread))/2.0)+(turb/10.0)
I assumed this was to effectively give a greater density of stars around the central region of the galaxy, but it's way off the mark.


Krischan(Posted 1+ years ago)

 To test the power of minib3d I ported this to Blitzmax - unfortunately I couldn't rearrange it to be superstrict. But it runs faster than in Blitz3D (on my old laptop 26FPS in minib3d and 21FPS in Blitz3D!). A general problem is the lack of some kind of quad/octree optimization to minimize CPU calculations as minib3d could handle at least a million of stars easy - which would look very impressive then.Moving is with mouse/arrows while LMB speeds up 10x and LMB+RMB speeds up 100 times, which is recommended in the start position (you can slow down in the bulge/arms)
Code: [Select]
Import sidesign.minib3d

Graphics3D 800, 600, 32, 2

ClearTextureFilters()

Const TurnSpeed:Float = 4.00
Const RollSpeed:Float = 0.50
Const CameraSpeed:Float = 0.01

Const Stars:Int = 250000 ' number of stars
Const Spiralarms:Int = 4 ' number of spiral arms
Const Spread:Float = 20.0 ' star spread
Const Rotation:Float = 4.0 ' how many spiral rotations
Const Range:Float = 100.0 ' milkyway radius

Const QuatToEulerAccuracy:Double = 0.00001

Global WIDTH:Int = GraphicsWidth()
Global HEIGHT:Int = GraphicsHeight()
Global TIMER:TTimer = CreateTimer(60)
Global Scale:Float = WIDTH / 3.0 ' star scale

Global meshes:Int[256]

Global total:Int, vis:Int

Local cam:TCamera, galaxy:Int, tex:TTexture, i:Int, g:Int

Type quad

Global List:TList = CreateList()
Method New()
ListAddLast(List, Self)
End Method
   
Field surf:Int
Field x:Float, y:Float, z:Float
Field v:Int
Field scale:Float
Field r:Int, g:Int, b:Int
Field lastdist:Float
   
End Type

tex = CreateSunTexture(256, 128, 128, 128)
TextureBlend tex, 3

' init galaxy
galaxy = InitGalaxy(Stars, Spiralarms, Spread, Rotation, Range)

For i = 0 To galaxy
   
If meshes[i] > 0 Then

EntityFX meshes[i], 1 + 2
EntityBlend meshes[i], 3
EntityTexture meshes[i], tex

EndIf
   
Next

' init camera
cam = CreateCamera()
CameraRange cam, 0.1, 1000
PositionEntity cam, 0, 90, 150
PointEntity cam, meshes[0]

' update galaxy once
Local cx:Float = EntityX(cam)
Local cy:Float = EntityY(cam)
Local cz:Float = EntityZ(cam)
Local q:quad, d:Float, s:Float

For q:quad = EachIn quad.List

' adaptive size
d = Distance3D(q.x, q.y, q.z, cx, cy, cz)
s = (q.Scale / d) + (d / Scale)
If s < d / Scale Then s = d / Scale
   
' align single surface quads to cam
UpdateQuad(q:quad, s, cam)
q.lastdist = d
   
Next

MoveMouse WIDTH / 2, HEIGHT / 2

' main loop
While Not AppTerminate()

Cls

' Escape = Terminate
If KeyHit(KEY_ESCAPE) Then End

Movement(cam, 1)

Local ms:Int, me:Int
   
ms = MilliSecs()
g = g + 1
If g >= 10 Then g = 0
UpdateGalaxy(cam, Scale, g)
me = MilliSecs() - ms

RenderWorld
   
WaitTimer TIMER
   
Text 0, 0, vis + " Stars updated [" + total + " Stars total] " + me + "ms"
   
Flip 0
   
Wend

End

Function Movement(cam:TCamera, sensitivity:Float = 1.0)

Local roll:Float, cz:Float, tx:Float, ty:Float, multi:Int = 1

cz = (KeyDown(KEY_UP) - KeyDown(KEY_DOWN)) * CameraSpeed
roll = (KeyDown(KEY_LEFT) - KeyDown(KEY_RIGHT)) * RollSpeed
If KeyDown(KEY_RSHIFT) Or MouseDown(1) Then multi = 10
If MouseDown(2) Then multi = multi * 10

tx = Normalize(MouseX(), 0, GraphicsWidth(), 1, -1)
ty = Normalize(MouseY(), 0, GraphicsHeight(), -1, 1)

If ty < 0 Then ty = (Abs(ty) ^ sensitivity) * -1 Else ty = ty ^ sensitivity
If tx < 0 Then tx = (Abs(tx) ^ sensitivity) * -1 Else tx = tx ^ sensitivity

TurnCam cam, ty * TurnSpeed, tx * TurnSpeed, roll * TurnSpeed
MoveEntity cam, 0, 0, cz * multi

End Function

' update quads in single surface mesh
Function UpdateGalaxy(cam:TEntity, scale:Float = 256.0, part:Int)
   
Local cx:Float = EntityX(cam)
Local cy:Float = EntityY(cam)
Local cz:Float = EntityZ(cam)
   
Local q:quad, d:Float, s:Float, steps:Int, i:Int, start:Int, ende:Int
   
total = 0
vis = 0
   
steps = Stars / 10
   
For q:quad = EachIn quad.List
       
' set start and end
start = part * steps
ende = (part + 1) * steps
       
' check only current part or nearby stars
If i >= start And i < ende Or q.lastdist < 5 Then
           
TFormPoint q.x, q.y, q.z, 0, cam
           
' in front of cam?
If TFormedZ() > 0 Then

' adaptive size
d:Float = Distance3D(q.x, q.y, q.z, cx, cy, cz)
s:Float = (q.Scale / d) + (d / Scale)
If s < d / Scale Then s = d / Scale
               
' store last distance calculation
q.lastdist = d

' align single surface quads To cam
UpdateQuad(q:quad, s, cam)

vis = vis + 1
               
EndIf

EndIf
       
i = i + 1
       
total = total + 1
       
Next
   
End Function

' Create galaxy
Function InitGalaxy:Int(stars:Int = 10000, arms:Int = 4, spread:Float = 40.0, rot:Float = 2.0, range:Float = 100.0)
   
Local mesh:TMesh = CreateMesh()
Local surf:TSurface = CreateSurface(mesh)
Local q:quad
Local angle:Float, dist:Float, turb:Float
Local i:Int, col:Float, multi:Float, lum:Float, bulge:Int, counter:Int, surfs:Int = 1, m:Int = 0
   
meshes[0] = mesh
   
For i = 1 To Stars
       
q:quad = New quad
       
' color
col = Rnd(1)
If col > 0.90 And col <= 1.00 Then
q.r = 255
q.g = 0
q.b = 0
EndIf

If col > 0.70 And col <= 0.90 Then
q.r = 255
q.g = 255
q.b = 0
EndIf

If col > 0.50 And col <= 0.70 Then
q.r = 0
q.g = 0
q.b = 255
EndIf

If col > 0.00 And col <= 0.50 Then
q.r = 255
q.g = 255
q.b = 255
EndIf
       
' angle
angle = Int(Floor(i * 1.0 / (Stars / arms))) * (360.0 / arms)
       
' center / arm relation
If Rnd(1) > 0.5 Then
multi = Rnd(0.1, 1)
Else
multi = Rnd(1, 2)
EndIf
       
' distance And turbulence
dist = Rnd(0, Range) * Rnd(1, Rnd(Rnd(multi)))
turb = Rnd(0, Rnd(Spread))
If Rnd(1) > 0.5 Then turb = -turb
       
' more red/yellow Stars in bulge
lum = Rnd(1)
If dist < Range / 2 * lum Then
           
If lum > 0.75 Then
               
q.r = 255
q.g = 0
q.b = 0        ' red Stars
               
Else If lum > 0.5 Then
               
q.r = 255
q.g = 255
q.b = 0    ' yellow Stars
               
EndIf
           
Else
           
If lum > 0.75 Then
               
q.r = 0
q.g = 0
q.b = 255        ' blue Stars
               

Else If lum > 0.5 Then
               
q.r = 255
q.g = 255
q.b = 255    ' white Stars
               
EndIf
           
EndIf
       
' star position x/z
q.x = dist * Cos(angle + (dist * rot)) + Rnd(Rnd(Rnd(-Spread)), Rnd(Rnd(Spread)))
q.z = dist * Sin(angle + (dist * rot)) + Rnd(Rnd(Rnd(-Spread)), Rnd(Rnd(Spread)))
       
' star position y
bulge = Normalize(Distance2D(q.x, q.z, 0, 0), 0, Range / 2.0, 0, 180) / 2.0
If bulge > 90 Then bulge = 90
q.y = (Cos(bulge) * Rnd(Rnd(-Spread), Rnd(Spread)) / 2.0) + (turb / 10.0)
       
' Scale
q.Scale = Rnd(0.01, Rnd(0.02, Rnd(0.04, 0.08)))
       
' Create New surface If too many vertices
If counter + 4 > 32000 Then
           
If surfs + 1 > 3 Then
m = m + 1
mesh = CreateMesh()
meshes[m] = mesh
surfs = 0
EndIf

surf = CreateSurface(mesh)
counter = 0
surfs = surfs + 1
           
EndIf
       
q.surf = surf
       
' add vertices
q.v = AddVertex(q.surf, 0, 0, 0, 0, 0)
AddVertex(q.surf, 0, 0, 0, 1, 0)
AddVertex(q.surf, 0, 0, 0, 1, 1)
AddVertex(q.surf, 0, 0, 0, 0, 1)
       
' color vertices
VertexColor q.surf, q.v + 0, q.r, q.g, q.b
VertexColor q.surf, q.v + 1, q.r, q.g, q.b
VertexColor q.surf, q.v + 2, q.r, q.g, q.b
VertexColor q.surf, q.v + 3, q.r, q.g, q.b
       
' add triangles
AddTriangle(q.surf, q.v, q.v + 1, q.v + 2)
AddTriangle(q.surf, q.v, q.v + 2, q.v + 3)
       
' vertex counter
counter = counter + 4
       
Next
   
Return m
   
End Function

' align single surface quad To cam
Function UpdateQuad(q:quad, s:Float, target:TEntity)
   
Local x1:Float, y1:Float, z1:Float, x2:Float, y2:Float, z2:Float
   
TFormVector - s, 0, 0, target, 0
x1 = TFormedX()
y1 = TFormedY()
z1 = TFormedZ()
   
TFormVector 0, -s, 0, target, 0
x2 = TFormedX()
y2 = TFormedY()
z2 = TFormedZ()
   
VertexCoords q.surf, q.v + 0, q.x - x1 - x2, q.y - y1 - y2, q.z - z1 - z2
VertexCoords q.surf, q.v + 1, q.x - x1 + x2, q.y - y1 + y2, q.z - z1 + z2
VertexCoords q.surf, q.v + 2, q.x + x1 + x2, q.y + y1 + y2, q.z + z1 + z2
VertexCoords q.surf, q.v + 3, q.x + x1 - x2, q.y + y1 - y2, q.z + z1 - z2
   
End Function

' calculate 2D Distance
Function Distance2D:Float(x1:Float, y1:Float, x2:Float, y2:Float)
   
Local x:Float = x1 - x2
Local y:Float = y1 - y2
   
Return Sqr((x * x) + (y * y))
   
End Function

' calucate 3D Distance
Function Distance3D:Float(x1:Float, y1:Float, z1:Float, x2:Float, y2:Float, z2:Float)
   
Local x:Float = x1 - x2
Local y:Float = y1 - y2
Local z:Float = z1 - z2
   
Return Sqr((x * x) + (y * y) + (z * z))
   
End Function

' Normalize a value
Function Normalize:Float(value:Float = 128.0, vmin:Float = 0.0, vmax:Float = 255.0, nmin:Float = 0.0, nmax:Float = 1.0)
   
Return ((value:Float - vmin:Float) / (vmax:Float - vmin:Float)) * (nmax:Float - nmin:Float) + nmin:Float
   
End Function

' Create a stunning sun texture
Function CreateSunTexture:TTexture(size:Int = 512, r:Int = 255, g:Int = 255, b:Int = 255)

Local i:Float, j:Int, col:Int, rgb:Int

Local tempcam:TCamera, tempsun:TPivot, tex:TTexture
Local pixmap:TPixmap = CreatePixmap(size, size, PF_RGBA8888)
Local source:TPixmap

For j = 0 To (size / 2) - 1
       
col = 255 - Normalize(j, 0, (size / 2.0) - 1, 0, 255)
If col > 255 Then col = 255
rgb = col * $1000000 + col * $10000 + col * $100 + col
       
For i = 0 To 360 Step 0.1
           
WritePixel(pixmap, (size / 2) + (Sin(i) * j), (size / 2) + (Cos(i) * j), rgb)
           
Next
       
Next

SavePixmapPNG(pixmap, "sun1.png")

tex = LoadTexture("sun1.png", 2)
   
' temp camera
tempcam = CreateCamera()
CameraRange tempcam, 1, WIDTH * 2
   
' temp pivot
tempsun = CreatePivot()
   
' Create 4 layers
CreateQuad(tempsun, size / 4.0, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
CreateQuad(tempsun, size / 1.5, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
CreateQuad(tempsun, size / 1.2, tex, 3, 1 + 8 + 16, r * 0.75, g * 0.75, b * 0.50, 0.75)
CreateQuad(tempsun, size / 1.0, tex, 3, 1 + 8 + 16, r * 0.50, g * 0.50, b * 0.50, 0.50)
   
PositionEntity tempsun, 0, 0, WIDTH
   
' render it
RenderWorld
RenderWorld
       
source = GrabPixmap(0, 0, WIDTH, HEIGHT)
     
' grab image
For x = 0 To size - 1
       
For y = 0 To size - 1
           
xx = (WIDTH / 2) - (size / 2) + x
yy = (HEIGHT / 2) - (size / 2) + y
           
rgb = ReadPixel(source, xx, yy)
           
r = (rgb & $ff0000) / $10000
g = (rgb & $ff00) / $100
b = (rgb & $ff)
           
' rgb
rgb = (r + g + b) / 3 * $1000000 + r * $10000 + g * $100 + b
           
WritePixel(pixmap, x, y, rgb)
           
Next
       
Next
   
SavePixmapPNG(pixmap, "sun2.png")

' Load texture
tex = LoadTexture("sun2.png", 2)
   
' Delete pivot and temp cam
FreeEntity tempsun
FreeEntity tempcam
   
Return tex
   
End Function

' advanced quad creation
Function CreateQuad:Tmesh(parent:TEntity, scale:Float = 1.0, tex:TTexture = Null, blend:Int = False, fx:Int = False, r:Int = 255, g:Int = 255, b:Int = 255, a:Float = 1.0)
   
Local mesh:TMesh = CreateMesh()
Local surf:TSurface = CreateSurface(mesh)
Local v0:Int, v1:Int, v2:Int, v3:Int
   
v0 = AddVertex(surf, 1, 1, 0, 0, 0)
v1 = AddVertex(surf, -1, 1, 0, 1, 0)
v2 = AddVertex(surf, -1, -1, 0, 1, 1)
v3 = AddVertex(surf, 1, -1, 0, 0, 1)
   
AddTriangle surf, v0, v1, v2
AddTriangle surf, v0, v2, v3
   
If parent Then EntityParent Mesh, parent
If fx Then EntityFX Mesh, fx
If tex Then EntityTexture Mesh, tex
If blend Then EntityBlend Mesh, blend
   
EntityColor Mesh, r, g, b
EntityAlpha Mesh, a
   
VertexColor surf, v0, r, g, b, a
VertexColor surf, v1, r, g, b, a
VertexColor surf, v2, r, g, b, a
VertexColor surf, v3, r, g, b, a
   
ScaleEntity Mesh, Scale, Scale, Scale
   
Return Mesh
   
End Function

Function TurnCam(Ent:TEntity, X:Float, Y:Float, Z:Float, Glob:Int = False)

Local Pitch:Float = 0.0
Local Yaw:Float = 0.0
Local Roll:Float = 0.0

Local Quat:TQuaternion = EulerToQuat( 0.0, 0.0, 0.0 )
Local Turn_Quat:TQuaternion = EulerToQuat( 0.0, 0.0, 0.0 )

If Glob=False

Quat = EulerToQuat( EntityPitch( Ent, True ), EntityYaw( Ent, True ), EntityRoll( Ent, True ) )
Turn_Quat = EulerToQuat( X, Y, Z )
Quat = MultiplyQuats( Quat, Turn_Quat )
Quat = NormalizeQuat( Quat )
QuatToEuler2( Quat.x, Quat.y, Quat.z, Quat.w, Pitch, Yaw, Roll )
RotateEntity Ent, Pitch, Yaw, Roll
Else

RotateEntity Ent, EntityPitch( Ent )+X, EntityYaw( Ent )+Y, EntityRoll( Ent )+Z

EndIf

End Function

Function EulerToQuat:TQuaternion(pitch:Float,yaw:Float,roll:Float)

Local cr:Float=Cos(-roll/2.0)
Local cp:Float=Cos(pitch/2.0)
Local cy:Float=Cos(yaw/2.0)
Local sr:Float=Sin(-roll/2.0)
Local sp:Float=Sin(pitch/2.0)
Local sy:Float=Sin(yaw/2.0)
Local cpcy:Float=cp*cy
Local spsy:Float=sp*sy
Local spcy:Float=sp*cy
Local cpsy:Float=cp*sy

Local q:TQuaternion=New TQuaternion

q.w:Float=cr*cpcy+sr*spsy
q.x:Float=sr*cpcy-cr*spsy
q.y:Float=cr*spcy+sr*cpsy
q.z:Float=cr*cpsy-sr*spcy

Return q

End Function

Function QuatToEuler2(x:Float,y:Float,z:Float,w:Float,pitch:Float Var,yaw:Float Var,roll:Float Var)

Local sint:Float=(2.0*w*y)-(2.0*x*z)
Local cost_temp:Float=1.0-(sint*sint)
Local cost:Float

If Abs(cost_temp)>QuatToEulerAccuracy

cost=Sqr(cost_temp)

Else

cost=0.0

EndIf

Local sinv:Float,cosv:Float,sinf:Float,cosf:Float

If Abs(cost)>QuatToEulerAccuracy

sinv=((2.0*y*z)+(2.0*w*x))/cost
cosv=(1.0-(2.0*x*x)-(2.0*y*y))/cost
sinf=((2.0*x*y)+(2.0*w*z))/cost
cosf=(1.0-(2.0*y*y)-(2.0*z*z))/cost

Else

sinv=(2.0*w*x)-(2.0*y*z)
cosv=1.0-(2.0*x*x)-(2.0*z*z)
sinf=0.0
cosf=1.0

EndIf

pitch=ATan2(sint,cost)
yaw=ATan2(sinf,cosf)
roll=-ATan2(sinv,cosv)

End Function

Function MultiplyQuats:TQuaternion(q1:TQuaternion,q2:TQuaternion)

Local q:TQuaternion=New TQuaternion

q.w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z
q.x = q1.w*q2.x + q1.x*q2.w + q1.y*q2.z - q1.z*q2.y
q.y = q1.w*q2.y + q1.y*q2.w + q1.z*q2.x - q1.x*q2.z
q.z = q1.w*q2.z + q1.z*q2.w + q1.x*q2.y - q1.y*q2.x

Return q

End Function

Function NormalizeQuat:TQuaternion(q:TQuaternion)

Local uv:Float=Sqr(q.w*q.w+q.x*q.x+q.y*q.y+q.z*q.z)

q.w=q.w/uv
q.x=q.x/uv
q.y=q.y/uv
q.z=q.z/uv

Return q

End Function


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal