make Tubes, the easiest ever

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

make Tubes, the easiest ever

Post by applePi »

how to make a tube without mathematics
just follow the cylinder base vertices, while it is moving and rotating , record its positions, and do MeshVertexPosition(x,y,z)
this was not possible until DK_PETER have posted a great idea , look here
viewtopic.php?f=36&t=61455#p524313
in short: we position a new node at every vertex of a mesh, and then we attach all the nodes and the entity itself to a main node. then we move/rotate the main node, at the same time we commit MeshVertexPosition at every node x,y,z positions

what to do ?: press Z to move the cylinder and to create new vertices. press Space to finalise the mesh and to triangulate the mesh. i have used the procedure in setmeshdata.pb to weave the triangles
Note: while you press Z to create new vertices you see points , it is just a visual representation of the vertices we still making and can't be displayed yet, it is borrowed from a points cloud we create for this purpose only.
Happy the Longest Moon Eclipse of the Century today :D :D

Code: Select all

Enumeration
  #PointsCloud
  #cyl
  #Tube
EndEnumeration

Declare DrawTriangles()


Global Dim MeshData.PB_MeshVertex(0)

#CameraSpeed = 1

Global indx, mainnode, NbZ, NbX, rot, flag, meshflag
NbX = 15

Global srcX.f = 0: Global srcY.f = 0 : Global angle.f: Global randomize

Define.f KeyX, KeyY, MouseX, MouseY

Declare CreateMatrix()
Declare DrawMatrix()

ExamineDesktops()

InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()

