Cone, Torus & Pyramid

Everything related to 3D programming
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Cone, Torus & Pyramid

Post by applePi »

i suggest to use for the cone and the pyramid my general (all-In-One) function :
TubeXYZ(#mesh, x,y,z, x2,y2,z2, TubeRadiusStart.f,TubRadiusEnd.f, TubeShape, Material)
to draw a cone centered in 0,0,0 with height 30, and base radius 35, top radius 0 use this:
TubeXYZ(#mesh, 0,0,0, 0,30,0, 35, 0, 32, 2)

the benefits of this function is apparent from its parameters:
1-the cone can point to any direction since it is going from x,y,z to x2,y2,z2 so TubeXYZ(#mesh, 0,0,0, 10,30,0, 35, 0, 32, 2) will go from 0,0,0 to 10,30,0 .
2- we can make it upside down from the beginning.
3- and the cone tip can be 0 or any number, so 1 will make a hole instead of sharp tip
4- we can choose how smooth the cone can be, i have used 32, if we use 4 we will get a pyramid.
PS: the origin of the included vector procedures can be found here:
http://www.purebasic.fr/english/viewtop ... 36&t=56642
not sure if it is necessary for the upright cone.
Image

Code: Select all

Define.f KeyX, KeyY, MouseX, MouseY

Enumeration
  #Window = 500
  #plane
  #Camera
  #Light1
  #Light2
  #sphere
  #mat
  #tex
  #BillboardGroup
    
EndEnumeration

#CameraSpeed = 1
#Rings = 2 ;number of Rings over all the Line (always 2, start ring and end ring)


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

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

Dim vertx.vertex(32)

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)

    
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


If InitEngine3D()
  
  Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #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)

OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "Cone ... , W toggle wire/solid Frame ..., H hide/unhide the sun..., mouse and arrow keys to move/ rotate the camera ")
  OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
    
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, 0, 50, 110, #PB_Absolute)
    CameraLookAt(#Camera,0,0,0)
    CameraBackColor(#Camera, RGB(197,225,235))
    
    CreateMaterial(0, LoadTexture(0, "white.jpg"))
    DisableMaterialLighting(0, #True)
    
    CreateMaterial(1, LoadTexture(1, "snow_1024.jpg"))
    MaterialCullingMode(1, #PB_Material_NoCulling)

    CreateMaterial(2, LoadTexture(2, "ground_diffuse.png"))
    MaterialCullingMode(2, #PB_Material_NoCulling)
    DisableMaterialLighting(2, #False)
    
    CreateLight(#Light1, RGB(200, 200, 200), 0, 45, 45)
    AmbientColor(RGB(200, 200, 200))
    
    CreateLight(#Light2, RGB(200, 200, 200), -5, 15, -5)
    

CreatePlane(#plane, 200, 200, 50, 50, 10, 10)
CreateEntity(#plane,MeshID(#plane),MaterialID(1), 0, 0, 0)

;glLineWidth_(5)
CreateLine3D(7, 0, 0.05, 0, RGB(255,   0,   0), 100,  0.05,  0, RGB(255,   0,   0))  ; Axis X
CreateLine3D(8, 0, 0, 0, RGB(  0, 255,   0),  0, 100,  0, RGB(  0, 255,   0))  ; Axis Y
CreateLine3D(9, 0, 0.05, 0, RGB(  0,   0, 255),  0,  0.05, 100, RGB(  0,   0, 255))  ; Axis Z


;doc: draw thick lines from x,y,z to x2,y2,z2 with thickness Radius and TubeShape is the number of points makes the tube cross section polygon
;doc: TubeXYZ(#mesh, x,y,z, x2,y2,z2, TubeRadiusStart.f,TubRadiusEnd.f, TubeShape, Material)
;TubeXYZ(2,  20,0,-2,  20,30,-2, 15, 0, 32, 2) 
TubeXYZ(2,  0,0,0,  0,30,0,  35, 0,   32, 2) 


EnableWorldPhysics(#True)

EntityPhysicBody(#plane, #PB_Entity_StaticBody, 1, 1, 0.1)

CreateSphere(#sphere, 4)
CreateEntity(#sphere, MeshID(#sphere), MaterialID(2), 0, 4,0)

; Create electric light ; or use the method in staticGeometry.pb example
LoadTexture(#tex , "Lensflare5.jpg") ; for the sprite
CreateMaterial(#mat, TextureID(#tex))
SetMaterialColor(#mat, #PB_Material_AmbientColor, RGB(1,1,1))
SetMaterialColor(#mat, #PB_Material_DiffuseColor, RGB(1,1,1))
DisableMaterialLighting(#mat, 1)
MaterialBlendingMode(#mat, #PB_Material_Add )
CreateBillboardGroup(#BillboardGroup, MaterialID(#mat), 10,10, 0, 0, 0)
AddBillboard(#BillboardGroup, -5, 15, -5)
AddBillboard(#BillboardGroup, 0, 45, 45)
WorldShadows(#PB_Shadow_Modulative  , -1, RGB(200, 200, 200))
;WorldShadows(#PB_Shadow_Additive)
;EntityRenderMode(#plane, 0)

wireFrame = 1: hide = 1
Repeat
  
  Event = WindowEvent()
        
      If ExamineMouse()
        MouseX = -MouseDeltaX()/20 
        MouseY = -MouseDeltaY()/20
      EndIf
      
          
      If ExamineKeyboard()
           
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed
        Else
          KeyY = 0
        EndIf
        
        If KeyboardReleased(#PB_Key_W)
          If wireFrame
            MaterialShadingMode(2, #PB_Material_Wireframe)
          wireFrame ! 1
        Else 
            MaterialShadingMode(2, #PB_Material_Solid)
          wireFrame ! 1
        EndIf
      EndIf
      
      If KeyboardReleased(#PB_Key_H)
        If hide
          HideBillboardGroup(#BillboardGroup, 1)
          hide ! 1
          EntityRenderMode(#sphere, 0)
          EntityRenderMode(2, 0) ; 2 is the Cone
        Else
          HideBillboardGroup(#BillboardGroup, 0)
          hide ! 1
          EntityRenderMode(#sphere, #PB_Entity_CastShadow      )
          EntityRenderMode(2, #PB_Entity_CastShadow ) ; 2 is the Cone
        EndIf
      EndIf
      


            
      EndIf
      
      RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera(#Camera, KeyX, 0, KeyY)
      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)
  
  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
    
  ;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(1, 1, 1)
            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 )
          MeshFace(v,v + bands+1, v+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)
    NormalizeMesh(tube)
    BuildMeshTangents(tube)
    FinishMesh(tube)
    
    CreateEntity(tube,MeshID(tube),MaterialID(Material))
      
      
    
  EndProcedure
  
 
 
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Cone, Torus & Pyramid

Post by applePi »

a more concise code for the cone but less general or versatile than the above example. no vector procedures here, from an old experiments i made, not checked for the shadow. and may have unnecessary code
some tests for the variables:
incr.f = 1 ; will be like a volcano
incr.f = 0.01 ; will have a sharp tip with a very tiny hole
cone(0.01) ; make a natural cone
cone(1) ; a flat disk with a tiny hole in the middle
minorOrbit.l = 20 ; for a cone like shape
minorOrbit.l = 4 ; for a pyramid like shape

Code: Select all

Declare cone(r.f) 

Enumeration
   #MESH
   #LIGHT
   #CAMERA_ONE
   #BUTTON
   #mainwin
 EndEnumeration

Quit.b = #False

ExamineDesktops()
If OpenWindow(#mainwin, 0, 0, DesktopWidth(0), DesktopHeight(0), "W ... toggle wireFrame/SolidFrame", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
;Initialize environment
InitEngine3D()
InitSprite()
OpenWindowedScreen(WindowID(#mainwin), 0, 0, DesktopWidth(0), DesktopHeight(0), 0, 0, 0)
;WorldShadows(#PB_Shadow_Additive)

InitKeyboard()
SetFrameRate(60)


Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)


CreateLight(0,RGB(255,255,255),-100,40,30)
AmbientColor(RGB(100,100,100))

CreateCamera(#CAMERA_ONE, 0, 0, 100, 100)
MoveCamera(#CAMERA_ONE, 0, 3, 20)
CameraLookAt(#CAMERA_ONE, 0, 2, 0)

RotateCamera(#CAMERA_ONE, -15, 0, 0)
EndIf

;SkyDome("clouds.jpg", 100) ;for blue color background

;- Mesh 
CreateMaterial(0, LoadTexture(0, "terrain_texture.jpg"))
MaterialCullingMode(0, #PB_Material_NoCulling)
DisableMaterialLighting(0, #True)
CreateMesh(1, #PB_Mesh_TriangleList, #PB_Mesh_Static)
SetMeshMaterial(1, MaterialID(0))

wireFrame = 1

cone(0.01)      
  
Repeat
  Event = WindowEvent()
  
   RotateEntity(1, 0, 0.5, 0, #PB_Relative)
   
   RenderWorld()
   FlipBuffers()

  ExamineKeyboard()
  
    If KeyboardReleased(#PB_Key_W)
          If wireFrame
            MaterialShadingMode(0, #PB_Material_Wireframe)
          wireFrame ! 1
        Else 
            MaterialShadingMode(0, #PB_Material_Solid)
          wireFrame ! 1
        EndIf
        EndIf
    


   If KeyboardPushed(#PB_Key_Escape)
      Quit = #True
    EndIf
    
    
  Until Quit = #True Or Event = #PB_Event_CloseWindow
  
  Procedure cone(rad.f)
  x.f: y.f :z.f : u.f: v.f: r.f
      majorOrbit.l = 100 : minorOrbit.l = 20
      majorStep.f   = 2 * #PI / majorOrbit
      minorStep.f   = 2 * #PI / minorOrbit
      i.l: j.l: txu.f : txv.f
 
      incr.f = 0.01
      For i = 0 To majorOrbit
        incr.f  + rad
      
        v = i * majorStep
        For j = 0 To minorOrbit
          u = j * minorStep
          
          x = Sin(u)*10 * incr
          y = Cos(u)*10 * incr
          
          z+0.02
          
          MeshVertexPosition(x, y, z);
          MeshVertexTextureCoordinate(txu, txv)
          MeshVertexNormal(1, 1, 1)
          ; texture the whole mesh with one picture stretched
          txv = txv + 1/minorOrbit ; texture coordinates
          
        Next
        
        txv = 0
        txu = txu + 1/majorOrbit 
      Next
      For i = 0 To majorOrbit-1
      For j = 0 To minorOrbit
          MeshFace(t,t + minorOrbit+1, t+1)
          MeshFace(t + minorOrbit+1,t + minorOrbit+2,t+1 )
          If i=majorOrbit-1 And j=minorOrbit-1 ;bypass the last triangle
            minorOrbit-1
          EndIf 
          t + 1   
          
     Next
     
   Next  
      
    NormalizeMesh(1)
    BuildMeshTangents(1)
    FinishMesh(#True)
    CreateEntity(1, MeshID(1), MaterialID(0))  
    ScaleEntity(1,0.2, 0.2, 0.2)
     
  EndProcedure
  
  
to look closely at the connections for possible tests:

Code: Select all

Declare cone(r.f) 

Enumeration
   #MESH
   #LIGHT
   #CAMERA_ONE
   #BUTTON
   #mainwin
 EndEnumeration

Quit.b = #False
rot.l=1 :stopFlag = 1
xs.f = 0.3:ys.f = 0.3:zs.f = 0.3
x.f: y.f :z.f: x0.f: y0.f=1 :z0.f
rotx.f:roty.f=0.5:rotz.f :rotx0.f: roty0.f: rotz0.f
up.f = 1.8: depth.f=0

ExamineDesktops()
If OpenWindow(#mainwin, 0, 0, DesktopWidth(0), DesktopHeight(0), "W... wireFrame/SolidFrame", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  

;Initialize environment
InitEngine3D()
InitSprite()
OpenWindowedScreen(WindowID(#mainwin), 0, 0, DesktopWidth(0), DesktopHeight(0), 0, 0, 0)
;WorldShadows(#PB_Shadow_Additive)

InitKeyboard()
SetFrameRate(60)


Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)


CreateLight(0,RGB(255,255,255),-100,40,30)
AmbientColor(RGB(100,100,100))

CreateCamera(#CAMERA_ONE, 0, 0, 100, 100)
MoveCamera(#CAMERA_ONE, 0, 3, 12)
CameraLookAt(#CAMERA_ONE, 0, 2, 0)

RotateCamera(#CAMERA_ONE, -15, 0, 0)
EndIf


;SkyDome("clouds.jpg", 100) ;for blue color background

;- Mesh 
CreateMaterial(0, LoadTexture(0, "terrain_texture.jpg"))
MaterialShadingMode(0, #PB_Material_Wireframe)
MaterialCullingMode(0, #PB_Material_NoCulling)
DisableMaterialLighting(0, #True)
CreateMesh(1, #PB_Mesh_TriangleList, #PB_Mesh_Static)
SetMeshMaterial(1, MaterialID(0))

x.f: y.f :z.f : u.f: v.f: r.f
      
cone(0.03)      
wireFrame = 0
Repeat
  Event = WindowEvent()
  
  
   RotateEntity(1, 0, 1, 0, #PB_Relative)
   
   RenderWorld()
   FlipBuffers()

  ExamineKeyboard()
  If KeyboardReleased(#PB_Key_W)
          If wireFrame
            MaterialShadingMode(0, #PB_Material_Wireframe)
          wireFrame ! 1
        Else 
            MaterialShadingMode(0, #PB_Material_Solid)
          wireFrame ! 1
        EndIf
        EndIf
   If KeyboardPushed(#PB_Key_Escape)
      Quit = #True
    EndIf
    
    
  Until Quit = #True Or Event = #PB_Event_CloseWindow
  
  Procedure cone(rad.f)
  x.f: y.f :z.f : u.f: v.f: r.f
      majorOrbit.l = 10 : minorOrbit.l = 10
      majorStep.f   = 10 * #PI / majorOrbit
      minorStep.f   = 2 * #PI / minorOrbit
      i.l: j.l: txu.f : txv.f
 
      incr.f = 1
      For i = 0 To majorOrbit
        incr.f  + rad
      
        v = i * majorStep
        For j = 0 To minorOrbit
          u = j * minorStep
          
          x = Sin(u)*10 * incr
          y = Cos(u)*10 * incr
                   
          MeshVertexPosition(x, y, z);
          MeshVertexTextureCoordinate(txu, txv)
          MeshVertexNormal(1, 1, 1)
          ; texture the whole mesh with one picture stretched
          txv = txv + 1/minorOrbit ; texture coordinates
          
        Next
        z+0.02
        txv = 0
        txu = txu + 1/majorOrbit 
      Next
      For i = 0 To majorOrbit-1
      For j = 0 To minorOrbit
          MeshFace(t,t + minorOrbit+1, t+1)
          MeshFace(t + minorOrbit+1,t + minorOrbit+2,t+1 )
          If i=majorOrbit-1 And j=minorOrbit-1 ;bypass the last triangle
            minorOrbit-1
          EndIf 
          t + 1   
          
     Next
     
   Next  
      
    NormalizeMesh(1)
    BuildMeshTangents(1)
    FinishMesh(#True)
    CreateEntity(1, MeshID(1), MaterialID(0))  
    ScaleEntity(1,0.2, 0.2, 18)
  ;Main loop
  MoveEntity(1,0,up,depth,#PB_Absolute)   
    
  EndProcedure
  
  
Post Reply