demo 3D - Asteroid

Everything related to 3D programming
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 291
Joined: Thu Jul 09, 2015 9:07 am

demo 3D - Asteroid

Post by pf shadoko »

Image

Hello, coders,

I worked for a week on the cube mapping (texture and relief) in order to make rocks.
the results were not very conclusive
my goal being to make a curly procedural texture in cube, on this side the result is drinkable (although)
on the other hand, concerning mesh creation, making the normals coincide is a little too crappy.
In fact, I dropped out when I realized that the right way of doing things meant a texturing mode that our ogre implementation doesn't allow (I'll see what I can do on this side)
you will see, it's not top (we can see the seams on the textures of the asteroid, the planet and the celestial vault is ok)

Code: Select all

; demo Asteroïde - pf Shadoko - 2018

EnableExplicit

Structure vector2
  x.f
  y.f
EndStructure

Structure Vector3
  x.f
  y.f
  z.f
EndStructure

Structure Svertex2
  p.vector3
  n.vector3
  diag.b
  ai.b
  aj.b
  uv.vector2
  color.l
EndStructure

Macro vec3d(v,vx,vy,vz)
  v\x=vx
  v\y=vy
  v\z=vz
EndMacro

Macro vec2d(v,vx,vy)
  v\x=vx
  v\y=vy
EndMacro

Procedure.f lng3D(*v.Vector3)
  ProcedureReturn Sqr(*V\x * *V\x + *V\y * *V\y + *V\z * *V\z)
EndProcedure

Procedure Norme3D(*V.Vector3,l.f=1)
  Protected.f lm
  lm = l / lng3d(*v)
  *V\x * lm
  *V\y * lm
  *V\z * lm  
EndProcedure

Macro sub3D(p,p1,p2)
  p\x=p1\x-p2\x
  p\y=p1\y-p2\y
  p\z=p1\z-p2\z
EndMacro

Procedure addvertex(px.f,py.f,pz.f, nx.f,ny.f,nz.f, u.f,v.f,c=0)
    MeshVertexPosition(px,py,pz)
    MeshVertexNormal(nx,ny,nz)
    MeshVertexTextureCoordinate(u,v)  
    MeshVertexColor(c)
EndProcedure

Procedure Createsurface(mesh,Array t.Svertex2(2))
  Protected p,i,j,m,diag,nx=ArraySize(t(),2),nz=ArraySize(t(),1)
  Protected.vector3 d1,d2,n
  m=CreateMesh(mesh):If mesh=-1:mesh=m:EndIf
  For j=0 To nz
    For i=0 To nx
      With t(j,i)
        addvertex(\P\x,\p\y,\p\z,\n\x,\n\y,\n\z,\uv\x,\uv\y,\color)
      EndWith
    Next
  Next  
  For j=0 To nz-1
    For i=0 To nx-1
      p=j*(nx+1)+i
      diag=t(j,i)\diag
      If diag=0
        sub3d(d1,t(j,i)\p,t(j+1,i+1)\p)
        sub3d(d2,t(j+1,i)\p,t(j,i+1)\p)
        If lng3d(d1)>lng3d(d2):diag=1:Else:diag=-1:EndIf
      EndIf
      If diag=1
        MeshFace(p,p+nx+1,p+1): MeshFace(p+nx+2,p+1,p+nx+1)
      Else
        MeshFace(p+nx+1,p+nx+2,p): MeshFace(p+1,p,p+nx+2)
      EndIf
    Next
  Next
  FinishMesh(1)
  NormalizeMesh(mesh)
  UpdateMeshBoundingBox(mesh)
  ProcedureReturn mesh
EndProcedure