OpenWindow(0,0,0,DesktopWidth(0), DesktopHeight(0)," Z: make new vertices,...., Space: finish the mesh .............. mouse/arrow keys for the camera",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,DesktopWidth(0), DesktopHeight(0),1,0,0,#PB_Screen_WaitSynchronization)

  Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts", #PB_3DArchive_FileSystem)
  Parse3DScripts()
  
  Global monitor=CreateSprite(#PB_Any,120,40)
      
    ;- Material
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    MaterialCullingMode(0, #PB_Material_NoCulling )
    CreateMaterial(1, LoadTexture(1, "terrain_texture.jpg"))
    CreateMaterial(2, LoadTexture(2, "clouds.jpg"))
    MaterialShadingMode(2, #PB_Material_Wireframe)
    MaterialCullingMode(2, #PB_Material_NoCulling )

    
    ;-Camera
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0,0,20,50, #PB_Absolute)
    CameraLookAt(0, 0, 0, 0)
    CameraBackColor(0, RGB(0, 0, 0))
    CameraRenderMode(0, #PB_Camera_Wireframe)

    ;-Light
    CreateLight(0, RGB(255, 255, 255), 20, 150, 120)
    AmbientColor(RGB(90, 90, 90))
    
    CreateCylinder(#cyl, 2, 2, NbX, 2, 0)
    CreateEntity(#cyl, MeshID(#cyl), MaterialID(2))
    
    ;-create a mesh of points lists , just to give a visual positions of the vertices you make with MeshVertexPosition
    CreateMatrix()
       
    ;get the mesh data of a cylinder
    GetMeshData(#cyl,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(#cyl)-1) 
    
    ;create a master node and attach the cylinder to it
    mainnode = CreateNode(#PB_Any,0, 0, 0)
    AttachNodeObject(mainnode, EntityID(#cyl))
    ;create number of nodes = number of vertices of a cylinder base
    Global Dim n(NbX) 
    For i = 0 To NbX : n(i) = CreateNode(#PB_Any) : Next
    For i = 0 To NbX
      ;move the nodes to the cylinder base vertices coordinates
      MoveNode(n(i),MeshData(i)\x, MeshData(i)\y, MeshData(i)\z, #PB_Absolute)
      AttachNodeObject(mainnode, NodeID(n(i)))
    Next
   
    Global.f x,y,z
    Global indx
    
    CreateMesh(#Tube, #PB_Mesh_TriangleList, #PB_Mesh_Dynamic)
        
    Repeat
      WindowEvent()
      
      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 KeyboardPushed(#PB_Key_Z)
          If flag = 1:Goto ext: EndIf
          meshflag = 1
          GetMeshData(#PointsCloud,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(#PointsCloud)-1) 
          angle.f + 5 ; the rotaion angle of the scanning machine
          srcX = 1 * Sin(Radian(angle)) ; formula for the circular motion
          srcY = 1 * Cos(Radian(angle)) ; formula for the circular motion
          
          RotateNode(mainnode, 0, 0, -5, #PB_Relative);#PB_Absolute) 
          MoveNode(mainnode, srcX,srcY,0,#PB_Relative);#PB_Absolute)
          
          For i=0 To NbX
            MeshVertexPosition(NodeX(n(i)), NodeY(n(i)), NodeZ(n(i)))
            MeshData(indx)\x = NodeX(n(i))
            MeshData(indx)\y = NodeY(n(i))
            MeshData(indx)\z = NodeZ(n(i))
            indx+1
          Next
          NbZ+1
          SetMeshData(#PointsCloud,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(#PointsCloud)-1)
          ext:
        EndIf
        
        If KeyboardReleased(#PB_Key_Space)
          If meshflag = 0: Goto exit:EndIf
          If flag = 1: Debug "sorry the mesh is finalized": Goto exit: EndIf
          HideEntity(#cyl, 1)
          HideEntity(#PointsCloud, 1)
          DrawTriangles()
          rot = 1
          flag = 1
          exit:
        EndIf
      
        
      EndIf
      
      If ExamineMouse()
        MouseX = -(MouseDeltaX()/10)
        MouseY = -(MouseDeltaY()/10)
      EndIf
      
            
      MoveCamera  (0, KeyX, 0, KeyY)
      RotateCamera(0,  MouseY, MouseX, 0, #PB_Relative)  
      
      If flag = 1
        RotateEntity(#Tube, 0, rot/2, 0, #PB_Relative)
      EndIf
                        
      RenderWorld()
            
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  

End

;-Procedures
Procedure DrawMatrix()
        
    angle.f + 0.5 ; the rotaion angle of the scanning machine
    srcX = radius * Sin(Radian(angle)) ; formula for the circular motion
    srcZ = radius * Cos(Radian(angle)) ; formula for the circular motion
    MoveEntity(#cyl, srcX, 2, srcZ, #PB_Absolute)
    EntityLookAt(#cyl, 0, 2, 0)
    EntityFixedYawAxis(#cyl, 1 , 0, 1, 0)

     MeshData(indx)\x = x
     MeshData(indx)\y = y
     MeshData(indx)\z = z
      
     
EndProcedure  

Procedure CreateMatrix()
  
  CreateMesh(#PointsCloud, #PB_Mesh_PointList, #PB_Mesh_Dynamic)
  
  For i=1 To 50000 ; just a shapeless mesh for the usage later
    MeshVertexPosition(0,0,0) ; plotted to the same point 0,0,0
    ;MeshVertexColor(RGB(255,255,255))
  Next
    
  FinishMesh(#True)
  SetMeshMaterial(#PointsCloud, MaterialID(0))
  
  CreateEntity(#PointsCloud, MeshID(#PointsCloud), #PB_Material_None, 0,0,0)
  
EndProcedure


Procedure DrawTriangles()
  Protected.l a, b, c, Nb
  Protected.w P1, P2, P3, P4
  
  NbZ-1
  Nb=NbX+1
  For b=0 To NbZ-1
    For a=0 To NbX-1
      P1=a+(b*Nb)
      P2=P1+1
      P3=a+(b+1)*Nb
      P4=P3+1
     
      MeshFace(P3, P2, P1)
      MeshFace(P2, P3, P4)
    Next
  Next
  FinishMesh(#True)
  SetMeshMaterial(#Tube, MaterialID(0))
  CreateEntity(#Tube, MeshID(#Tube), #PB_Material_None)
EndProcedure 
we can use math formulas to let the cylinder move over, and at the same time the new vertices will follow the cylinder base. but be carefull the cylinder must be tangent to the curve, look Calculus Lesson, Tangents to curves : viewtopic.php?f=36&t=61469&p=459769
Last edited by applePi on Tue Aug 07, 2018 7:07 am, edited 1 time in total.
User avatar
DK_PETER
Addict
Addict
Posts: 898
Joined: Sat Feb 19, 2011 10:06 am
Location: Denmark
Contact:

Re: make Tubes, the easiest ever

Post by DK_PETER »

Very nice, applePi.
Try moving the main node in xyz direction and do rotation at the same time for some interesting meshes. :)
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.
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: make Tubes, the easiest ever

Post by applePi »

Thanks DK_PETER
when changing the z from 0 to 0.2 Line 117 the ring is stretched to 3D making a spiral
MoveNode(mainnode, srcX,srcY,0.2,#PB_Relative)

the condition is that the radius of the tube should be approximately the same. the difficulty in making the cylinder to stay tangent to the movement path.
i imagine the best approach is to install a cylinder over the purebasic Car (carPhysics.pb or VehicleTerrain.pb) the tube will go wherever the car go and at the end we will have a pipes city in 3D

here is the tube is going over the sine wave curve gradually:

Code: Select all

Enumeration
  #PointsCloud = 200
  #cyl
  #Tube
EndEnumeration

Declare DrawTriangles()
Global Dim MeshData.PB_MeshVertex(0)

#CameraSpeed = 1

Global indx, mainnode, NbZ, NbX, rot, flag, meshflag
NbX = 16

Global srcX.f = 0: Global srcY.f = 0 : Global angle.f: Global randomize
Define.f KeyX, KeyY, MouseX, MouseY

Declare CreateMatrix()


Declare DrawPoints()

    #CameraSpeed = 1
    ;the range of the function under study is from xMin to xMax
    Global xMin.f = -2*#PI
    Global xMax.f =  2*#PI
    Global stepx.f = (xMax - xMin) / 1000 ; the increment of x every loop

    Enumeration
      #mesh
      #entity
      #tex
      #light
      #camera
      #plane
     
    EndEnumeration

    ExamineDesktops()

    InitEngine3D(#PB_Engine3D_DebugLog)
    InitSprite()
    InitKeyboard()
    InitMouse()

    OpenWindow(0,0,0,DesktopWidth(0), DesktopHeight(0),"Z: make new vertices,...., Space: finish the mesh any time .............. mouse/arrow keys for the camera",#PB_Window_ScreenCentered)
    OpenWindowedScreen(WindowID(0),0,0,DesktopWidth(0), DesktopHeight(0),1,0,0,#PB_Screen_WaitSynchronization)

    Add3DArchive(".", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/fonts", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts", #PB_3DArchive_FileSystem)
    Parse3DScripts()

    KeyboardMode(#PB_Keyboard_AllowSystemKeys)

    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, "clouds.jpg"))
    ;MaterialShadingMode(2, #PB_Material_Wireframe)
    MaterialCullingMode(2, #PB_Material_NoCulling )
    
    
    CreateLight(0,RGB(245,245,205),19,13,0)

    ;Create Camera
    CreateCamera(0,0,0,100,100)
    MoveCamera(0,-50,30,33,#PB_Absolute)
    CameraLookAt(0, 0, 0, 0)
    CameraBackColor(0, RGB(227,239,242))
    CameraRenderMode(0, #PB_Camera_Wireframe)

    AmbientColor(RGB(255,255,255))

    CreateLine3D(#PB_Any, -20, 0, 0, #Red, 20, 0, 0, RGB(255, 0, 0)) ; Red
    CreateLine3D(#PB_Any, 0,-20,0, #Green, 0, 20, 0, RGB(0, 255, 0)); Green
    CreateLine3D(#PB_Any, 0,0,-20, #Blue, 0, 0, 20, RGB(0, 0, 255)) ;Blue
    ;-Mesh
    DrawPoints() ; call the function drawing procedure

    CreateTexture(2,32,32)
      StartDrawing(TextureOutput(2))
        Box(0,0,32,32,RGB(255,0,0))
      StopDrawing()
      CreateMaterial(2,TextureID(2))
      MaterialCullingMode(2, #PB_Material_NoCulling)
     
    CreateCylinder(#cyl, 2, 1, NbX, 2, 0)
    ;TransformMesh(#Mesh, x, y, z, ScaleX, ScaleY, ScaleZ, RotateX, RotateY, RotateZ [, SubMesh])
    TransformMesh(#cyl,0,0,0,1,1,1,0,0,90)
    CreateEntity(#cyl, MeshID(#cyl), MaterialID(2) )
    ;RotateEntity(#cyl, 0,0,90, #PB_Absolute)    
    MoveEntity(#cyl, -2*#PI*3, 0, 0, #PB_Absolute);-2*#PI*3

    ; create a mesh of points lists , just To give a visual positions of the vertices you make With MeshVertexPosition
    CreateMatrix()
    FreeEntity(#cyl) ; wse don't need it after getting cylinder vertices info  
    ;get the mesh data of a cylinder
    GetMeshData(#cyl,0, MeshData(), #PB_Mesh_Vertex, NbX+1, MeshVertexCount(#cyl)-1) 
    
    ;create a master node and attach the cylinder to it
    mainnode = CreateNode(#PB_Any,0, 0, 0)
    RotateNode(mainnode, 0,0,90)
    MoveNode(mainnode, -2*#PI*3, 0, 0, #PB_Absolute)
    ;create number of nodes = number of vertices of a cylinder base
    Global Dim n(NbX) 
    For i = 0 To NbX : n(i) = CreateNode(#PB_Any) : Next
    For i = 0 To NbX
      ;move the nodes to the cylinder base vertices coordinates
      MoveNode(n(i),MeshData(i)\x, MeshData(i)\y, MeshData(i)\z, #PB_Absolute)
      AttachNodeObject(mainnode, NodeID(n(i)))
    Next
   
    Global.f x,y,z
    Global indx
    
    CreateMesh(#Tube, #PB_Mesh_TriangleList, #PB_Mesh_Dynamic)
    
    x.f = -2*#PI
    start = 0
    Repeat
      WindowEvent()
     
      If ExamineMouse()
            MouseX = -MouseDeltaX() * #CameraSpeed * 0.2
            MouseY = -MouseDeltaY() * #CameraSpeed * 0.2
          EndIf
      ShowCursor_(0)
       
    ; Use arrow keys and mouse to rotate and fly in/out
      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_Z) 
            start ! 1
          EndIf
         
          If start
            ;------------------------------
            If flag = 1:Goto ext: EndIf
          meshflag = 1
          GetMeshData(#PointsCloud,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(#PointsCloud)-1) 
          
          count + 1 ;just to make a mesh less compact with big triangles
          If count = 10
          count = 0  
          For i=0 To NbX
            MeshVertexPosition(NodeX(n(i)), NodeY(n(i)), NodeZ(n(i)))
            MeshData(indx)\x = NodeX(n(i))
            MeshData(indx)\y = NodeY(n(i))
            MeshData(indx)\z = NodeZ(n(i))
            indx+1
          Next
          NbZ+1
          SetMeshData(#PointsCloud,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(#PointsCloud)-1)
        EndIf
        
        ;------------------------------
              x.f + stepx
              y.f = Sin(x)
              z.f=0
              slope.f= Cos(x) ; the derivative of sin(x) is cos(x)
              slope = Degree(ATan(slope))
             
              MoveNode(mainnode,x*3,y*3, z,   #PB_Absolute) ; we just amplify x,y by 3
              RotateNode(mainnode, 0,0,slope, #PB_Absolute)
             
             
              If x > xMax
                start = 0
              EndIf 
        
                 
            EndIf ; its head is: ( if start )
            ext:
            
          If KeyboardReleased(#PB_Key_Space)
            If meshflag = 0: Goto exit:EndIf
            If flag = 1: Debug "sorry the mesh is finalized": Goto exit: EndIf
            FreeEntity(#PointsCloud)
            DrawTriangles()
            rot = 1
            flag = 1
            exit:
          EndIf
            
          If flag = 1
           RotateEntity(#Tube, 0.5, 0, 0, #PB_Relative)
          EndIf
                  
         
          RotateCamera(0, MouseY, MouseX, 0, #PB_Relative)
          MoveCamera  (0, KeyX, 0, KeyY)
         
      RenderWorld()
     
      FlipBuffers()

    Until KeyboardPushed(#PB_Key_Escape) Or WindowEvent() = #PB_Event_CloseWindow

    ;function drawing
    Procedure DrawPoints()
      Protected.f x, y
       
      CreateMesh(0, #PB_Mesh_PointList, #PB_Mesh_Static)
       
      x.f = xMin: z.f = 0
     
        While x <= 2*#PI
         
          y.f = Sin(x)
                         
          MeshVertexPosition(x*3, y*3, z)
          MeshVertexColor(RGB(0,0,255))
         
          x.f + stepx
        Wend
           
        FinishMesh(#True)
        CreateEntity(#entity, MeshID(0), MaterialID(0) ,0,0,0)
       
EndProcedure 

Procedure CreateMatrix()
  
  CreateMesh(#PointsCloud, #PB_Mesh_PointList, #PB_Mesh_Dynamic)
  
  For i=1 To 100000 ; just a shapeless mesh for the usage later
    MeshVertexPosition(0,0,0) ; plotted to the same point 0,0,0
    ;MeshVertexColor(RGB(255,255,255))
  Next
    
  FinishMesh(#True)
  SetMeshMaterial(#PointsCloud, MaterialID(2))
  
  CreateEntity(#PointsCloud, MeshID(#PointsCloud), #PB_Material_None, 0,0,0)
  
EndProcedure


Procedure DrawTriangles()
  Protected.l a, b, c, Nb
  Protected.w P1, P2, P3, P4
  
  NbZ-1
  Nb=NbX+1
  For b=0 To NbZ-1
    For a=0 To NbX-1
      P1=a+(b*Nb)
      P2=P1+1
      P3=a+(b+1)*Nb
      P4=P3+1
     
      MeshFace(P3, P2, P1)
      MeshFace(P2, P3, P4)
    Next
  Next
  FinishMesh(#True)
  SetMeshMaterial(#Tube, MaterialID(2))
  CreateEntity(#Tube, MeshID(#Tube), #PB_Material_None)
EndProcedure


Post Reply