Page 1 of 1

something Hairy ( spiky )

Posted: Sun May 18, 2014 5:45 pm
by applePi
draw a line from a random point on the surface of a sphere to its center (which are here 0,0,0) the x,y,z of that point are determined by a random value of 2 angles, look the comments on the code and also here http://stackoverflow.com/questions/9697 ... f-a-sphere
note that:
s=RandF(0,1)
t=RandF(0,360)
plot a disk of lines of thickness 1 but spreaded to 360 degree
while
s=RandF(0,360)
t=RandF(0,360)
plot a full sphere of lines, change the values to have more shapes
for more plans look example MeshManual2.pb in PB 3D examples
the Procedure RandF are from kenmo i think

Code: Select all

#CameraSpeed = 1
Procedure.f RandF(Min.f, Max.f, Resolution.i = 10000)
  ProcedureReturn (Min + (Max - Min) * Random(Resolution) / Resolution)
EndProcedure

IncludeFile #PB_Compiler_Home + "Examples/3D/Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY
  
If InitEngine3D()
  
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Scripts",#PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Packs/desert.zip", #PB_3DArchive_Zip)
    Parse3DScripts()
   
  
   
  InitSprite()
  InitKeyboard()
  InitMouse()
  
    
  If Screen3DRequester()
    r.f = 8
    s.f:t.f
    
    CreateMesh(0, #PB_Mesh_LineList , #PB_Mesh_Static)
    For i=1 To 300
      ;s is the angle around the z-axis
      ;t is the height angle, measured 'down' from the z-axis. 
    ;s=RandF(0,1)
    ;t=RandF(0,360)
    s=RandF(0,360)
    t=RandF(0,360)
    s=Radian(s)
    t=Radian(t)
    x.f = r * Cos(s) * Sin(t)
    y.f = r * Sin(s) * Sin(t)
    z.f = r * Cos(t)
    MeshVertexColor(RGB(Random(255),Random(255),Random(255))) 
    MeshVertexPosition(0, 0, 0) 
    MeshVertexPosition(x, y, z) 
    
    
    
    Next
    FinishMesh(#True)
    
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    SetMeshMaterial(0, MaterialID(0))
    
    CreateEntity(0,MeshID(0),MaterialID(0) )
    
    ; Camera
    ;
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0, 20, 5, 20, #PB_Absolute)
    CameraLookAt(0, 0, 0, 0)
    
    Repeat
      Screen3DEvents()
          
      If ExamineKeyboard()
       
      EndIf
     
      RotateEntity(0, 0.5,1,0.5,#PB_Relative)
      RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
    
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
  
End

Re: something Hairy

Posted: Sun May 18, 2014 6:31 pm
by IdeasVacuum
...nice! More spikey than hairy though :D

Re: something Hairy

Posted: Sun May 18, 2014 10:45 pm
by T4r4ntul4
cool!

first thing what came to my mind was 'grass' so i had to edit it and here it is:

Code: Select all

#CameraSpeed = 1
Procedure.f RandF(Min.f, Max.f, Resolution.i = 10000)
  ProcedureReturn (Min + (Max - Min) * Random(Resolution) / Resolution)
EndProcedure

IncludeFile #PB_Compiler_Home + "Examples/3D/Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY
 
If InitEngine3D()
 
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Scripts",#PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Packs/desert.zip", #PB_3DArchive_Zip)
    Parse3DScripts()
   
  InitSprite()
  InitKeyboard()
  InitMouse()
 
   
  If Screen3DRequester()
   
    CreateMesh(0, #PB_Mesh_LineList , #PB_Mesh_Static)
    For i=1 To 600

    x = Random(50)
    y = Random(30)
    z = Random(50)
    
    x2 = Random(5)
    y2 = Random(5)
    
    MeshVertexColor(RGB(Random(100),Random(255),Random(100)))
    MeshVertexPosition(x-50, 0, z-50)
    MeshVertexPosition((x-50)+x2, y, (z-50)+y2)
   
   
   
    Next
    FinishMesh(#True)
   
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    SetMeshMaterial(0, MaterialID(0))
   
    CreateEntity(0,MeshID(0),MaterialID(0) )
   
    ; Camera
    ;
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0, 120, 20, 120, #PB_Absolute)
    CameraLookAt(0, 0, 0, 0)
   
    Repeat
      Screen3DEvents()
         
      If ExamineKeyboard()
       
      EndIf
     
      RotateEntity(0, 0,1,0,#PB_Relative)
      RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
   
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
 
End

Re: something Hairy

Posted: Mon May 19, 2014 9:16 am
by applePi
thats cool grass thanks, i have tried to move its upper tip as in wind, just a show case and not optimal nor correct until finding better formula, it is by storing the mesh in array such as MeshData, and then updating the array elements which refer to grass upper tip (For i=1 To ArrSize Step 2)

uncomment lines 37 - 38 (SortStructuredArray(MeshData...) to have funny mesh

also to modify centerpoint of a mesh to rotate around itself correctly (haven't tried it yet here):
http://www.forums.purebasic.com/english ... 36&t=56753
which have a reference to Comtois solution here:
http://www.purebasic.fr/english/viewtop ... 15#p417666

Code: Select all

#CameraSpeed = 1
Procedure.f RandF(Min.f, Max.f, Resolution.i = 10000)
  ProcedureReturn (Min + (Max - Min) * Random(Resolution) / Resolution)
EndProcedure

IncludeFile #PB_Compiler_Home + "Examples/3D/Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY
Global Dim MeshData.PB_MeshVertex(0)

Global xx.f, yy.f
Global ArrSize

Declare CreateMatrix()
Declare UpdateMatrix()

 
If InitEngine3D()
 
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Scripts",#PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Packs/desert.zip", #PB_3DArchive_Zip)
  Parse3DScripts()
   
  InitSprite()
  InitKeyboard()
  InitMouse()
 
   
  If Screen3DRequester()
    
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    CreateMatrix()
    ArrSize = ArraySize(MeshData())
    ;Debug "ArraySize(MeshData()) =  " + Str(ArrSize)
    ;SortStructuredArray(MeshData(), #PB_Sort_Ascending , OffsetOf(PB_MeshVertex\y), TypeOf(PB_MeshVertex\y))
    ;SetMeshData(0,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(0,0)-1)
    For c=0 To ArrSize
      Debug MeshData(c)\x ; data sorted on y
      Debug MeshData(c)\y
      Debug MeshData(c)\z
      Debug Chr(10)+Chr(13)
    Next c

   
    ; Camera
    ;
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0, 120, 40, 120, #PB_Absolute)
    CameraLookAt(0, 0, 0, 0)
   
    Repeat
      Screen3DEvents()
         
      If ExamineKeyboard()
                
        If KeyboardPushed(#PB_Key_Right)
          xx + 0.4 :UpdateMatrix()
        ElseIf KeyboardPushed(#PB_Key_Left) 
          xx - 0.4 :UpdateMatrix()
        EndIf
        xx + 0.4
       If xx>360:xx=0:EndIf
        UpdateMatrix()
        
      EndIf
     
      RotateEntity(0, 0,1,0,#PB_Relative)
      RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
   
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
 
End

Procedure CreateMatrix()
  
  CreateMesh(0, #PB_Mesh_LineList , #True)
  SetMeshMaterial(0, MaterialID(0))
    For i=1 To 300

    x = Random(50)
    y = Random(30)
    z = Random(50)
    
    x2 = Random(5)
    y2 = Random(5)
    
    
    MeshVertexColor(RGB(Random(100),Random(255),Random(100)))
    MeshVertexPosition(x-50, 0, z-50)
    MeshVertexPosition((x-50)+x2, y, (z-50)+y2)
    
    Next
    FinishMesh(#True)
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    SetMeshMaterial(0, MaterialID(0))
   
    CreateEntity(0,MeshID(0),MaterialID(0) )
      
    ;ScaleEntity(0, 2, 2, 2)
    ;oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
  GetMeshData(0,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(0)-1)
  
EndProcedure



  Procedure UpdateMatrix()
    For i=1 To ArrSize Step 2
    
      MeshData(i)\x + Sin(xx)
      ;MeshData(i)\y + Sin(xx)
      MeshData(i)\z + Sin(xx)

    Next  
     
      SetMeshData(0,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(0)-1)
      
    EndProcedure
    

Re: something Hairy

Posted: Mon May 19, 2014 9:55 am
by IdeasVacuum
Nice work chaps, in fact very educational. 8)

Re: something Hairy

Posted: Mon May 19, 2014 1:36 pm
by T4r4ntul4
it seems there's a storm raging over that grass :lol:

Re: something Hairy

Posted: Fri May 23, 2014 12:13 pm
by applePi
spiky ball (thanks IdeasVacuum)
until i find a way to invest the vertex normals (such as MeshData(i)\NormalX ...) to orient the line or the cylinder perpendicular to the sphere at that vertex, here is another way for lines only since we know the start point and the end point of the line (but does not work for a cylinder in a position other than vertex 0: (there is FetchOrientation(EntityID(0)), don't know if FetchVertexOrientation(MeshID(0), VertexIndex) are possible
we create a big sphere , we depends on the line equation between the sphere center and the the vertices at the sphere surface to deduce another point outside so to extend the line , then we choose the start point from the vertex and the end point the deduced point.
http://mathcentral.uregina.ca/QQ/databa ... rray2.html
we position a small sphere over every vertex
and for research we position a cylinder over vertex 0, it does not work for other vertices.
Image

press W to toggle wireFrame

Code: Select all

#CameraSpeed = 1
#sphere      = 50

Procedure.f RandF(Min.f, Max.f, Resolution.i = 10000)
  ProcedureReturn (Min + (Max - Min) * Random(Resolution) / Resolution)
EndProcedure

Global Dim MeshData.PB_MeshVertex(0)

Global xx.f, yy.f
Global ArrSize

Define.f KeyX, KeyY, MouseX, MouseY

Enumeration
  #Window
  #Plane
  #Camera
  #Light1
  #Light2
  #rod
EndEnumeration

If InitEngine3D()
  
  Add3DArchive("\", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Models", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Scripts",#PB_3DArchive_FileSystem)
    
  Parse3DScripts()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)
Total=50

If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "spikey , W toggle wireFrame ")
  If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
  
    CreateMaterial(3, LoadTexture(3, "snow_1024.jpg"))
    DisableMaterialLighting(3, #False)
    SetMaterialColor(3, #PB_Material_AmbientColor, RGB(250, 255, 0))
    SetMaterialColor(3, #PB_Material_SpecularColor, RGB(255, 255, 0))
    
        
    CreatePlane(#Plane, 150, 150, 1, 1, 10, 10)
    CreateEntity(#Plane,MeshID(#Plane),MaterialID(3),0.1,-10,0.2)

    r.f = 3
    s.f:t.f
    
    CreateMaterial(1, LoadTexture(1, "Dirt.jpg"))
    MaterialCullingMode(1, #PB_Material_NoCulling)

    CreateMaterial(2, LoadTexture(2, "RustySteel.jpg"))
       
    CreateSphere(#sphere,3,8,8)
    CreateEntity(#sphere,MeshID(#sphere), MaterialID(1),0,0,0 )
   
    NormalizeMesh(#sphere)
        
    GetMeshData(#sphere,0, MeshData(), #PB_Mesh_Vertex | #PB_Mesh_Normal , 0, MeshVertexCount(#sphere)-1)
    ArrSize = ArraySize(MeshData())
    ;Debug ArrSize
       
    For c=0 To ArrSize ; create many small spheres to position later over the big sphere vertices
      CopyEntity(#sphere, c+700)
      ScaleEntity(c+700, 0.05, 0.05, 0.05)
      SetEntityMaterial(c+700, MaterialID(2))

    Next c
    
    ;;spikes (lines)
    CreateMesh(0, #PB_Mesh_LineList , #PB_Mesh_Static) ; spikes from lines
    For c=0 To ArrSize
      
      ;start point of the line (spike) are on a vertex
      x.f = MeshData(c)\x 
      y.f = MeshData(c)\y
      z.f = MeshData(c)\z
      
      ;(x,y,z) = (1,6,3) + t(7,-4,4) = (1 + 7t, 6 - 4t, 3 + 4t).
      ;from the parametric equation of a line we get the End point of the line (spike)
      ;(x,y,z) = t*(MeshData(c)\x, MeshData(c)\y, MeshData(c)\z) 
      x2.f = 3*MeshData(c)\x
      y2.f = 3*MeshData(c)\y
      z2.f = 3*MeshData(c)\z
      
      MeshVertexColor(RGB(0,0,0))
      MeshVertexPosition(x, y, z) 
      MeshVertexPosition(x2, y2, z2)
      
      MoveEntity(c+700, x,y,z, #PB_Absolute); position a small sphere on a vertex
      If c=0 ; just to make the small sphere on the vertex bigger and to position another rod
        ScaleEntity(c+700, 3, 3, 3)
        CreateCylinder(#rod, 0.1, 7)
        CreateEntity(#rod,MeshID(#rod), MaterialID(2))
        MoveEntity(#rod, x,y,z, #PB_Absolute)
        AttachEntityObject(#sphere, "", EntityID(#rod))
      EndIf 
      
      AttachEntityObject(#sphere, "", EntityID(c+700)) ; attach the small sphers to the big sphere
      
    Next c
   
    
    FinishMesh(#True) ; finish the lines (spikes) collections mesh
    
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    SetMeshMaterial(0, MaterialID(0))
    CreateEntity(0,MeshID(0),MaterialID(0))
    AttachEntityObject(0,"",EntityID(#sphere))
    ;SortStructuredArray(MeshData(), #PB_Sort_Ascending , OffsetOf(PB_MeshVertex\y), TypeOf(PB_MeshVertex\y))
    ;SetMeshData(#sphere,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(#sphere,0)-1)
    ;;oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
   
   
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, 0, 5, 20, #PB_Absolute)
    CameraLookAt(#Camera,0,0,0)
    CameraBackColor(#Camera, RGB(0,100,0))


    CreateLight(#Light1, RGB(0, 0, 0), -20, 40, 20)
    SetLightColor(#Light1, #PB_Light_DiffuseColor, RGB(255,255,255))
    CreateLight(#Light2, RGB(0, 0, 0), 20, 40, 20)
    SetLightColor(#Light2, #PB_Light_DiffuseColor, RGB(0,0,255))
    
    AmbientColor(RGB(255, 255, 255))

  EndIf
EndIf
;HideEntity(#sphere,1)
wireFrame = 1
    Repeat
      
      If ExamineMouse()
        MouseX = -MouseDeltaX()/20 
        MouseY = -MouseDeltaY()/20
      EndIf
      
          
      If ExamineKeyboard()
      
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -0.2
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = 0.2
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -0.2
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = 0.2
        Else
          KeyY = 0
        EndIf
        
        If KeyboardReleased(#PB_Key_W)
          If wireFrame
          MaterialShadingMode(1, #PB_Material_Wireframe)
          wireFrame ! 1
        Else 
          MaterialShadingMode(1, #PB_Material_Solid)
          wireFrame ! 1
        EndIf
        EndIf
            
      EndIf
  
      RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera(#Camera, KeyX, 0, KeyY)
      
      RotateEntity(0, 0.5,1,0.5,#PB_Relative)
      
      RenderWorld()
      
            
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
    
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
  
End

Re: something Hairy ( spiky )

Posted: Fri May 23, 2014 8:34 pm
by davido
Most interesting. Thank you. :D

Re: something Hairy ( spiky )

Posted: Sat Dec 13, 2014 10:20 am
by applePi
now it is easy to cover the above sphere hair with tubes (or lets say rods) , due to the success in plotting tubes in the coordinate geometry space exactly like we draw lines from x1,y1,z1 point to x2,y2,z2 point . the code are documented except the frenet magical procedures which i know nothing how it works. (may be only William Rowan Hamilton who can imagine exactly how quaternions, rotations, vectors , matrices, and so on, how they works exactly in practice and not only in the exam, i read that several programmers admits they don't understand this mathematical subject but they say who cares just use it, no need to know how the CPU works exactly to use your computer)
Image
some fun things you can experiment:
1- in line 173 TubeXYZ (tube, x.f, y.f,z.f, x2.f, y2.f,z2.f, 0.3, 0.3, 8, 4) change 8 to 2 (the TubeShape) and you will see flat 2D tubes, 3 for triangular tubes
2- change the start and end tube radius like this
TubeXYZ (tube, x.f, y.f,z.f, x2.f, y2.f,z2.f, 0.3, 0.0, 8, 4)
and you will get very spiky sphere
Image
3- in line 115 change it to CreateSphere(#sphere,3,3,6) and you will see a weird triangular sphere with spikes.
change it to CreateSphere(#sphere,3,2,6) and will see a flat 2D sphere with spikes
notes: such 3D compound shapes use it in Geometry demonstration, and not physics, unless you manage to accept the collision are only to the big sphere
we have constructed this complex object by using AttachEntityObject(...) , i hope the compound object will be real virtual physical object in the future, and we can discover this if when we use SaveMesh(#sphere, "sphere.mesh") after adding all the objects to the mother sphere then the sphere.mesh should contains all the other objects added to it and not only the mother sphere. i think then we can load sphere.mesh and use it in the physics demos correctly like the other models we make with modeling software
see you the next year and happy new year for all .

Code: Select all

#CameraSpeed = 1

Enumeration
  #Window
  #Plane = 970
  #Camera
  #Light1
  #Light2
  #sphere

EndEnumeration

Structure vector3d
  x.f
  y.f
  z.f
EndStructure

Structure vertex
  x.f
  y.f
  z.f
EndStructure

Declare DrawTube (x.f, y.f,z.f, x2.f, y2.f, z2.f, RadiusS.f, RadiusE.f, TubeShape)
Declare TubeXYZ (tube, x.f, y.f, z.f, x2.f, y2.f, z2.f, RadiusS.f, RadiusE.f, TubeShape, Material)

;beginning of frenet sqaure approximation 5 procedures
Procedure vector_cross(*v1.vector3d, *v2.vector3d, *vout.vector3d)
    *vout\x = (*v1\y * *v2\z) - (*v2\y * *v1\z)
    *vout\y = (*v1\z * *v2\x) - (*v2\z * *v1\x)
    *vout\z = (*v1\x * *v2\y) - (*v2\x * *v1\y)
EndProcedure

Procedure.f vector_magnitude(*v.vector3d)
    mag.f
    mag = Sqr(*v\x * *v\x + *v\y * *v\y + *v\z * *v\z)
    If mag = 0:mag = 1:EndIf
    ProcedureReturn mag
EndProcedure

Procedure vector_normalize (*v.vector3d)
    mag.f
    mag = vector_magnitude(*v)
    *v\x = *v\x / mag
    *v\y = *v\y / mag
    *v\z = *v\z / mag
EndProcedure


Procedure vector_add (*v1.vector3d, *v2.vector3d, *vout.vector3d)
    *vout\x = *v1\x + *v2\x
    *vout\y = *v1\y + *v2\y
    *vout\z = *v1\z + *v2\z
EndProcedure

Procedure vector_sub (*v1.vector3d, *v2.vector3d, *vout.vector3d)
    *vout\x = *v1\x - *v2\x
    *vout\y = *v1\y - *v2\y
    *vout\z = *v1\z - *v2\z
EndProcedure
;end of frenet sqaure approximation 5 procedures  

Global Dim MeshData.PB_MeshVertex(0)

Global xx.f, yy.f
Global ArrSize

Define.f KeyX, KeyY, MouseX, MouseY

If InitEngine3D()
  
  Add3DArchive("\", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Models", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Scripts",#PB_3DArchive_FileSystem)
    
  Parse3DScripts()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)

If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "spikey , W toggle wireFrame...., . Space toggle rotation, ... mouse/arrow keys: rotate/move camera ")
  If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
  
    CreateMaterial(3, LoadTexture(3, "snow_1024.jpg"))
    DisableMaterialLighting(3, #False)
    SetMaterialColor(3, #PB_Material_AmbientColor, RGB(250, 255, 0))
    SetMaterialColor(3, #PB_Material_SpecularColor, RGB(255, 255, 0))
    
        
    CreatePlane(#Plane, 150, 150, 1, 1, 10, 10)
    CreateEntity(#Plane,MeshID(#Plane),MaterialID(3),0.1,-10,0.2)
    
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    
    CreateMaterial(1, LoadTexture(1, "Dirt.jpg"))
    MaterialCullingMode(1, #PB_Material_NoCulling)

    CreateMaterial(2, LoadTexture(2, "RustySteel.jpg"))
    MaterialCullingMode(2, #PB_Material_NoCulling)
    
    CreateMaterial(4, LoadTexture(4, "ground_diffuse.png"))
    MaterialCullingMode(4, #PB_Material_NoCulling)
    
    CreateMaterial(5, LoadTexture(5, "Geebee2.bmp"))
    MaterialCullingMode(5, #PB_Material_NoCulling)
       
    CreateSphere(#sphere,3,6,6)
    CreateEntity(#sphere,MeshID(#sphere), MaterialID(1),0,0,0 )
   
    NormalizeMesh(#sphere)
        
    ;getting info about the big sphere data
    GetMeshData(#sphere,0, MeshData(), #PB_Mesh_Vertex | #PB_Mesh_Normal , 0, MeshVertexCount(#sphere)-1)
    ArrSize = ArraySize(MeshData())
    ;Debug ArrSize
       
    For c=0 To ArrSize ;42
      CopyEntity(#sphere, c) ; making tiny spheres to position later into the big sphere vertices
      ScaleEntity(c, 0.05, 0.05, 0.05)
      SetEntityMaterial(c, MaterialID(5))

    Next c
    
    ;spikes in the form of thin Lines, note that we use (#PB_Mesh_LineList)
    CreateMesh(0, #PB_Mesh_LineList , #PB_Mesh_Static)
    For c=0 To ArrSize ;42
      ;getting the vertices positions data which makes the big sphere 
      x.f = MeshData(c)\x
      y.f = MeshData(c)\y
      z.f = MeshData(c)\z
      
      x2.f = 3*MeshData(c)\x ; getting the virtual points so we can make a line from the sphere center to ...
      y2.f = 3*MeshData(c)\y ; the sphere vertex and extending the line to this point outside the sphere
      z2.f = 3*MeshData(c)\z ; we will only draw the line from a sphere vertex to this point, ignoring the line to the center
      
      MeshVertexColor(RGB(255,0,0))
      MeshVertexPosition(x, y, z) 
      MeshVertexPosition(x2, y2, z2)
      MoveEntity(c, x,y,z, #PB_Absolute) ; move the tiny red spheres we mada before to every sphere vertex position
      
      AttachEntityObject(#sphere, "", EntityID(c)) ; we attach the tiny red spheres to the big sphere
      
    Next c
       
    FinishMesh(#True)
        
    SetMeshMaterial(0, MaterialID(0))
    CreateEntity(0,MeshID(0),MaterialID(0))
    AttachEntityObject(#sphere,"",EntityID(0))
    
    tube = 200 ; we begins the tubes mesh numbering from 200 because the numbering from 0 to ... are reserved for other entities made before
    ; making the tubes at the same position of the Lines using the function TubeXYZ(...)
    For c=0 To ArrSize
      ; getting data of sphere vertices positions to use this in drawing the tubes with TubeXYZ(...) function
      x.f = MeshData(c)\x 
      y.f = MeshData(c)\y
      z.f = MeshData(c)\z
      
      x2.f = 3*MeshData(c)\x
      y2.f = 3*MeshData(c)\y
      z2.f = 3*MeshData(c)\z
      
      CreateMesh(tube , #PB_Mesh_TriangleList, #PB_Mesh_Static )
      ;TubeXYZ (tube, x.f, y.f, z.f, x2.f, y2.f, z2.f, RadiusS.f, RadiusE.f, TubeShape, Material)
      TubeXYZ (tube, x.f, y.f,z.f, x2.f, y2.f,z2.f, 0.3, 0.3, 8, 4) ; call the tube making function
      
      AttachEntityObject(#sphere,"",EntityID(tube))
      
      tube + 1 ; next tube mesh numbering
      
    Next c
    ;;oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
   
   
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, 0, 5, 28, #PB_Absolute)
    CameraLookAt(#Camera,0,0,0)
    CameraBackColor(#Camera, RGB(0,100,0))


    CreateLight(#Light1, RGB(0, 0, 0), -20, 40, 20)
    SetLightColor(#Light1, #PB_Light_DiffuseColor, RGB(255,255,255))
    CreateLight(#Light2, RGB(0, 0, 0), 20, 40, 20)
    SetLightColor(#Light2, #PB_Light_DiffuseColor, RGB(0,0,255))
    
    AmbientColor(RGB(255, 255, 255))

  EndIf
EndIf
;HideEntity(#sphere,1)
wireFrame = 1: rot=1 
Repeat
  
  Event = WindowEvent()
        
      If ExamineMouse()
        MouseX = -MouseDeltaX()/20 
        MouseY = -MouseDeltaY()/20
      EndIf
      
          
      If ExamineKeyboard()
         
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -0.2
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = 0.2
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -0.2
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = 0.2
        Else
          KeyY = 0
        EndIf
        
        If KeyboardReleased(#PB_Key_W)
          If wireFrame
            MaterialShadingMode(1, #PB_Material_Wireframe)
            MaterialShadingMode(4, #PB_Material_Wireframe)
          wireFrame ! 1
        Else 
          MaterialShadingMode(1, #PB_Material_Solid)
          MaterialShadingMode(4, #PB_Material_Solid)
          wireFrame ! 1
        EndIf
        EndIf
            
      EndIf
  
      RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera(#Camera, KeyX, 0, KeyY)
                      
      RotateEntity(#sphere, 0,rot,0,#PB_Relative)
      
      If KeyboardReleased(#PB_Key_Space)
        rot ! 1 
        ;SaveMesh(#sphere, "sphere.mesh"); it saves only the mother sphere discarding what we have added to it previously

      EndIf
                
      RenderWorld()
      
            
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
    
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
  
End

Procedure  DrawTube (x.f, y.f,z.f, x2.f, y2.f,z2.f, RadiusS.f, RadiusE.f, TubeShape)
  #Rings = 2
  Dim vertx.vertex(2)
  lineVec.vector3d

  u.f: r.f
      
  txu.f : txv.f
   
  x1.f = x
  y1.f = y
  z1.f = z
  
  bands = TubeShape ; 2 flat tube, 3 triangular tube, 4 rectangular, 8 almost cylindrical tube
    
  ;vector of the line between start vertex and the end vertex
  lineVec\x = x2 - x1
  lineVec\y = y2 - y1
  lineVec\z = z2 - z1
  

  tt.f = 0
  
  For i=0 To 2
      
      x = x1 + lineVec\x * tt 
      y = y1 + lineVec\y * tt 
      z = z1 + lineVec\z * tt
      tt + 1
      
       vertx(i)\x = x
       vertx(i)\y = y
       vertx(i)\z = z
       
   Next 
        
     current_point.vector3d
        next_point.vector3d
        T.vector3d
        B.vector3d
        N.vector3d
        p.f
     For i = 0 To 1
       If i=0 ; to manage the radius of tube start and tube end
         Radius.f = RadiusS
         Else 
           Radius.f=RadiusE
       EndIf
        ;center point
                
        current_point\x = vertx(i)\x
        current_point\y = vertx(i)\y
        current_point\z = vertx(i)\z
        ;next point For Frenet square
        
        next_point\x = vertx(i+1)\x
        next_point\y = vertx(i+1)\y
        next_point\z = vertx(i+1)\z

        ;T  = P' - P
        vector_sub(next_point, current_point, T)

        ;N = P' + P
        vector_add(next_point, current_point, N)

        ;B = T x N
        vector_cross(T, N, B)

        ;N = B x T
        vector_cross(B, T, N)

        ;Normalize vectors Or Else it won't work
        vector_normalize(B)
        vector_normalize(N)
        
        For j = 0 To bands
              new_point_x.f
              new_point_y.f
              
              ;rotate around the current point using normal rotation makes bands
            new_point_x = Sin(j * (#PI*2) / bands) * Radius
            new_point_y = Cos(j * (#PI*2) / bands) * Radius
            
                ;this is the coordinates of our point along the curve
            x = N\x * new_point_x + B\x * new_point_y + current_point\x
            y = N\y * new_point_x + B\y * new_point_y + current_point\y
            z = N\z * new_point_x + B\z * new_point_y + current_point\z
            
            MeshVertexPosition(x, y, z)
            MeshVertexTextureCoordinate(txu, txv)
            MeshVertexNormal(x, y, z)
            txv = txv + 1/#Rings
                         
         Next 
         txv = 0
         txu = txu + 1/bands
         
      Next 

      v.l
      For j = 0 To bands -1
          MeshFace(v,v+1,v + bands+1)
          MeshFace(v + bands+1,v + bands+2,v+1 )
         
          v + 1   
          
      Next 
 
  EndProcedure
  
  Procedure TubeXYZ (tube, x.f, y.f,z.f, x2.f, y2.f,z2.f, RadiusS.f, RadiusE.f, TubeShape, Material)
    x.f+0.00001 : y.f+0.00001 : z.f+0.00001 ; +0.00001 necessary if x,y,z or x2,y2,z2 are zero !!!
    x2.f+0.00001 : y2.f+0.00001 : z2.f+0.00001     
    
    CreateMesh(tube , #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )
    
    DrawTube (x, y, z, x2, y2, z2, RadiusS, RadiusE, TubeShape)
    FinishMesh(tube)
    NormalizeMesh(tube)
    BuildMeshTangents(tube)
    CreateEntity(tube,MeshID(tube),MaterialID(Material))
    
    
  EndProcedure