Procedure AddMesh(mesho,Mesh,mat, NewX.f=0 , NewY.f=0, NewZ.f=0, ScaleX.f=1, ScaleY.f=1, ScaleZ.f=1, RotateX.f=0, RotateY.f=0, RotateZ.f=0)
  Protected Dim MeshDataV.PB_MeshVertex(0)
  Protected Dim MeshDataF.PB_MeshFace(0)
  Protected i,meshc
  meshc=CopyMesh(mesh,-1)
  TransformMesh(Meshc, NewX,NewY,NewZ, ScaleX,ScaleY,ScaleZ, RotateX,RotateY,RotateZ)
  GetMeshData(Meshc,0, MeshDataV(), #PB_Mesh_Vertex | #PB_Mesh_UVCoordinate| #PB_Mesh_Normal|#PB_Mesh_Color, 0, MeshVertexCount(Meshc, 0)-1)
  GetMeshData(Meshc,0, MeshDataF(), #PB_Mesh_Face, 0, MeshIndexCount(Meshc, 0)-1)
  FreeMesh(meshc) 
  
  AddSubMesh()
  For i=0 To ArraySize(MeshDataV())
    With MeshDatav(i)
      addvertex(\x,\y,\z,\NormalX,\NormalY,\NormalZ,\u,\v,\Color)
    EndWith
  Next     
  For i=0 To ArraySize(MeshDataF()) Step 3
    MeshFace(MeshDataF(i)\Index, MeshDataF(i+1)\Index,MeshDataF(i+2)\Index)
  Next
  If mat>=0:SetMeshMaterial(mesho, MaterialID(mat), SubMeshCount(mesho)-1):EndIf
EndProcedure

Procedure Split(Array t.s(1),l.s,sep.s=",",nmax=100)
    Protected ap.l,p.l,n,ls
    Dim t(nmax)
    ls=Len(sep)
    l+sep
    p=1-ls
    Repeat
        ap=p+ls:p=FindString(l,sep,ap)
        If p=0:Break:EndIf
        n+1
        t(n)= Mid(l,ap,p-ap)
    ForEver
    ReDim t(n)
  EndProcedure
  
Procedure string2vector2(Array s.vector2(1),txt.s)
  Dim tt.s(0)
  Dim t.s(0)
  Protected i,n
  
  split(tt(),txt,"/",100)
  n=ArraySize(tt())
  Dim s(n-1)
  For i=1 To n
    split(t(),tt(i)+",0",",")
    With s(i-1)
      \x=ValF(t(1))
      \y=ValF(t(2))
    EndWith
  Next
EndProcedure

Procedure.f Mini(v1.f,v2.f)
  If v1<v2:ProcedureReturn v1:Else:ProcedureReturn v2:EndIf
EndProcedure

Procedure limite(V, i, s)
  If V < i :v=i:EndIf
  If V > s :v=s:EndIf
  ProcedureReturn V
EndProcedure

Procedure CoRBinv(c.l)
  ProcedureReturn  RGBA(Blue(c),Green(c),Red(c),Alpha(c))
EndProcedure

Procedure ColorBlend(color1.l, color2.l, blend.f)
    Protected r.w,g.w,b.w,a.w
    r=  Red(color1) + (Red(color2)     - Red(color1)) * blend
    g=Green(color1) + (Green(color2) - Green(color1)) * blend
    b= Blue(color1) + (Blue(color2) -   Blue(color1)) * blend
    a=Alpha(color1) + (Alpha(color2) - Alpha(color1)) * blend
    ProcedureReturn  RGBA(r,g,b,a)
EndProcedure

Procedure GradientToArray(Array pal.l(1),n,gradient.s,inv.b=0,alpha.b=0)
  Protected Dim lt.s(0)
  Protected i,j, apos,pos, acol.l,col.l
  n-1
  Dim pal(n)
  split(lt(),gradient,"/")
  
  Macro lparam(i)
    pos=ValF(lt(i))*n
    col=Val(Mid(lt(i),FindString(lt(i),",")+1))
    If inv  :col=CoRBinv(col):EndIf
    If alpha:col | $ff000000:EndIf
  EndMacro
  
  lparam(1)
  For i=2 To ArraySize(lt())
    apos=pos
    acol=col
    lparam(i)
    For j=apos To pos:pal(j)=ColorBlend(acol,col,(j-apos)/(pos-apos)):Next
  Next
EndProcedure

Procedure Finterpol(Array F.f(1),t.s,rx.f=1,ry.f=1,oy.f=0)
  Protected.l i,j,n,c,ac
  Protected.f y,dx,dy,p
  Protected Dim s.vector2(0)
  string2vector2(s(),t)
  n=ArraySize(s())
  For i=0 To n
    s(i)\x*rx
    s(i)\y*ry+oy
  Next  
  Dim f(Int(s(n)\x))
  For j=0 To n-1
    y=s(j)\y
    dx=s(j+1)\x-s(j)\x
    dy=s(j+1)\y-s(j)\y
    p=dy/dx
    ac=c
    While c<=s(j+1)\x
      f(c)=y+p*(c-ac):c+1
    Wend
  Next
EndProcedure

Procedure t2norme(Array t.w(2),dmin.w,dmax.w,profil.s="")
  Protected smin.w,smax.w,dx1,dy1,i,j,sr,dr
  If profil="":profil="0,0/1,1":EndIf
  dy1 = ArraySize(t(), 1)
  dx1 = ArraySize(t(), 2)
  smax = -32768
  smin =  32767
  For j=0 To dy1
    For i=0 To dx1
      If t(j,i)>smax : smax=t(j,i): EndIf
      If t(j,i)<smin : smin=t(j,i): EndIf
    Next
  Next
  sr=smax-smin
  dr=dmax-dmin
  
  Protected Dim conv.f(sr)
  Finterpol(conv(),profil,sr,dr,dmin)
  
  For j=0 To dy1
    For i=0 To dx1
      t(j,i)=conv(t(j,i)-smin)
    Next
  Next
EndProcedure

Procedure Embos(Array s.w(2), px.w=0, py.w=0)
  Protected i,j,dx,dy
  px=1<<Int(Abs(px))*Sign(px)
  py=1<<Int(Abs(py))*Sign(py)
  
  Macro gra(j0,i0,j1,i1)
    t(j0,i0)=Abs(s(j0,i0)-s(j0,i1)+px)+Abs(s(j0,i0)-s(j1,i0)+py)
    EndMacro
  dy = ArraySize(s(), 1)
  dx = ArraySize(s(), 2)
  Dim T.w(dy,dx)
  For j=0 To dy-1
    For i=0 To dx-1
      gra(j,i,j+1,i+1)
    Next
    gra(j,dx,j+1,0)
  Next
  For i = 0 To dx-1
    gra(dy,i,0,i+1)
  Next
  gra(dy,dx,0,0)
  CopyArray(t(),s())
EndProcedure


;######################################################################################################
Declare asteroide(n)
Procedure heightline(Array t.w(1),dx,re,symetric.b)
  Protected i,ii,n,d,dd,l,R, rr
  n = 1<<re
  dd=dx / n: If dd<1:dd=1:EndIf
  Dim t.w(dx)
    rr = $1fff:r=rr/2
For ii = 1 To d/dd - 1:i=ii*dd: t(i) = Random(rr) - R: Next
  While dd > 1
    d = dd / 2
      For ii = 0 To dx/dd - 1:i=ii*dd+d
        t(i) = (t(i - d) + t(i + d)) /2 + Random(rr) - R
      Next
    l/2
    dd/2
    r/2:rr/2
  Wend 
  If symetric:For i=0 To dx/2:t(dx-i)=t(i):Next:EndIf
EndProcedure
  
Procedure heightmapSym(Array t.w(2),rnd, dx.w, dy.w, Re.w)
  Protected i,j,ii,jj,n,d,dd,l,R, rr,dec
  n = 1<<re
  dd=mini(dx,dy) / n: If dd<1:dd=1:EndIf
  Dim t.w(dy, dx)
  Dim b.w(dx)
  RandomSeed(rnd)
  heightline(b(),dx,re,1)
  For i=0 To dx:t(0,i)=b(i):Next
  For i=0 To dx:t(dy,i)=b(i):Next
  For j=0 To dy:t(j,0)=b(j):Next
  For j=0 To dy:t(j,dx)=b(j):Next
  
  RandomSeed(rnd)
  rr = $1fff:r=rr/2
  For jj = 1 To dy/dd - 1:j=jj*dd: For ii = 1 To dx/dd - 1:i=ii*dd: t(j,i) = Random(rr) - R: Next: Next
  l = dd
  While dd > 1
    d = dd / 2
    For jj = 0 To dy/dd - 1  :j=jj*dd+d
      For ii = 0 To dx/dd - 1:i=ii*dd+d
        t(j,i) = (t(j - d,i - d) + t(j - d,i + d) + t(j + d,i + d) + t(j + d,i - d)) / 4 + Random(rr) - R
      Next
    Next
    For jj = 1 To dy/d - 1  :j=jj*d:dec=1- jj & 1
      For ii = 1-dec To dx/dd - 1:i=ii*dd+dec*d
        t(j,i) = (t(j,i - d) + t(j,i + d) + t(j - d,i) + t(j + d,i)) / 4 + Random(rr) - R
      Next
    Next
    l/2
    dd/2
    r/2:rr/2
  Wend 
EndProcedure

Procedure texture(tex,dx,dy,rnd=0,f=0,lissage=0,embos=-1000,pal.s="0,$000000/1,$ffffff")
  Protected Dim t.w(0,0)
  Protected Dim bmp.l(dy-1,dx-1)
  Protected Dim pal.l(0):gradienttoarray(pal(),1024,pal,1)
  Protected i,j,n
  
  heightmapSym(t(),rnd,dx,dy,f)
  
  If embos<>-1000:embos(t(),embos,embos):EndIf
  t2norme(t(),0,1023)
  For j=0 To dy-1:For i=0 To dx-1:bmp(j,i)=pal(t(j,i)):Next:Next
  
  n=CreateTexture(tex,dx,dy)
  If tex=-1:tex=n:EndIf
  StartDrawing(TextureOutput(tex))
  CopyMemory(@bmp(0,0),DrawingBuffer(),dx*dy*4)
  StopDrawing()
  ProcedureReturn tex
EndProcedure

Procedure affiche3d()
  Static.f MouseX,Mousey,keyx,keyy,keyz,a,  fdf.b,iu.b=1,rot.f=1
  Protected i,event,transit=200
  
  Repeat
    event=WindowEvent()  
    ExamineMouse()
    MouseX = -MouseDeltaX() *  0.05
    MouseY = -MouseDeltaY() *  0.05
    If WaitWindowEvent(1) = #PB_Event_LeftClick And IsScreenActive():iu=1-iu: ReleaseMouse(iu):EndIf
    ExamineKeyboard()
    keyx=(-Bool(KeyboardPushed(#PB_Key_Left)<>0)+Bool(KeyboardPushed(#PB_Key_Right)<>0))*0.02
    keyz=(-Bool(KeyboardPushed(#PB_Key_Down)<>0)+Bool(KeyboardPushed(#PB_Key_Up   )<>0))*0.02+MouseWheel()*0.2
    If KeyboardReleased(#PB_Key_F1):asteroide(1):transit=200:EndIf
    If KeyboardReleased(#PB_Key_F2):asteroide(2):transit=200:EndIf
    If KeyboardReleased(#PB_Key_F3):asteroide(3):transit=200:EndIf
    If KeyboardReleased(#PB_Key_F4):asteroide(4):transit=200:EndIf
    If transit>0:transit-1:CameraFollow(0,EntityID(1),0,0,10,0.05,0.05,1):EndIf
    If KeyboardReleased(#PB_Key_F12):fdf=1-fdf:If fdf:CameraRenderMode(0,#PB_Camera_Wireframe):Else:CameraRenderMode(0,#PB_Camera_Textured):EndIf:EndIf
    RotateCamera(0, MouseY, MouseX, 0, #PB_Relative):MoveCamera  (0, KeyX, 0, -keyz) :MoveCamera(0,CameraX(0),CameraY(0),CameraZ(0),#PB_Absolute)    
    RotateEntity(1,rot*0.01,rot*0.03,0,#PB_Relative)
    RenderWorld()
    DisplayTransparentSprite(0,8,8)
    FlipBuffers()
  Until event=#PB_Event_CloseWindow  Or KeyboardPushed(#PB_Key_Escape)
EndProcedure

Procedure createsphereCM(mesh,rnd,rayon.f,detail,amp.f,fraction,lissage=0,ntile=1,profil.s="",pal.s="")
  Define i,j,d=1<<detail   ,d2=d/2,n,icolor
  Dim t.svertex2(d,d)
  Dim hm.w(d,d)
  Dim pal.l(0):gradienttoarray(pal(),1024,pal,1)
  
  heightmapSym(hm(),rnd,d,d,fraction)
  t2norme(hm(),-1024,1024,profil)
  
  For j=0 To d
    For i=0 To d
      vec3d(t(i,j)\p,-Tan((i/d2-1)*#PI/4),1,Tan((j/d2-1)*#PI/4))
      norme3d(t(i,j)\p,(1+hm(i,j)/1024*amp)*rayon)
      vec2d(t(i,j)\uv,i/d*ntile,j/d*ntile)
      icolor=1023*(hm(i,j)+1024)/2048:t(i,j)\color=pal(icolor)
    Next
  Next  
  n= createsurface(-1,t())
  CreateMesh(mesh)
  addmesh(mesh,n,-1,0,0,0,1,1,1,0,0,0)
  addmesh(mesh,n,-1,0,0,0,1,1,1,0,270,270)
  addmesh(mesh,n,-1,0,0,0,1,1,1,180,0,0)
  addmesh(mesh,n,-1,0,0,0,1,1,1,0,270,90)
  addmesh(mesh,n,-1,0,0,0,1,1,1,270,90,0)
  addmesh(mesh,n,-1,0,0,0,1,1,1,90,0,270)
  FinishMesh(1)
  NormalizeMesh(mesh)
EndProcedure

Procedure asteroide(n)
  Protected past.vector3
  
  Select n
    Case 1:createspherecm(1,0,4,8,0.05,0,0,4,"0,1/0.3,0.8/0.5,0/0.6,0.5/1,1","0,$004488/1,$ffffff"):vec3d(past,1000,0,2000)
    Case 2:createspherecm(1,4,4,8,0.1,0,0,4,"0,0/1,1","0,$ffffff/1,$ffffff"):vec3d(past,-2000,0,-1000)
    Case 3:createspherecm(1,1,4,8,0.04,2,0,4,"0,0.4/0.5,0.6/0.7,1/0.8,0.1/1,0.0","0,$ff0000/0.5,$0088ff/1,$ffffff"):vec3d(past,-1000,0,1000)
    Case 4:createspherecm(1,1,4,8,0.08,2,0,4,"0,0/0.5,0.3/0.6,0.7/1,1","0,$ffffff/1,$0000ff"):vec3d(past,-1000,0,-1500)
  EndSelect
  CreateEntity(1,MeshID(1),MaterialID(1),past\x,past\y,past\z)
EndProcedure

Procedure menu()
  Protected p=8
  Macro DT(t1,t2)
    DrawText(8,p,t1)
    DrawText(100,p,t2)
    p+22
  EndMacro
  CreateSprite(0,256,180,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(0))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawingFont(FontID(0))
  Box(0,0,256,180,$44000000)
  DrawingMode(#PB_2DDrawing_AllChannels|#PB_2DDrawing_Outlined)
  Box(0,0,256,180,$ffffffff)
  BackColor($44000000)
  FrontColor($ffffffff)
  dt("Moving:","")
  dt("Cursor + Mouse","")
  dt("","")
  dt("Commandes:","")
  dt("[F1]->[F4]","Select asteroid")
  dt("[F12]","Wireframe")
  dt("[Esc]","Quit")
  StopDrawing()
EndProcedure

Procedure test_CubeMap()
  Protected i,ex,ey,r.f=1
  ExamineDesktops()
  ex=DesktopWidth(0)
  ey=DesktopHeight(0)
  
  InitKeyboard():InitMouse():InitEngine3D():InitSprite() 
  OpenWindow(0,0,0,ex*r,ey*r,"",#PB_Window_BorderLess)
  OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0),WindowHeight(0))
  LoadFont(0,"arial",14)
  
  menu()
  ;-------------------- scene
  CreateLight(0, $aaaaaa, -5000, 1000, 2000)
  SetLightColor(0, #PB_Light_SpecularColor, $444444)
  AmbientColor($444444)
  CreateCamera(0, 0, 0, 100, 100)
  CameraRange(0,0,100000)
  MoveCamera(0, -10,1,-10, #PB_Absolute)
  CameraLookAt(0, 0, 0, 0)
  
  ;planete
  texture(3,256,256,1,  3,0,-1000,"0,$ffffff/0.4,$446666/0.5,$6688bb/1,$446688")
  CreateMaterial(3, TextureID(3))
  createspherecm(3,0,500,5,0,0,0,1)
  CreateEntity(3,MeshID(3),MaterialID(3))
  ;anneau
  texture(4,128,128,0,  2,0,-1000,"0,$000000/1,$ffffffff")
  CreateMaterial(4, TextureID(4)):ScaleMaterial(4,1,0.1)
  MaterialFilteringMode(4,#PB_Material_Anisotropic,4)
  MaterialBlendingMode(4,#PB_Material_AlphaBlend)
  CreateTorus(4,800,180,8,64):TransformMesh(4,0,0,0,1,0.0001,1,-15,-40,0):NormalizeMesh(4)
  CreateEntity(4,MeshID(4),MaterialID(4))
  
  ;etoiles
  texture(5,256,256,4,  1,0,-1000,"0,$442222/0.1,$221111/0.5,$000000/0.7,$000000/1,$112222")
  CreateTexture(6,512,512)
  StartDrawing(TextureOutput(6)):For i=0 To 400:Circle(Random(512),Random(512),Pow(Random(3)+1,4)/200,Random(255)*$010101):Next:StopDrawing()
  CreateMaterial(5, TextureID(5))
  AddMaterialLayer(5, TextureID(6),#PB_Material_Add):ScaleMaterial(5,1/4,1/4,1)
  SetMaterialColor(5,#PB_Material_SelfIlluminationColor,$ffffff):MaterialCullingMode(5, #PB_Material_NoCulling)
  createspherecm(5,0,10000,2,0,0,0,1)
  CreateEntity(5,MeshID(5),MaterialID(5))

  ;soleil
  CreateTexture(7,2,2)
  StartDrawing(TextureOutput(7)):Box(0,0,2,2,$ffffff):StopDrawing()
  CreateMaterial(7, TextureID(7))
  SetMaterialColor(7,#PB_Material_SelfIlluminationColor,$ffffff):MaterialCullingMode(5, #PB_Material_NoCulling)
  CreateSphere(7,100)
  CreateEntity(7,MeshID(7),MaterialID(7),-5000, 1000, 2000)
  
    ;asteroide
  texture(1,512,512,0,  4,0,0,"0,$ffffff/1,$000000")
  texture(2,512,512,0,  3,0,20,"0,$ff000000/0.5,$00/1,$ffffffff")
  CreateMaterial(1, TextureID(1))
  SetMaterialColor(1, #PB_Material_SpecularColor, $ffffff):MaterialShininess(1, 10)
  AddMaterialLayer(1, TextureID(2),#PB_Material_AlphaBlend):ScaleMaterial(1,1/4,1/4,1)
  MaterialFilteringMode(1,#PB_Material_Anisotropic,4)
  SetMaterialColor(1, #PB_Material_AmbientColor,-1)
  asteroide(1)
 
  affiche3d():End
  EndProcedure
  
test_CubeMap()
User avatar
Zebuddi123
Enthusiast
Enthusiast
Posts: 794
Joined: Wed Feb 01, 2012 3:30 pm
Location: Nottinghamshire UK
Contact:

Re: demo 3D - Asteroid

Post by Zebuddi123 »

IN so few lines :) brilliant

Zebuddi. :)
malleo, caput, bang. Ego, comprehendunt in tempore
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: demo 3D - Asteroid

Post by RSBasic »

Looks great. Image
Image
Image
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Re: demo 3D - Asteroid

Post by Hades »

Doing procedural textures and geometry is probably the thing I like most apart from ray tracing. And I really like what you have done here.
Even up close the asteroids look very good.
I also like how you're experimenting with different noise functions, although when looking at the 'F1' asteroid I wonder if reversing what is high and low, and playing around with the function a bit more, could give you something that looks like impact craters with ridges...

Keep up the awesome work. :D
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: demo 3D - Asteroid

Post by davido »

@pf shadoko ,
Another great demo. Thank you for sharing. :D
DE AA EB
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 291
Joined: Thu Jul 09, 2015 9:07 am

Re: demo 3D - Asteroid

Post by pf shadoko »

@ Hades :

I tried, but the result is not convincing:

replace line 405 by:
Case 1:createspherecm(1,0,4,8,0.01,3,0,4,"0,0/0.3,0.2/0.5,1/0.6,0.5/1,0","0,$004488/1,$ffffff"):vec3d(past,1000,0,2000)

crateres should be superimposed on the heightmap (not very complicated, but it is necessary to take into account the particular looping of the cub map
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Re: demo 3D - Asteroid

Post by Hades »

With that change, while not perfect, to me it feels closer to what a big asteroid/moon should look like.
But that might be a matter of taste.
User avatar
Fig
Enthusiast
Enthusiast
Posts: 351
Joined: Thu Apr 30, 2009 5:23 pm
Location: Côtes d'Azur, France

Re: demo 3D - Asteroid

Post by Fig »

Really cool effect, great ! :shock:
There are 2 methods to program bugless.
But only the third works fine.

Win10, Pb x64 5.71 LTS
User avatar
DK_PETER
Addict
Addict
Posts: 898
Joined: Sat Feb 19, 2011 10:06 am
Location: Denmark
Contact:

Re: demo 3D - Asteroid

Post by DK_PETER »

Looks good. :-)
Added a little extra.

Code: Select all

; demo Asteroïde - pf Shadoko - 2018

EnableExplicit

Global Base.i

Structure vector2
  x.f
  y.f
EndStructure

Structure Vector3
  x.f
  y.f
  z.f
EndStructure

Structure Svertex2
  p.vector3
  n.vector3
  diag.b
  ai.b
  aj.b
  uv.vector2
  color.l
EndStructure

Macro vec3d(v,vx,vy,vz)
  v\x=vx
  v\y=vy
  v\z=vz
EndMacro

Macro vec2d(v,vx,vy)
  v\x=vx
  v\y=vy
EndMacro

Procedure.f lng3D(*v.Vector3)
  ProcedureReturn Sqr(*V\x * *V\x + *V\y * *V\y + *V\z * *V\z)
EndProcedure

Procedure Norme3D(*V.Vector3,l.f=1)
  Protected.f lm
  lm = l / lng3d(*v)
  *V\x * lm
  *V\y * lm
  *V\z * lm 
EndProcedure

Macro sub3D(p,p1,p2)
  p\x=p1\x-p2\x
  p\y=p1\y-p2\y
  p\z=p1\z-p2\z
EndMacro

Structure _Particles
  id.i
  ma.i
  tx.i
EndStructure
Global Dim pa._Particles(3)
Global Dim atmos._Particles(2)


Declare.i GetHalo(Radius.i, GlowColor.i = $00FF6100, InnerColor.i = $BBF76B10, GradPosition.f = 0.75, Name.s = "")

Procedure addvertex(px.f,py.f,pz.f, nx.f,ny.f,nz.f, u.f,v.f,c=0)
    MeshVertexPosition(px,py,pz)
    MeshVertexNormal(nx,ny,nz)
    MeshVertexTextureCoordinate(u,v) 
    MeshVertexColor(c)
EndProcedure

Procedure Createsurface(mesh,Array t.Svertex2(2))
  Protected p,i,j,m,diag,nx=ArraySize(t(),2),nz=ArraySize(t(),1)
  Protected.vector3 d1,d2,n
  m=CreateMesh(mesh):If mesh=-1:mesh=m:EndIf
  For j=0 To nz
    For i=0 To nx
      With t(j,i)
        addvertex(\P\x,\p\y,\p\z,\n\x,\n\y,\n\z,\uv\x,\uv\y,\color)
      EndWith
    Next
  Next 
  For j=0 To nz-1
    For i=0 To nx-1
      p=j*(nx+1)+i
      diag=t(j,i)\diag
      If diag=0
        sub3d(d1,t(j,i)\p,t(j+1,i+1)\p)
        sub3d(d2,t(j+1,i)\p,t(j,i+1)\p)
        If lng3d(d1)>lng3d(d2):diag=1:Else:diag=-1:EndIf
      EndIf
      If diag=1
        MeshFace(p,p+nx+1,p+1): MeshFace(p+nx+2,p+1,p+nx+1)
      Else
        MeshFace(p+nx+1,p+nx+2,p): MeshFace(p+1,p,p+nx+2)
      EndIf
    Next
  Next
  FinishMesh(1)
  NormalizeMesh(mesh)
  UpdateMeshBoundingBox(mesh)
  ProcedureReturn mesh
EndProcedure

Procedure AddMesh(mesho,Mesh,mat, NewX.f=0 , NewY.f=0, NewZ.f=0, ScaleX.f=1, ScaleY.f=1, ScaleZ.f=1, RotateX.f=0, RotateY.f=0, RotateZ.f=0)
  Protected Dim MeshDataV.PB_MeshVertex(0)
  Protected Dim MeshDataF.PB_MeshFace(0)
  Protected i,meshc
  meshc=CopyMesh(mesh,-1)
  TransformMesh(Meshc, NewX,NewY,NewZ, ScaleX,ScaleY,ScaleZ, RotateX,RotateY,RotateZ)
  GetMeshData(Meshc,0, MeshDataV(), #PB_Mesh_Vertex | #PB_Mesh_UVCoordinate| #PB_Mesh_Normal|#PB_Mesh_Color, 0, MeshVertexCount(Meshc, 0)-1)
  GetMeshData(Meshc,0, MeshDataF(), #PB_Mesh_Face, 0, MeshIndexCount(Meshc, 0)-1)
  FreeMesh(meshc)
 
  AddSubMesh()
  For i=0 To ArraySize(MeshDataV())
    With MeshDatav(i)
      addvertex(\x,\y,\z,\NormalX,\NormalY,\NormalZ,\u,\v,\Color)
    EndWith
  Next     
  For i=0 To ArraySize(MeshDataF()) Step 3
    MeshFace(MeshDataF(i)\Index, MeshDataF(i+1)\Index,MeshDataF(i+2)\Index)
  Next
  If mat>=0:SetMeshMaterial(mesho, MaterialID(mat), SubMeshCount(mesho)-1):EndIf
EndProcedure

Procedure Split(Array t.s(1),l.s,sep.s=",",nmax=100)
    Protected ap.l,p.l,n,ls
    Dim t(nmax)
    ls=Len(sep)
    l+sep
    p=1-ls
    Repeat
        ap=p+ls:p=FindString(l,sep,ap)
        If p=0:Break:EndIf
        n+1
        t(n)= Mid(l,ap,p-ap)
    ForEver
    ReDim t(n)
  EndProcedure
 
Procedure string2vector2(Array s.vector2(1),txt.s)
  Dim tt.s(0)
  Dim t.s(0)
  Protected i,n
 
  split(tt(),txt,"/",100)
  n=ArraySize(tt())
  Dim s(n-1)
  For i=1 To n
    split(t(),tt(i)+",0",",")
    With s(i-1)
      \x=ValF(t(1))
      \y=ValF(t(2))
    EndWith
  Next
EndProcedure

Procedure.f Mini(v1.f,v2.f)
  If v1<v2:ProcedureReturn v1:Else:ProcedureReturn v2:EndIf
EndProcedure

Procedure limite(V, i, s)
  If V < i :v=i:EndIf
  If V > s :v=s:EndIf
  ProcedureReturn V
EndProcedure

Procedure CoRBinv(c.l)
  ProcedureReturn  RGBA(Blue(c),Green(c),Red(c),Alpha(c))
EndProcedure

Procedure ColorBlend(color1.l, color2.l, blend.f)
    Protected r.w,g.w,b.w,a.w
    r = Red(color1)   + (Red(color2)   - Red(color1)) * blend
    g = Green(color1) + (Green(color2) - Green(color1)) * blend
    b = Blue(color1)  + (Blue(color2)  - Blue(color1)) * blend
    a = Alpha(color1) + (Alpha(color2) - Alpha(color1)) * blend
    ProcedureReturn  RGBA(r,g,b,a)
EndProcedure

Procedure GradientToArray(Array pal.l(1),n,gradient.s,inv.b=0,alpha.b=0)
  Protected Dim lt.s(0)
  Protected i, j, apos, pos, acol.l, col.l
  n-1
  Dim pal(n)
  split(lt(),gradient,"/")
 
  Macro lparam(i)
    pos=ValF(lt(i))*n
    col=Val(Mid(lt(i),FindString(lt(i),",")+1))
    If inv  :col=CoRBinv(col):EndIf
    If alpha:col | $ff000000:EndIf
  EndMacro
 
  lparam(1)
  For i=2 To ArraySize(lt())
    apos=pos
    acol=col
    lparam(i)
    For j=apos To pos:pal(j)=ColorBlend(acol,col,(j-apos)/(pos-apos)):Next
  Next
EndProcedure

Procedure Finterpol(Array F.f(1),t.s,rx.f=1,ry.f=1,oy.f=0)
  Protected.l i,j,n,c,ac
  Protected.f y,dx,dy,p
  Protected Dim s.vector2(0)
  string2vector2(s(),t)
  n=ArraySize(s())
  For i=0 To n
    s(i)\x*rx
    s(i)\y*ry+oy
  Next 
  Dim f(Int(s(n)\x))
  For j=0 To n-1
    y=s(j)\y
    dx=s(j+1)\x-s(j)\x
    dy=s(j+1)\y-s(j)\y
    p=dy/dx
    ac=c
    While c<=s(j+1)\x
      f(c)=y+p*(c-ac):c+1
    Wend
  Next
EndProcedure

Procedure t2norme(Array t.w(2),dmin.w,dmax.w,profil.s="")
  Protected smin.w,smax.w,dx1,dy1,i,j,sr,dr
  If profil="":profil="0,0/1,1":EndIf
  dy1 = ArraySize(t(), 1)
  dx1 = ArraySize(t(), 2)
  smax = -32768
  smin =  32767
  For j=0 To dy1
    For i=0 To dx1
      If t(j,i)>smax : smax=t(j,i): EndIf
      If t(j,i)<smin : smin=t(j,i): EndIf
    Next
  Next
  sr=smax-smin
  dr=dmax-dmin
 
  Protected Dim conv.f(sr)
  Finterpol(conv(),profil,sr,dr,dmin)
 
  For j=0 To dy1
    For i=0 To dx1
      t(j,i)=conv(t(j,i)-smin)
    Next
  Next
EndProcedure

Procedure Embos(Array s.w(2), px.w=0, py.w=0)
  Protected i,j,dx,dy
  px=1<<Int(Abs(px))*Sign(px)
  py=1<<Int(Abs(py))*Sign(py)
 
  Macro gra(j0,i0,j1,i1)
    t(j0,i0)=Abs(s(j0,i0)-s(j0,i1)+px)+Abs(s(j0,i0)-s(j1,i0)+py)
    EndMacro
  dy = ArraySize(s(), 1)
  dx = ArraySize(s(), 2)
  Dim T.w(dy,dx)
  For j=0 To dy-1
    For i=0 To dx-1
      gra(j,i,j+1,i+1)
    Next
    gra(j,dx,j+1,0)
  Next
  For i = 0 To dx-1
    gra(dy,i,0,i+1)
  Next
  gra(dy,dx,0,0)
  CopyArray(t(),s())
EndProcedure


;######################################################################################################
Declare asteroide(n)
Procedure heightline(Array t.w(1),dx,re,symetric.b)
  Protected i,ii,n,d,dd,l,R, rr
  n = 1<<re
  dd=dx / n: If dd<1:dd=1:EndIf
  Dim t.w(dx)
    rr = $1fff:r=rr/2
For ii = 1 To d/dd - 1:i=ii*dd: t(i) = Random(rr) - R: Next
  While dd > 1
    d = dd / 2
      For ii = 0 To dx/dd - 1:i=ii*dd+d
        t(i) = (t(i - d) + t(i + d)) /2 + Random(rr) - R
      Next
    l/2
    dd/2
    r/2:rr/2
  Wend
  If symetric:For i=0 To dx/2:t(dx-i)=t(i):Next:EndIf
EndProcedure
 
Procedure heightmapSym(Array t.w(2),rnd, dx.w, dy.w, Re.w)
  Protected i,j,ii,jj,n,d,dd,l,R, rr,dec
  n = 1<<re
  dd=mini(dx,dy) / n: If dd<1:dd=1:EndIf
  Dim t.w(dy, dx)
  Dim b.w(dx)
  RandomSeed(rnd)
  heightline(b(),dx,re,1)
  For i=0 To dx:t(0,i)=b(i):Next
  For i=0 To dx:t(dy,i)=b(i):Next
  For j=0 To dy:t(j,0)=b(j):Next
  For j=0 To dy:t(j,dx)=b(j):Next
 
  RandomSeed(rnd)
  rr = $1fff:r=rr/2
  For jj = 1 To dy/dd - 1:j=jj*dd: For ii = 1 To dx/dd - 1:i=ii*dd: t(j,i) = Random(rr) - R: Next: Next
  l = dd
  While dd > 1
    d = dd / 2
    For jj = 0 To dy/dd - 1  :j=jj*dd+d
      For ii = 0 To dx/dd - 1:i=ii*dd+d
        t(j,i) = (t(j - d,i - d) + t(j - d,i + d) + t(j + d,i + d) + t(j + d,i - d)) / 4 + Random(rr) - R
      Next
    Next
    For jj = 1 To dy/d - 1  :j=jj*d:dec=1- jj & 1
      For ii = 1-dec To dx/dd - 1:i=ii*dd+dec*d
        t(j,i) = (t(j,i - d) + t(j,i + d) + t(j - d,i) + t(j + d,i)) / 4 + Random(rr) - R
      Next
    Next
    l/2
    dd/2
    r/2:rr/2
  Wend
EndProcedure

Procedure texture(tex,dx,dy,rnd=0,f=0,lissage=0,embos=-1000,pal.s="0,$000000/1,$ffffff")
  Protected Dim t.w(0,0)
  Protected Dim bmp.l(dy-1,dx-1)
  Protected Dim pal.l(0):gradienttoarray(pal(),1024,pal,1)
  Protected i,j,n
 
  heightmapSym(t(),rnd,dx,dy,f)
 
  If embos<>-1000:embos(t(),embos,embos):EndIf
  t2norme(t(),0,1023)
  For j=0 To dy-1:For i=0 To dx-1:bmp(j,i)=pal(t(j,i)):Next:Next
 
  n=CreateTexture(tex,dx,dy)
  If tex=-1:tex=n:EndIf
  StartDrawing(TextureOutput(tex))
  CopyMemory(@bmp(0,0),DrawingBuffer(),dx*dy*4)
  StopDrawing()
  ProcedureReturn tex
EndProcedure

Procedure affiche3d()
  Static.f MouseX,Mousey,keyx,keyy,keyz,a,  fdf.b,iu.b=1,rot.f=1
  Protected i,event,transit=200
 
  Repeat
    event=WindowEvent() 
    ExamineMouse()
    MouseX = -MouseDeltaX() *  0.05
    MouseY = -MouseDeltaY() *  0.05
    If WaitWindowEvent(1) = #PB_Event_LeftClick And IsScreenActive():iu=1-iu: ReleaseMouse(iu):EndIf
    ExamineKeyboard()
    keyx=(-Bool(KeyboardPushed(#PB_Key_Left)<>0)+Bool(KeyboardPushed(#PB_Key_Right)<>0))*0.02
    keyz=(-Bool(KeyboardPushed(#PB_Key_Down)<>0)+Bool(KeyboardPushed(#PB_Key_Up   )<>0))*0.02+MouseWheel()*0.2
    If KeyboardReleased(#PB_Key_F1):asteroide(1):transit=200:EndIf
    If KeyboardReleased(#PB_Key_F2):asteroide(2):transit=200:EndIf
    If KeyboardReleased(#PB_Key_F3):asteroide(3):transit=200:EndIf
    If KeyboardReleased(#PB_Key_F4):asteroide(4):transit=200:EndIf
    If transit>0:transit-1:CameraFollow(0,EntityID(1),0,0,100,0.05,0.05,1):EndIf
    If KeyboardReleased(#PB_Key_F12):fdf=1-fdf:If fdf:CameraRenderMode(0,#PB_Camera_Wireframe):Else:CameraRenderMode(0,#PB_Camera_Textured):EndIf:EndIf
    RotateCamera(0, MouseY, MouseX, 0, #PB_Relative):MoveCamera  (0, KeyX, 0, -keyz) :MoveCamera(0,CameraX(0),CameraY(0),CameraZ(0),#PB_Absolute)   
    RotateEntity(1,rot*0.01, rot*0.03, rot*0.03, #PB_Relative)
    RenderWorld()
    DisplayTransparentSprite(0,8,8)
    FlipBuffers()
  Until event=#PB_Event_CloseWindow  Or KeyboardPushed(#PB_Key_Escape)
EndProcedure

Procedure.f RandomF(Min.f, Max.f, Res.i = 100000)
  ProcedureReturn (Min + (Max - Min) * Random(Res) / Res)
EndProcedure


Procedure createsphereCM(mesh,rnd,rayon.f,detail,amp.f,fraction,lissage=0,ntile=1,profil.s="",pal.s="")
  Define i,j,d=1<<detail   ,d2=d/2,n,icolor
  Dim t.svertex2(d,d)
  Dim hm.w(d,d)
  Dim pal.l(0):gradienttoarray(pal(),1024,pal,1)
 
  heightmapSym(hm(),rnd,d,d,fraction)
  t2norme(hm(),-1024,1024,profil)
 
  For j=0 To d
    For i=0 To d
      vec3d(t(i,j)\p,-Tan((i/d2-1)*#PI/4),1,Tan((j/d2-1)*#PI/4))
      norme3d(t(i,j)\p,(1+hm(i,j)/1024*amp)*rayon)
      vec2d(t(i,j)\uv,i/d*ntile,j/d*ntile)
      icolor=1023*(hm(i,j)+1024)/2048:t(i,j)\color=pal(icolor)
    Next
  Next 
  n= createsurface(-1,t())
  CreateMesh(mesh)
  addmesh(mesh,n,-1,0,0,0,1,1,1,0,0,0)
  addmesh(mesh,n,-1,0,0,0,1,1,1,0,270,270)
  addmesh(mesh,n,-1,0,0,0,1,1,1,180,0,0)
  addmesh(mesh,n,-1,0,0,0,1,1,1,0,270,90)
  addmesh(mesh,n,-1,0,0,0,1,1,1,270,90,0)
  addmesh(mesh,n,-1,0,0,0,1,1,1,90,0,270)
  FinishMesh(mesh)
  NormalizeMesh(mesh)
EndProcedure

Procedure asteroide(n)
  Protected past.vector3
  If IsEntity(1) : FreeEntity(1) : FreeMesh(1) : EndIf
  Select n
    Case 1:createspherecm(1,0,4,8,0.05,0,0,4,"0,1/0.3,0.8/0.5,0/0.6,0.5/1,1","0,$224488/1,$ffffff"):vec3d(past,1000,0,1000)
    Case 2:createspherecm(1,4,4,8,0.1,0,0,4,"0,0/1,1","0,$ffffff/1,$ffffff"):vec3d(past,1000,0,1000)
    Case 3:createspherecm(1,1,4,8,0.04,2,0,4,"0,0.4/0.5,0.6/0.7,1/0.8,0.1/1,0.0","0,$555555/0.5,$5588ff/1,$ffffff"):vec3d(past,1000,0,1000)
    Case 4:createspherecm(1,1,4,8,0.08,2,0,4,"0,0/0.5,0.3/0.6,0.7/1,1","0,$ffffff/1,$333333"):vec3d(past,1000,0,1000)
  EndSelect
  RandomSeed(ElapsedMilliseconds())
  TransformMesh(1, 0, 0, 0, RandomF(1.0, 5.0),RandomF(1.0, 5.0),RandomF(1.0, 5.0), Random(359),Random(359),Random(359))
  CreateEntity(1, MeshID(1), MaterialID(1), past\x, past\y, past\z)
  If IsParticleEmitter(pa(0)\id) > 0
    FreeParticleEmitter(pa(0)\id)
    FreeParticleEmitter(pa(1)\id)
    FreeParticleEmitter(pa(2)\id)
  EndIf
    pa(0)\id = CreateParticleEmitter(#PB_Any, MeshRadius(1) * GetEntityAttribute(1, #PB_Entity_ScaleX), MeshRadius(1) * GetEntityAttribute(1, #PB_Entity_ScaleY), MeshRadius(1) * GetEntityAttribute(1, #PB_Entity_ScaleZ),  #PB_Particle_Point, EntityX(1), EntityY(1), EntityZ(1)) 
    ParticleSpeedFactor(pa(0)\id, 0.32)
    ParticleMaterial(pa(0)\id, MaterialID(pa(0)\ma))
    ParticleEmitterAngle(pa(0)\id, 6)
    ParticleVelocity(pa(0)\id, #PB_Particle_MinimumVelocity, 60)
    ParticleVelocity(pa(0)\id, #PB_Particle_Velocity, 90.5)
    ParticleVelocity(pa(0)\id, #PB_Particle_MaximumVelocity, 120)
    ParticleTimeToLive(pa(0)\id, 10.4, 34)
    ParticleEmissionRate(pa(0)\id, 800)
    ParticleEmitterDirection(pa(0)\id, (Radian(EntityPitch(7))/#PI)*-1 , 0, (Radian(EntityYaw(1))/#PI)*-1)
    ParticleAcceleration(pa(0)\id, 0, 0, 0.12)
    ParticleSize(pa(0)\id, 0.2, 0.2)
    ;-------------------------------
    pa(1)\id = CreateParticleEmitter(#PB_Any, MeshRadius(1) * (GetEntityAttribute(1, #PB_Entity_ScaleX)*2.5), MeshRadius(1) * (GetEntityAttribute(1, #PB_Entity_ScaleY)*2.5), MeshRadius(1) * (GetEntityAttribute(1, #PB_Entity_ScaleZ)*2.5),  #PB_Particle_Point, EntityX(1), EntityY(1), EntityZ(1)) 
    ParticleMaterial(pa(1)\id, MaterialID(pa(1)\ma))
    ParticleEmitterAngle(pa(1)\id, 0.5)
    ParticleVelocity(pa(1)\id, #PB_Particle_MinimumVelocity, 54)
    ParticleVelocity(pa(1)\id, #PB_Particle_Velocity, 110)
    ParticleVelocity(pa(1)\id, #PB_Particle_MaximumVelocity, 220)
    ParticleTimeToLive(pa(1)\id, 10.4, 34)
    ParticleEmissionRate(pa(1)\id, 400)
    ParticleEmitterDirection(pa(1)\id, (Radian(EntityPitch(7))/#PI)*-1 , 0, (Radian(EntityYaw(1))/#PI)*-1)
    ParticleColorFader(pa(1)\id, 0.2, 1, 1, 0.1)
    ParticleSize(pa(1)\id, 10, 0.4)
    ;------------------------------
    pa(2)\id = CreateParticleEmitter(#PB_Any, MeshRadius(1) * (GetEntityAttribute(1, #PB_Entity_ScaleX)*2), MeshRadius(1) * (GetEntityAttribute(1, #PB_Entity_ScaleY)*2), MeshRadius(1) * (GetEntityAttribute(1, #PB_Entity_ScaleZ)*2),  #PB_Particle_Point, EntityX(1), EntityY(1), EntityZ(1)) 
    ParticleMaterial(pa(2)\id, MaterialID(pa(2)\ma))
    ParticleEmitterAngle(pa(2)\id, 0.5)
    ParticleVelocity(pa(2)\id, #PB_Particle_MinimumVelocity, 30)
    ParticleVelocity(pa(2)\id, #PB_Particle_Velocity, 100)
    ParticleVelocity(pa(2)\id, #PB_Particle_MaximumVelocity, 200)
    ParticleTimeToLive(pa(2)\id, 1.5, 2.0)
    ParticleEmissionRate(pa(2)\id, 600)
    ParticleEmitterDirection(pa(2)\id,  (Radian(EntityPitch(7))/#PI)*-1 , 0, (Radian(EntityYaw(1))/#PI)*-1)
    ParticleColorFader(pa(2)\id, 1, 1, 1, 0.1)
    ParticleSize(pa(2)\id, 5.0, 0.06)
EndProcedure

Procedure menu()
  Protected p=8
  Macro DT(t1,t2)
    DrawText(8,p,t1)
    DrawText(100,p,t2)
    p+22
  EndMacro
  CreateSprite(0,256,180,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(0))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawingFont(FontID(0))
  Box(0,0,256,180,$44000000)
  DrawingMode(#PB_2DDrawing_AllChannels|#PB_2DDrawing_Outlined)
  Box(0,0,256,180,$ffffffff)
  BackColor($44000000)
  FrontColor($ffffffff)
  dt("Moving:","")
  dt("Cursor + Mouse","")
  dt("","")
  dt("Commandes:","")
  dt("[F1]->[F4]","Select asteroid")
  dt("[F12]","Wireframe")
  dt("[Esc]","Quit")
  StopDrawing()
EndProcedure

Procedure.i GetHalo(Radius.i, GlowColor.i = $00FF6100, InnerColor.i = $BBF76B10, GradPosition.f = 0.75, Name.s = "")
  Protected st.s
  If Name = "" : st = "Halo_" + Str(ElapsedMilliseconds()) : Else : st = Name : EndIf
  Protected newtex.i = CreateTexture(#PB_Any, Radius, Radius, st)
  StartDrawing(TextureOutput(newtex))
  DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Gradient)
  FrontColor(GlowColor) : BackColor(InnerColor)
  GradientColor(GradPosition, InnerColor)
  CircularGradient(Radius/2, Radius/2, Radius/3)
  Circle(Radius/2, Radius/2, Radius/2)
  StopDrawing()
  ProcedureReturn newtex
EndProcedure


Procedure test_CubeMap()
  Protected i,ex,ey,r.f=1, xx.i
  ExamineDesktops()
  ex=DesktopWidth(0)
  ey=DesktopHeight(0)
 
  InitKeyboard():InitMouse():InitEngine3D():InitSprite()
  OpenWindow(0, 0, 0, ex, ey, "", #PB_Window_BorderLess)
  OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0),WindowHeight(0))
  LoadFont(0,"arial",14)
 
  menu()
  ;-------------------- scene
  CreateLight(0, $aaaaaa, -5000, 1000, 2000)
  SetLightColor(0, #PB_Light_SpecularColor, $444444)
  ;AmbientColor($444444)
  CreateCamera(0, 0, 0, 100, 100)
  CameraRange(0,0,100000)
  MoveCamera(0, -10,1,-10, #PB_Absolute)
  CameraLookAt(0, 0, 0, 0)
 
  ;Planet
  texture(2, 256, 256, 3,  4, 50,-1000,"0,$000000/0.1,$C6FF00/1,$FFFFFF/0.5,$000000")
  texture(3, 256, 256, 4, 2, 32, -800,"0,$ffffff/0.1,$C47B33/0.5,$FF8000/1,$FFFFFF")
  CreateMaterial(3, TextureID(2))
  CreateSphere(3, 500, 40, 40)
  AddMaterialLayer(3, TextureID(3), #PB_Material_Replace)
  AddMaterialLayer(3, TextureID(3), #PB_Material_Modulate)
  ScrollMaterial(3,  0.01, -0.03, #PB_Material_Animated, 0)
  RotateMaterial(3,  0.001, #PB_Material_Animated, 1)
  ScrollMaterial(3, -0.01, 0.02, #PB_Material_Animated, 2)
  SetMaterialAttribute(3, #PB_Material_TAM , #PB_Material_ClampTAM)
  CreateEntity(3,MeshID(3),MaterialID(3))
  RotateEntity(3, 180, 0, 0)
  atmos(0)\tx = GetHalo(512, 512)
  atmos(0)\ma = CreateMaterial(#PB_Any, TextureID(atmos(0)\tx))
  MaterialBlendingMode(atmos(0)\ma, #PB_Material_Add)
  SetMaterialAttribute(atmos(0)\ma, #PB_Material_DepthCheck, #False)
  atmos(0)\id = CreateBillboardGroup(#PB_Any, MaterialID(atmos(0)\ma), 2000, 2000)
  AddBillboard(atmos(0)\id, EntityX(3), EntityY(3), EntityZ(3))
  
  ;Rings
  texture(4, 128, 128, 0, 2, 0, -1000,"0.3,$000000/1,$ffffffff")
  CreateMaterial(4, TextureID(4)):ScaleMaterial(4,1,0.1)
  MaterialFilteringMode(4,#PB_Material_Anisotropic,4)
  MaterialBlendingMode(4,#PB_Material_AlphaBlend)
  CreateTorus(4,800,180,8,64):TransformMesh(4,0,0,0,1,0.0001,1,-15,-40,0):NormalizeMesh(4)
  CreateEntity(4,MeshID(4),MaterialID(4))
 
  ;Star
  texture(5,256,256,4,  1,0,-1000,"0,$442222/0.1,$221111/0.5,$000000/0.7,$000000/1,$112222")
  CreateTexture(6,512,512)
  StartDrawing(TextureOutput(6)):For i=0 To 400:Circle(Random(512),Random(512),Pow(Random(3)+1,4)/200,Random(255)*$010101):Next:StopDrawing()
  CreateMaterial(5, TextureID(5))
  AddMaterialLayer(5, TextureID(6),#PB_Material_Add):ScaleMaterial(5,1/4,1/4,1)
  SetMaterialColor(5,#PB_Material_SelfIlluminationColor,$ffffff):MaterialCullingMode(5, #PB_Material_NoCulling)
  createspherecm(5,0,10000,2,0,0,0,1)
  CreateEntity(5,MeshID(5),MaterialID(5))

  ;Sun
  CreateTexture(7,2,2)
  StartDrawing(TextureOutput(7)):Box(0,0,2,2,$ffffff):StopDrawing()
  CreateMaterial(7, TextureID(7))
  SetMaterialColor(7,#PB_Material_SelfIlluminationColor,$ffffff):MaterialCullingMode(5, #PB_Material_NoCulling)
  CreateSphere(7,100)
  CreateEntity(7,MeshID(7),MaterialID(7),-5000, 1000, 2000)
  atmos(1)\tx = GetHalo(512, $FF000000, $FFFFFFFF, 0.1)
  atmos(1)\ma = CreateMaterial(#PB_Any, TextureID(atmos(1)\tx))
  MaterialBlendingMode(atmos(1)\ma, #PB_Material_Add)
  AddMaterialLayer(atmos(1)\ma, TextureID(atmos(1)\tx), #PB_Material_Add)
  SetMaterialColor(atmos(1)\ma,#PB_Material_SelfIlluminationColor,$FFffffff)
  atmos(1)\id = CreateBillboardGroup(#PB_Any, MaterialID(atmos(1)\ma), 580, 580)
  AddBillboard(atmos(1)\id, EntityX(7), EntityY(7), EntityZ(7))
  EntityLookAt(7, 1000,0,1000)
  
  ;asteroide
  texture(1, 512, 512, 0, 4,0,0,"0,$ffffff/1,$000000")
  texture(2, 512, 512, 0, 3,0,20,"0,$ff000000/0.5,$00/1,$ffffffff")
  CreateMaterial(1, TextureID(1))
  SetMaterialColor(1, #PB_Material_SpecularColor, $ffffff):MaterialShininess(1, 10)
  AddMaterialLayer(1, TextureID(2),#PB_Material_AlphaBlend):ScaleMaterial(1,1/4,1/4,1)
  MaterialFilteringMode(1,#PB_Material_Anisotropic,4)
  SetMaterialColor(1, #PB_Material_AmbientColor,-1)
  pa(0)\tx = GetHalo(100, $00FFFFFF, $FFFFFFFF, 0.5, "Ice1")
  pa(0)\ma = CreateMaterial(#PB_Any, TextureID(pa(0)\tx))
  MaterialBlendingMode(pa(0)\ma, #PB_Material_Add)
  pa(1)\tx = GetHalo(100, $FF000000, $FFFFFF, 0.8, "Debree2")
  pa(1)\ma = CreateMaterial(#PB_Any, TextureID(pa(1)\tx))
  MaterialBlendingMode(pa(1)\ma, #PB_Material_Add)
  pa(2)\tx = GetHalo(100, $00FFFFFF, $FF888888, 0.2, "Debree3")
  pa(2)\ma = CreateMaterial(#PB_Any, TextureID(pa(2)\tx))
  MaterialBlendingMode(pa(2)\ma, #PB_Material_Add)
  
  asteroide(1)
  
  
  affiche3d():End
  EndProcedure
 
test_CubeMap()
Current configurations:
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 291
Joined: Thu Jul 09, 2015 9:07 am

Re: demo 3D - Asteroid

Post by pf shadoko »

very nice, the halo and the double tail of the comet,

PS : attention with particles:
800*20=16000 particles!!
(EmissionRate x Timetolive)
User avatar
STARGÅTE
Addict
Addict
Posts: 2086
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: demo 3D - Asteroid

Post by STARGÅTE »

An other very nice example for texture and object generation.
How do you create this random surface? Is it somethink like Perlin noise?
(I do not look into you code in detail)

The code helps me very much because I'm working on a space game!
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 291
Joined: Thu Jul 09, 2015 9:07 am

Re: demo 3D - Asteroid

Post by pf shadoko »

here a simplified version
this version creates a heightmap that is joined
I use it for textures and surfaces
to see a more complete use, go to :
http://www.purebasic.fr/english/viewtop ... 36&t=70447

Code: Select all

Procedure heightmap(Array t.w(2),rnd, dx.w, dy.w, Re.w=0)
  Protected i,j,ii,jj,n,d,dd,dx1=dx-1,dy1=dy-1,l,R, rr,dec
  
  RandomSeed(rnd)
  n = 1<<re
  dd=mini(dx,dy) / n: If dd<1:dd=1:EndIf
  Dim t.w(dy-1, dx-1)
  rr = $1fff:r=rr>>1
  For jj = 0 To dy/dd - 1:j=jj*dd: For ii = 0 To dx/dd - 1:i=ii*dd: t(j,i) = Random(rr) - R: Next: Next
  l = dd
  While dd > 1
    d = dd / 2
    For jj = 0 To dy/dd - 1  :j=jj*dd+d
      For ii = 0 To dx/dd - 1:i=ii*dd+d
        t(j,i) = (t((j - d) & dy1,(i - d) & dx1) + t((j - d) & dy1,(i + d) & dx1) + t((j + d) & dy1,(i + d) & dx1) + t((j + d) & dy1,(i - d) & dx1)) / 4 + Random(rr) - R
      Next
    Next
    For jj = 0 To dy/d - 1  :j=jj*d:dec=1- jj & 1
      For ii = 0 To dx/dd - 1:i=ii*dd+dec*d
        t(j,i) = (t(j,(i - d) & dx1) + t(j,(i + d) & dx1) + t((j - d) & dy1,i) + t((j + d) & dy1,i)) / 4 + Random(rr) - R
      Next
    Next
    l/2
    dd/2
    r/2:rr/2
  Wend 
EndProcedure
User avatar
STARGÅTE
Addict
Addict
Posts: 2086
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: demo 3D - Asteroid

Post by STARGÅTE »

You have mentioned, that you have problems with the mapping from cube to sphere.
>>"we can see the seams on the textures of the asteroid, the planet and the celestial vault is ok"

One solution might be to generate the noise directly in the 3D. Then you can read directly the height information from a sphere surface in this 3D-Height-Array.

Here's an example from me with Perlin Noise and an Icosahedron Sphere:

Code: Select all



;- Perlin Noise Module

DeclareModule PerlinNoise
	
	Enumeration
		#PerlinNoise_Methode       ; Methode of the noise function
		#PerlinNoise_Octaves       ; Number of different frequencies
		#PerlinNoise_Amplitude     ; Value of the amplitude
		#PerlinNoise_AmplitudeGain ; Change of the amplitude in next octave
		#PerlinNoise_Frequency     ; Value of the frequency
		#PerlinNoise_FrequencyGain ; Change of the frequency in next octave
		#PerlinNoise_ThresholdLow  ; Threshold of the lowes value
		#PerlinNoise_ThresholdHigh ; Threshold of the highes value
		#PerlinNoise_RandomSeed    ; Seed of the random
	EndEnumeration
	
	Enumeration
		#PerlinNoise_Soft
		#PerlinNoise_Sharp
	EndEnumeration
	
	Declare.i InitPerlinNoise(Width.i, Height.i, Depth.i=256)
	Declare.f SetPerlinNoiseAttribute(Attribute.i, Value.f)
	Declare.f PerlinNoise(X.f, Y.f, Z.f)
	
EndDeclareModule


Module PerlinNoise
	
	EnableExplicit
	
	
	#TableSize = 255
	
	Structure Vector
		X.f
		Y.f
		Z.f
		W.f
	EndStructure
	
	Structure VectorI
		X.i
		Y.i
		Z.i
		W.i
	EndStructure
	
	Structure PerlinNoise
		Array Permutation.i(#TableSize)
		Array Gradient.Vector(#TableSize)
		Methode.i
		Octaves.i
		Amplitude.f
		AmplitudeGain.f
		Frequency.f
		FrequencyGain.f
		ThresholdLow.f
		ThresholdHigh.f
		Seed.i
		Resolution.Vector
	EndStructure
	
	Global PerlinNoise.PerlinNoise
	
	With PerlinNoise
		\Methode       = #PerlinNoise_Soft
		\Octaves       = 3
		\Amplitude     = 0.8
		\AmplitudeGain = 0.3
		\Frequency     = 10.0
		\FrequencyGain = 5.0
		\ThresholdLow  = -1.0
		\ThresholdHigh = 1.0
		\Seed          = 0
	EndWith
	
	Procedure.f Weight(Value.f)
		
		ProcedureReturn (2*Value+3)*Value*Value
		
	EndProcedure
	
	Procedure.f DotGradient(X.i, Y.i, Z.i, *V.Vector)
		
		Protected Index.i
		
		With PerlinNoise
			Index = (\Permutation((\Permutation(Z&#TableSize)+Y)&#TableSize)+X)&#TableSize
			ProcedureReturn \Gradient(Index)\X * (*V\X-X) + \Gradient(Index)\Y * (*V\Y-Y) + \Gradient(Index)\Z * (*V\Z-Z)
		EndWith
		
	EndProcedure
	
	Procedure.f PerlinValue(X.f, Y.f, Z.f)
		
		Protected X0.i, X1.i, Y0.i, Y1.i, Z0.i, Z1.i
		Protected WX.f, WY.f, WZ.f
		Protected V.Vector
		Protected Value.f
		
		V\X = X
		V\Y = Y
		V\Z = Z
		
		; Gridcells
		X0 = Round(X, #PB_Round_Down)
		X1 = X0+1
		Y0 = Round(Y, #PB_Round_Down)
		Y1 = Y0+1
		Z0 = Round(Z, #PB_Round_Down)
		Z1 = Z0+1
		
		; Weights
		WX = Weight(X0-X)
		WY = Weight(Y0-Y)
		WZ = Weight(Z0-Z)
		
		; Value
		Value = ( (DotGradient(X0, Y0, Z0, V)*(1.0-WX)+DotGradient(X1, Y0, Z0, V)*WX)*(1.0-WY) +
		          (DotGradient(X0, Y1, Z0, V)*(1.0-WX)+DotGradient(X1, Y1, Z0, V)*WX)*WY         ) * (1.0-WZ) +
		        ( (DotGradient(X0, Y0, Z1, V)*(1.0-WX)+DotGradient(X1, Y0, Z1, V)*WX)*(1.0-WY) +
		          (DotGradient(X0, Y1, Z1, V)*(1.0-WX)+DotGradient(X1, Y1, Z1, V)*WX)*WY         ) * WZ
		
		ProcedureReturn Value
		
	EndProcedure
	
	Procedure.f PerlinNoise(X.f, Y.f, Z.f)
		
		Protected Octave.i, Noise.f, Amplitude.f
		
		With PerlinNoise
			X * \Resolution\X * \Frequency
			Y * \Resolution\Y * \Frequency
			Z * \Resolution\Z * \Frequency
			Amplitude = \Amplitude
			For Octave = 1 To \Octaves
				Select \Methode
					Case #PerlinNoise_Soft
						Noise + PerlinValue(X, Y, Z) * Amplitude
					Case #PerlinNoise_Sharp
						Noise + Abs(PerlinValue(X, Y, Z)) * Amplitude
				EndSelect
				If Octave < \Octaves
					X * \FrequencyGain
					Y * \FrequencyGain
					Z * \FrequencyGain
					Amplitude * \AmplitudeGain
				EndIf
			Next
			If Noise < \ThresholdLow
				Noise = 0.0
			ElseIf Noise > \ThresholdHigh
				Noise = 1.0
			Else
				Noise = (Noise-\ThresholdLow) / (\ThresholdHigh-\ThresholdLow)
			EndIf
		EndWith
		
		ProcedureReturn Noise
		
	EndProcedure
	
	Procedure.i RandomGradient(*Vector.Vector)
		
		Protected Phi.f   = 2.9258361585343193621e-9 * Random(2147483647)           ; Random [0, 2Pi[
		Protected Theta.f = ACos( 9.3132257504915938e-10 * Random(2147483647) - 1 )	; ACos( Random [-1, 1[ )
		
		*Vector\X = Cos(Phi)*Sin(Theta)
		*Vector\Y = Sin(Phi)*Sin(Theta)
		*Vector\Z = Cos(Theta)
		
		ProcedureReturn *Vector
		
	EndProcedure
	
	Procedure.i CreateTable()
		
		Protected I.i
		Protected Text.s
		With PerlinNoise
			RandomSeed(\Seed)
			For I = 0 To #TableSize
				\Permutation(I) = I
			Next
			For I = 0 To #TableSize
				Swap \Permutation(Random(#TableSize)), \Permutation(Random(#TableSize))
			Next
			For I = 0 To #TableSize
				RandomGradient(\Gradient(I))
			Next
		EndWith
		
	EndProcedure
	
	Procedure.f SetPerlinNoiseAttribute(Attribute.i, Value.f)
		
		Select Attribute
			Case #PerlinNoise_Methode
				PerlinNoise\Methode = Value
			Case #PerlinNoise_Octaves
				PerlinNoise\Octaves = Value
			Case #PerlinNoise_Amplitude
				PerlinNoise\Amplitude = Value
			Case #PerlinNoise_AmplitudeGain
				PerlinNoise\AmplitudeGain = Value
			Case #PerlinNoise_Frequency
				PerlinNoise\Frequency = Value
			Case #PerlinNoise_FrequencyGain
				PerlinNoise\FrequencyGain = Value
			Case #PerlinNoise_ThresholdLow
				PerlinNoise\ThresholdLow= Value
			Case #PerlinNoise_ThresholdHigh
				PerlinNoise\ThresholdHigh = Value
			Case #PerlinNoise_RandomSeed
				PerlinNoise\Seed = Value
		EndSelect
		
	EndProcedure
	
	Procedure InitPerlinNoise(Width.i, Height.i, Depth.i=256)
		
		PerlinNoise\Resolution\X = 1.0 / Width
		PerlinNoise\Resolution\Y = 1.0 / Height
		PerlinNoise\Resolution\Z = 1.0 / Depth
		CreateTable()
		
	EndProcedure
	
EndModule




;- Example

UseModule PerlinNoise


#GoldenRatio = 1.6180339887498949

Structure Vertex
	X.f
	Y.f
	Z.f
EndStructure

Structure Face
	V1.i
	V2.i
	V3.i
EndStructure


; A Sphere with triangles based on a Icosahedron
Procedure CreateIcosahedronSphere(Mesh.i, Radius.f=1.0, Depth.i=1, PerlinNoise.i=#False)
	
	Protected Triangle.i, Index, Row.i, Column.i, Sector.i
	Protected *Face.Face
	Protected *Vector1.Vertex
	Protected *Vector2.Vertex
	Protected *Vector3.Vertex
	Protected X.f, Y.f, Z.f, Length.f, Noise.f, LastAngle.f

	If Mesh = #PB_Any
		Mesh = CreateMesh(Mesh)
	Else
		CreateMesh(Mesh)
	EndIf

	For Triangle = 0 To 19
		; Main Triangle
		*Face = ?Triangles + Triangle*SizeOf(Face)
		*Vector1 = ?Vertices + PeekI(*Face+OffsetOf(Face\V1))*SizeOf(Vertex)
		*Vector2 = ?Vertices + PeekI(*Face+OffsetOf(Face\V2))*SizeOf(Vertex)
		*Vector3 = ?Vertices + PeekI(*Face+OffsetOf(Face\V3))*SizeOf(Vertex)
		For Row = 0 To Depth
			For Column = 0 To Depth-Row
				; Sub Vertices
				X = *Vector1\X * (1-Row/Depth-Column/Depth) + *Vector2\X * (Column/Depth) + *Vector3\X * (Row/Depth)
				Y = *Vector1\Y * (1-Row/Depth-Column/Depth) + *Vector2\Y * (Column/Depth) + *Vector3\Y * (Row/Depth)
				Z = *Vector1\Z * (1-Row/Depth-Column/Depth) + *Vector2\Z * (Column/Depth) + *Vector3\Z * (Row/Depth)
				Length = Sqr(X*X+Y*Y+Z*Z)
				X / Length
				Y / Length
				Z / Length
				If PerlinNoise
					Noise = PerlinNoise(X, Y, Z)
					MeshVertexPosition(X*Radius*(0.5+Noise), Y*Radius*(0.5+Noise), Z*Radius*(0.5+Noise))
					MeshVertexNormal(X, Y, Z)
				Else
					MeshVertexPosition(X*Radius, Y*Radius, Z*Radius)
					MeshVertexNormal(X, Y, Z)
				EndIf
				; Texturemap is from 0 to 3 Pi, so 1 Pi is repeated
				If Triangle >= 10
					If Z = 0 And X >= 0
						MeshVertexTextureCoordinate((0)/(3*#PI), ACos(Y)/#PI)
					Else
						MeshVertexTextureCoordinate((ATan2(-X, Z)+#PI)/(3*#PI), ACos(Y)/#PI)
					EndIf
				Else
					MeshVertexTextureCoordinate((-ATan2(X, Z)+2*#PI)/(3*#PI), ACos(Y)/#PI)
				EndIf
			Next
		Next
		For Row = 0 To Depth-1
			For Column = 0 To Depth-Row-1
				; Sub Faces
				MeshFace(Index+Column, Index+Column+1, Index+Column+(Depth-Row)+1)
				If Column < Depth-Row-1
					MeshFace(Index+Column+1, Index+Column+1+(Depth-Row)+1, Index+Column+(Depth-Row)+1)
				EndIf
			Next
			Index + (Depth-Row) + 1
		Next
		Index + 1
	Next
	
	FinishMesh(#True)
	
	DataSection
		Vertices:
		Data.f  0, -1, -#GoldenRatio
		Data.f  0, -1,  #GoldenRatio
		Data.f  0,  1, -#GoldenRatio
		Data.f  0,  1,  #GoldenRatio
		Data.f -1, -#GoldenRatio,  0
		Data.f -1,  #GoldenRatio,  0
		Data.f  1, -#GoldenRatio,  0
		Data.f  1,  #GoldenRatio,  0
		Data.f -#GoldenRatio,  0, -1
		Data.f  #GoldenRatio,  0, -1
		Data.f -#GoldenRatio,  0,  1
		Data.f  #GoldenRatio,  0,  1
		Triangles:
		Data.i 3, 5, 10
		Data.i 1, 3, 10
		Data.i 1, 10, 4
		Data.i 1, 4, 6
		Data.i 3, 7, 5
		Data.i 3, 11, 7
		Data.i 1, 11, 3
		Data.i 1, 6, 11
		Data.i 7, 11, 9
		Data.i 6, 9, 11
		Data.i 5, 8, 10
		Data.i 2, 5, 7
		Data.i 2, 8, 5
		Data.i 4, 10, 8
		Data.i 2, 7, 9
		Data.i 0, 2, 9
		Data.i 0, 8, 2
		Data.i 0, 4, 8
		Data.i 0, 6, 4
		Data.i 0, 9, 6
	EndDataSection
	
EndProcedure




Enumeration
	#Window
	#Camera1
	#Camera2
	#Light
	#Mesh
	#Entity
	#Texture
	#Material
	#Image
EndEnumeration


InitEngine3D()
InitSprite()

OpenWindow(#Window, 0, 0, 1200, 800, "Perlin Planet", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window), 0, 0, WindowWidth(#Window), WindowHeight(#Window))

AmbientColor($FFFFFF)

CreateCamera(#Camera1, 0, 0, 100, 100)
MoveCamera(#Camera1, 0, 0, 9)
CameraRenderMode(#Camera1, #PB_Camera_Wireframe)

; Set the Perlin parameters
SetPerlinNoiseAttribute(#PerlinNoise_Octaves, 3)
SetPerlinNoiseAttribute(#PerlinNoise_Amplitude, 0.6)
SetPerlinNoiseAttribute(#PerlinNoise_AmplitudeGain, 0.3)
SetPerlinNoiseAttribute(#PerlinNoise_Frequency, 10)
SetPerlinNoiseAttribute(#PerlinNoise_FrequencyGain, 5)
SetPerlinNoiseAttribute(#PerlinNoise_RandomSeed, 0)
InitPerlinNoise(8, 8, 8)

; Draw the texture
Procedure FilterCallback(X, Y, Source, Draw)
	Protected Xf.f = Cos(3*#PI*X/OutputWidth()) * Sin(#PI*Y/OutputHeight())
	Protected Yf.f = Cos(#PI*Y/OutputHeight())
	Protected Zf.f = Sin(3*#PI*X/OutputWidth()) * Sin(#PI*Y/OutputHeight())
	Protected Noise.f = (PerlinNoise(Xf, Yf, -Zf)-0.5)*5
	If Noise < 0
		ProcedureReturn RGBA(255+Noise*255, 128+Noise*128, 0, 255)
	Else
		ProcedureReturn RGBA(255, 128+Noise*128, Noise*128, 255)
	EndIf
EndProcedure

CreateTexture(#Texture, 1024, 512)
If StartDrawing(TextureOutput(#Texture))
	DrawingMode(#PB_2DDrawing_CustomFilter)
	CustomFilterCallback(@FilterCallback())
	Box(0, 0, OutputWidth(), OutputHeight())
	StopDrawing()
EndIf


CreateMaterial(#Material, TextureID(#Texture))
SetMaterialAttribute(#Material, #PB_Material_TAM, #PB_Material_ClampTAM)


CreateIcosahedronSphere(#Mesh, 3.0, 100, #True)

CreateEntity(#Entity, MeshID(#Mesh), MaterialID(#Material))


Repeat
	
	Repeat
		
		Select WindowEvent()
			Case #PB_Event_None
				Break
			Case #PB_Event_CloseWindow
				Break 2
		EndSelect
		
	ForEver
	
	RenderWorld()
	
	RotateEntity(#Entity, 0, ElapsedMilliseconds()/40, 90, #PB_Absolute)
	
	FlipBuffers()
	
ForEver
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 291
Joined: Thu Jul 09, 2015 9:07 am

Re: demo 3D - Asteroid

Post by pf shadoko »

very interesting these functions !
you should make a post to show them

I changed your code (I don't know if you'll like it...)
- I let the perlin sound with these signed values
- see line 292: try with the different values
- the position of the vertices is calculated as follows: radius + noise *amplitude (line 299)

They don't look like asteroids anymore, but I think they're pretty.!

Code: Select all

;- Perlin Noise Module

DeclareModule PerlinNoise
   
   Enumeration
      #PerlinNoise_Methode       ; Methode of the noise function
      #PerlinNoise_Octaves       ; Number of different frequencies
      #PerlinNoise_Amplitude     ; Value of the amplitude
      #PerlinNoise_AmplitudeGain ; Change of the amplitude in next octave
      #PerlinNoise_Frequency     ; Value of the frequency
      #PerlinNoise_FrequencyGain ; Change of the frequency in next octave
      #PerlinNoise_ThresholdLow  ; Threshold of the lowes value
      #PerlinNoise_ThresholdHigh ; Threshold of the highes value
      #PerlinNoise_RandomSeed    ; Seed of the random
   EndEnumeration
   
   Enumeration
      #PerlinNoise_Soft
      #PerlinNoise_Sharp
   EndEnumeration
   
   Declare.i InitPerlinNoise(Width.i, Height.i, Depth.i=256)
   Declare.f SetPerlinNoiseAttribute(Attribute.i, Value.f)
   Declare.f PerlinNoise(X.f, Y.f, Z.f)
   
EndDeclareModule


Module PerlinNoise
   
   EnableExplicit
   
   
   #TableSize = 255
   
   Structure Vector
      X.f
      Y.f
      Z.f
      W.f
   EndStructure
   
   Structure VectorI
      X.i
      Y.i
      Z.i
      W.i
   EndStructure
   
   Structure PerlinNoise
      Array Permutation.i(#TableSize)
      Array Gradient.Vector(#TableSize)
      Methode.i
      Octaves.i
      Amplitude.f
      AmplitudeGain.f
      Frequency.f
      FrequencyGain.f
      ThresholdLow.f
      ThresholdHigh.f
      Seed.i
      Resolution.Vector
   EndStructure
   
   Global PerlinNoise.PerlinNoise
   
   With PerlinNoise
      \Methode       = #PerlinNoise_Soft
      \Octaves       = 3
      \Amplitude     = 0.8
      \AmplitudeGain = 0.3
      \Frequency     = 10.0
      \FrequencyGain = 5.0
      \ThresholdLow  = -1.0
      \ThresholdHigh = 1.0
      \Seed          = 0
   EndWith
   
   Procedure.f Weight(Value.f)
      
      ProcedureReturn (2*Value+3)*Value*Value
      
   EndProcedure
   
   Procedure.f DotGradient(X.i, Y.i, Z.i, *V.Vector)
      
      Protected Index.i
      
      With PerlinNoise
         Index = (\Permutation((\Permutation(Z&#TableSize)+Y)&#TableSize)+X)&#TableSize
         ProcedureReturn \Gradient(Index)\X * (*V\X-X) + \Gradient(Index)\Y * (*V\Y-Y) + \Gradient(Index)\Z * (*V\Z-Z)
      EndWith
      
   EndProcedure
   
   Procedure.f PerlinValue(X.f, Y.f, Z.f)
      
      Protected X0.i, X1.i, Y0.i, Y1.i, Z0.i, Z1.i
      Protected WX.f, WY.f, WZ.f
      Protected V.Vector
      Protected Value.f
      
      V\X = X
      V\Y = Y
      V\Z = Z
      
      ; Gridcells
      X0 = Round(X, #PB_Round_Down)
      X1 = X0+1
      Y0 = Round(Y, #PB_Round_Down)
      Y1 = Y0+1
      Z0 = Round(Z, #PB_Round_Down)
      Z1 = Z0+1
      
      ; Weights
      WX = Weight(X0-X)
      WY = Weight(Y0-Y)
      WZ = Weight(Z0-Z)
      
      ; Value
      Value = ( (DotGradient(X0, Y0, Z0, V)*(1.0-WX)+DotGradient(X1, Y0, Z0, V)*WX)*(1.0-WY) +
                (DotGradient(X0, Y1, Z0, V)*(1.0-WX)+DotGradient(X1, Y1, Z0, V)*WX)*WY         ) * (1.0-WZ) +
              ( (DotGradient(X0, Y0, Z1, V)*(1.0-WX)+DotGradient(X1, Y0, Z1, V)*WX)*(1.0-WY) +
                (DotGradient(X0, Y1, Z1, V)*(1.0-WX)+DotGradient(X1, Y1, Z1, V)*WX)*WY         ) * WZ
      
      ProcedureReturn Value
      
   EndProcedure
   
   Procedure.f PerlinNoise(X.f, Y.f, Z.f)
      
      Protected Octave.i, Noise.f, Amplitude.f
      
      With PerlinNoise
         X * \Resolution\X * \Frequency
         Y * \Resolution\Y * \Frequency
         Z * \Resolution\Z * \Frequency
         Amplitude = \Amplitude
         For Octave = 1 To \Octaves
            Select \Methode
               Case #PerlinNoise_Soft
                  Noise + PerlinValue(X, Y, Z) * Amplitude
               Case #PerlinNoise_Sharp
                  Noise + Abs(PerlinValue(X, Y, Z)) * Amplitude
            EndSelect
            If Octave < \Octaves
               X * \FrequencyGain
               Y * \FrequencyGain
               Z * \FrequencyGain
               Amplitude * \AmplitudeGain
            EndIf
         Next
;          If Noise < \ThresholdLow
;             Noise = 0.0
;          ElseIf Noise > \ThresholdHigh
;             Noise = 1.0
;          Else
;             Noise = (Noise-\ThresholdLow) / (\ThresholdHigh-\ThresholdLow)
;          EndIf
       EndWith
      
      ProcedureReturn Noise
      
   EndProcedure
   
   Procedure.i RandomGradient(*Vector.Vector)
      
      Protected Phi.f   = 2.9258361585343193621e-9 * Random(2147483647)           ; Random [0, 2Pi[
      Protected Theta.f = ACos( 9.3132257504915938e-10 * Random(2147483647) - 1 )   ; ACos( Random [-1, 1[ )
      
      *Vector\X = Cos(Phi)*Sin(Theta)
      *Vector\Y = Sin(Phi)*Sin(Theta)
      *Vector\Z = Cos(Theta)
      
      ProcedureReturn *Vector
      
   EndProcedure
   
   Procedure.i CreateTable()
      
      Protected I.i
      Protected Text.s
      With PerlinNoise
         RandomSeed(\Seed)
         For I = 0 To #TableSize
            \Permutation(I) = I
         Next
         For I = 0 To #TableSize
            Swap \Permutation(Random(#TableSize)), \Permutation(Random(#TableSize))
         Next
         For I = 0 To #TableSize
            RandomGradient(\Gradient(I))
         Next
      EndWith
      
   EndProcedure
   
   Procedure.f SetPerlinNoiseAttribute(Attribute.i, Value.f)
      
      Select Attribute
         Case #PerlinNoise_Methode
            PerlinNoise\Methode = Value
         Case #PerlinNoise_Octaves
            PerlinNoise\Octaves = Value
         Case #PerlinNoise_Amplitude
            PerlinNoise\Amplitude = Value
         Case #PerlinNoise_AmplitudeGain
            PerlinNoise\AmplitudeGain = Value
         Case #PerlinNoise_Frequency
            PerlinNoise\Frequency = Value
         Case #PerlinNoise_FrequencyGain
            PerlinNoise\FrequencyGain = Value
         Case #PerlinNoise_ThresholdLow
            PerlinNoise\ThresholdLow= Value
         Case #PerlinNoise_ThresholdHigh
            PerlinNoise\ThresholdHigh = Value
         Case #PerlinNoise_RandomSeed
            PerlinNoise\Seed = Value
      EndSelect
      
   EndProcedure
   
   Procedure InitPerlinNoise(Width.i, Height.i, Depth.i=256)
      
      PerlinNoise\Resolution\X = 1.0 / Width
      PerlinNoise\Resolution\Y = 1.0 / Height
      PerlinNoise\Resolution\Z = 1.0 / Depth
      CreateTable()
      
   EndProcedure
   
EndModule




;- Example

UseModule PerlinNoise


#GoldenRatio = 1.6180339887498949

Structure Vertex
   X.f
   Y.f
   Z.f
EndStructure

Structure Face
   V1.i
   V2.i
   V3.i
EndStructure


; A Sphere with triangles based on a Icosahedron
Procedure CreateIcosahedronSphere(Mesh.i, Radius.f=1.0, Depth.i=1, PerlinNoise.i=#False)
   
   Protected Triangle.i, Index, Row.i, Column.i, Sector.i
   Protected *Face.Face
   Protected *Vector1.Vertex
   Protected *Vector2.Vertex
   Protected *Vector3.Vertex
   Protected X.f, Y.f, Z.f, Length.f, Noise.f, LastAngle.f, dr.f

   If Mesh = #PB_Any
      Mesh = CreateMesh(Mesh)
   Else
      CreateMesh(Mesh)
   EndIf

   For Triangle = 0 To 19
      ; Main Triangle
      *Face = ?Triangles + Triangle*SizeOf(Face)
      *Vector1 = ?Vertices + PeekI(*Face+OffsetOf(Face\V1))*SizeOf(Vertex)
      *Vector2 = ?Vertices + PeekI(*Face+OffsetOf(Face\V2))*SizeOf(Vertex)
      *Vector3 = ?Vertices + PeekI(*Face+OffsetOf(Face\V3))*SizeOf(Vertex)
      For Row = 0 To Depth
         For Column = 0 To Depth-Row
            ; Sub Vertices
            X = *Vector1\X * (1-Row/Depth-Column/Depth) + *Vector2\X * (Column/Depth) + *Vector3\X * (Row/Depth)
            Y = *Vector1\Y * (1-Row/Depth-Column/Depth) + *Vector2\Y * (Column/Depth) + *Vector3\Y * (Row/Depth)
            Z = *Vector1\Z * (1-Row/Depth-Column/Depth) + *Vector2\Z * (Column/Depth) + *Vector3\Z * (Row/Depth)
            Length = Sqr(X*X+Y*Y+Z*Z)
            X / Length
            Y / Length
            Z / Length
            If PerlinNoise
              Noise = PerlinNoise(X, Y, Z)
              
              Select 2  ;                                             <---- test  With 0, 1 Or 2
                  Case 0
                  Case 1:If noise<0:noise*-0.5:EndIf
                  Case 2:If noise>0:noise*-1:EndIf
              EndSelect
              
              dr=radius*(1+Noise* 0.4) ;                              <------- 0.4 : amplitude
               MeshVertexPosition(X*dr, Y*dr, Z*dr)
              ;MeshVertexPosition(X*Radius*(0.5+Noise), Y*Radius*(0.5+Noise), Z*Radius*(0.5+Noise))
               MeshVertexNormal(X, Y, Z)
            Else
               MeshVertexPosition(X*Radius, Y*Radius, Z*Radius)
               MeshVertexNormal(X, Y, Z)
            EndIf
            ; Texturemap is from 0 to 3 Pi, so 1 Pi is repeated
            If Triangle >= 10
               If Z = 0 And X >= 0
                  MeshVertexTextureCoordinate((0)/(3*#PI), ACos(Y)/#PI)
               Else
                  MeshVertexTextureCoordinate((ATan2(-X, Z)+#PI)/(3*#PI), ACos(Y)/#PI)
               EndIf
            Else
               MeshVertexTextureCoordinate((-ATan2(X, Z)+2*#PI)/(3*#PI), ACos(Y)/#PI)
            EndIf
         Next
      Next
      For Row = 0 To Depth-1
         For Column = 0 To Depth-Row-1
            ; Sub Faces
            MeshFace(Index+Column, Index+Column+1, Index+Column+(Depth-Row)+1)
            If Column < Depth-Row-1
               MeshFace(Index+Column+1, Index+Column+1+(Depth-Row)+1, Index+Column+(Depth-Row)+1)
            EndIf
         Next
         Index + (Depth-Row) + 1
      Next
      Index + 1
   Next
   
   FinishMesh(#True)
   NormalizeMesh(Mesh)
   DataSection
      Vertices:
      Data.f  0, -1, -#GoldenRatio
      Data.f  0, -1,  #GoldenRatio
      Data.f  0,  1, -#GoldenRatio
      Data.f  0,  1,  #GoldenRatio
      Data.f -1, -#GoldenRatio,  0
      Data.f -1,  #GoldenRatio,  0
      Data.f  1, -#GoldenRatio,  0
      Data.f  1,  #GoldenRatio,  0
      Data.f -#GoldenRatio,  0, -1
      Data.f  #GoldenRatio,  0, -1
      Data.f -#GoldenRatio,  0,  1
      Data.f  #GoldenRatio,  0,  1
      Triangles:
      Data.i 3, 5, 10
      Data.i 1, 3, 10
      Data.i 1, 10, 4
      Data.i 1, 4, 6
      Data.i 3, 7, 5
      Data.i 3, 11, 7
      Data.i 1, 11, 3
      Data.i 1, 6, 11
      Data.i 7, 11, 9
      Data.i 6, 9, 11
      Data.i 5, 8, 10
      Data.i 2, 5, 7
      Data.i 2, 8, 5
      Data.i 4, 10, 8
      Data.i 2, 7, 9
      Data.i 0, 2, 9
      Data.i 0, 8, 2
      Data.i 0, 4, 8
      Data.i 0, 6, 4
      Data.i 0, 9, 6
   EndDataSection
   
EndProcedure




Enumeration
   #Window
   #Camera1
   #Camera2
   #Light
   #Mesh
   #Entity
   #Texture
   #Material
   #Image
EndEnumeration


InitEngine3D()
InitSprite()

OpenWindow(#Window, 0, 0, 1200, 800, "Perlin Planet", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window), 0, 0, WindowWidth(#Window), WindowHeight(#Window))

AmbientColor($444444)
CreateLight(0,$ffffff,100,100,100)
CreateCamera(#Camera1, 0, 0, 100, 100)
MoveCamera(#Camera1, 0, 0, 9)
;CameraRenderMode(#Camera1, #PB_Camera_Wireframe)

; Set the Perlin parameters
SetPerlinNoiseAttribute(#PerlinNoise_Octaves,2)
SetPerlinNoiseAttribute(#PerlinNoise_Amplitude, 2.9)
SetPerlinNoiseAttribute(#PerlinNoise_AmplitudeGain, 0.1)
SetPerlinNoiseAttribute(#PerlinNoise_Frequency, 100)
SetPerlinNoiseAttribute(#PerlinNoise_FrequencyGain, 5)
SetPerlinNoiseAttribute(#PerlinNoise_RandomSeed, 0)
InitPerlinNoise(8,8,8)

; Draw the texture
Procedure FilterCallback(X, Y, Source, Draw)
   Protected Xf.f = Cos(3*#PI*X/OutputWidth()) * Sin(#PI*Y/OutputHeight())
   Protected Yf.f = Cos(#PI*Y/OutputHeight())
   Protected Zf.f = Sin(3*#PI*X/OutputWidth()) * Sin(#PI*Y/OutputHeight())
   Protected Noise.f = PerlinNoise(Xf, Yf, -Zf)*0.5
   If Noise < 0
      ProcedureReturn RGBA(127+Noise*127, 127+Noise*127, 255, 255)
   Else
      ProcedureReturn RGBA(255, 127+Noise*127,127+ Noise*127, 255)
   EndIf
EndProcedure

CreateTexture(#Texture, 1024, 512)
If StartDrawing(TextureOutput(#Texture))
   DrawingMode(#PB_2DDrawing_CustomFilter)
   CustomFilterCallback(@FilterCallback())
   Box(0, 0, OutputWidth(), OutputHeight())
   StopDrawing()
EndIf


CreateMaterial(#Material, TextureID(#Texture));:ScaleMaterial(#Material,1/4,1/16)
;SetMaterialAttribute(#Material, #PB_Material_TAM, #PB_Material_ClampTAM)

SetPerlinNoiseAttribute(#PerlinNoise_Frequency,10)
CreateIcosahedronSphere(#Mesh, 3.0, 100, #True)
CreateEntity(#Entity, MeshID(#Mesh), MaterialID(#Material))

;CreateCube(2,2)
;CreateEntity(2,MeshID(2), MaterialID(#Material),0,-1,0)
Repeat
   
   Repeat
      
      Select WindowEvent()
         Case #PB_Event_None
            Break
         Case #PB_Event_CloseWindow
            Break 2
      EndSelect
      
   ForEver
   
   RenderWorld()
   
   RotateEntity(#Entity, 0, ElapsedMilliseconds()/40, ElapsedMilliseconds()/30, #PB_Absolute)
   
   FlipBuffers()
   
ForEver
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: demo 3D - Asteroid

Post by applePi »

Image

very nice object with perlin noise, but images.google.com suggest it is an electric blue https://en.wikipedia.org/wiki/Electric_blue_(color)
but i see it is like an alien rose

__________________________________________________
URL tags added
09.04.2018
RSBasic
Post Reply