Page 1 of 1

thick and thin lines, and tubes of all shapes

Posted: Tue Nov 25, 2014 10:23 am
by applePi
i was trying to make a thick line using PB 3d graphics, and from this page:
http://www.ogre3d.org/forums/viewtopic.php?f=2&t=62671 someone advised to use glLineWidth(...) before drawing a line and then link it with opengl32.lib (on windows)
in the following example there is just one glLineWidth(10) opengl function anywhere in the code and all the lines will be thick (may be 10 points thickness). but this will not work unless we adjust the Library Subsystem to opengl (from menu :compilers --> compiler options)
the same plan works also with example CreateLine3D.pb from the PB examples)
just two notes:
1- it seems not possible to mix thick and thin lines.
2- we are restricted to thickness about 10 points, but this is not a real problem. thickness 1 to 10 are more than enough for a line.

Code: Select all

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 100
      ;s is the angle around the z-axis
      ;t is the height angle, measured 'down' from the z-axis. 
    ;t=RandF(0,360)
    s=RandF(0,360)
    ;s=RandF(0,1)  ; uncomment to get a  flat disk shape and not a sphere
    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) 
    
    glLineWidth_(10) ; this is an opengl function
    
    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()
 
      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: thick and thin lines

Posted: Tue Nov 25, 2014 12:05 pm
by IdeasVacuum
Nice demo applePi. glLineWidth_() doesn't seem to have any effect on my WinXPx86 machine though (OpenGL Version: 2.1.2). Is the PB Line really a line as expected by OpenGL or is it a work-around, i.e. a thin mesh masquerading as a line?

Re: thick and thin lines

Posted: Tue Nov 25, 2014 1:13 pm
by applePi
Hi IdeasVacuum , my opengl version is 4.1 with the card geforce GT 520, and winxp/32 bit in this session.
it is possible your card or drivers version does not support the thick lines. and also the IDE menu Library Subsystem should be set to opengl

i have read yesterday that the thick lines are software based and not by the card hardware so it is relatively slow, and that it is in reality a quad, i can't find that link again.
there is some people have described how to make a quad to represent a line,
http://www.ogre3d.org/forums/viewtopic.php?f=10&t=57710 i will try it later.
here is the picture of the output of the above example
Image

Re: thick and thin lines

Posted: Tue Nov 25, 2014 4:03 pm
by IdeasVacuum
Hi applePi - yeah, from your screen shot I would definitely say that is not a 3D line. In CAD-CAM apps, the line would have a thickness 'all round' so it would effectively be like a thin cylinder. In CAD-CAM, there are a variety of 2D and 3D wireframe elements that can be defined in 3D space - lines, arcs, circles, ellipses, splines are the minimum. I wonder how Marc is defining them in his application?

NURBS: Open Nurbs

Re: thick and thin lines

Posted: Tue Nov 25, 2014 5:39 pm
by Samuel
Hey applepi, you could try adding a second plane to each line and just rotate it 90 degrees. It would look like a cross if you looked down it, but this might help a little for certain viewpoints.

If you want nice looking 3D lines with thickness, like the ones in some cad and modeling software, then shaders are the way to go.
Nvidia has a nice chapter on this if you want to do a little reading on it.
http://http.developer.nvidia.com/GPUGem ... ter22.html

Re: thick and thin lines

Posted: Wed Nov 26, 2014 5:48 pm
by applePi
i really need to read some chapters about vectors, and until this happened i will use an available procedure called frenet sqaure approximation which referenced in the thread "Tubes , bent tubes, custom pipes" http://www.purebasic.fr/english/viewtop ... 36&t=56642
the Samuel suggestion makes me think of covering the line with a tube, we draw first the thin line, and then we put a polygon at the start and end of the line, the job of the frenet sqaure approximation is to adjust the polygon points to be perpendicular to the curve (which are here a line), in the example the
Global bands = 8 ; the polygon have 8 sides so it is almost circular, you can use bands = 4 so it will be squared.
to change the thickness of the thick line (the tube) change #RADIUS = 0.1
this program are half experimental so it needs more weaving and tunning .
to draw the usual thick line coordinates at the 0,0,0 edit the subsystem Library to opengl instead of the empty box in the IDE menu "compiler -> compiler options"
the usage: example:
LineXYZ(2, 5,4,-2, 3,0,3) ; 2 is the mesh name, this will draw a thick line from point 5,4,-2 to point 3,0,3
by default you will see this graphics of 3 thick lines
Image

now uncomment the lines 135-138:
For i=4 To 500
LineXYZ(i, Random(10,0),Random(10,0),Random(10,0), Random(10,0),Random(10,0),Random(10,0))
HideEntity(i,1)
Next

and you will see a jungle of 500 tubes in all direction,
Image
so this fuction LineXYZ can work to make a whole city from tubes (or thick lines). you just design the coordinates of the lines and apply this function.
notes: i have tested the tubes physics as static in a hurry and letting a small sphere fall inside one of the tilted tubes and it passed the physics test for the static tubes
the first code without physics

Code: Select all

#CameraSpeed = 0.05
#RADIUS  = 0.1 ;tube thickness

Global bands = 8 ;number of points of every ring (circle)
#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)
Declare LineXYZ (Line3D, x.f, y.f, z.f, x2.f, y2.f, z2.f)

	 
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

Define.f KeyX, KeyY, MouseX, MouseY

Enumeration
  #Window = 500
  #Plane
  #Camera
  #Light1
    
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)

If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "thick lines , W toggle wire/solid Frame ...., mouse and arrow keys to move/ rotate the camera ")
  If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
    
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, 1, 10, 10, #PB_Absolute)
    CameraLookAt(#Camera,1,0,0)
    CameraBackColor(#Camera, RGB(200,200,200))
    
    CreateMaterial(0, LoadTexture(0, "white.jpg"))
    DisableMaterialLighting(0, #False)
    SetMaterialColor(0, #PB_Material_AmbientColor, RGB(250, 255, 0))
    SetMaterialColor(0, #PB_Material_SpecularColor, RGB(255, 255, 0))

    CreateMaterial(1, LoadTexture(1, "MRAMOR6X6.jpg"))
    MaterialCullingMode(1, #PB_Material_NoCulling)

    CreateMaterial(2, LoadTexture(2, "ground_diffuse.png"))
    ;CreateMaterial(2, LoadTexture(2, "wood.jpg"))
    MaterialCullingMode(2, #PB_Material_NoCulling)
    DisableMaterialLighting(2, #False)
    SetMaterialColor(2, #PB_Material_AmbientColor, RGB(250, 255, 0))
    SetMaterialColor(2, #PB_Material_SpecularColor, RGB(255, 255, 0))
    
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    
    CreateLight(#Light1, RGB(255, 255, 255), 0, 20, 20)
    AmbientColor(RGB(255, 255, 255))
  
  EndIf
EndIf

CreatePlane(#plane, 600, 600, 100, 100, 100, 100)
CreateEntity(#plane,MeshID(#plane),MaterialID(1), 0, 0, 0)

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

wireFrame = 1

;doc: draw thick lines from x,y,z to x2,y2,z2
;doc: LineXYZ(#mesh, x,y,z, x2,y2,z2)
LineXYZ(1,  1,0,-2,  1,4,-2) ;:HideEntity(1,1) ;to hide the thin lines
LineXYZ(2,  5,4,-2,  3,0,3)  ;:HideEntity(2,1)
LineXYZ(3,  5,4,-2,  0,0,0)  ;:HideEntity(3,1)

;For i=4 To 500 ; make a huge tubes jungle
;LineXYZ(i,  Random(10,0),Random(10,0),Random(10,0),  Random(10,0),Random(10,0),Random(10,0))
;HideEntity(i,1)
;Next

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
            
      EndIf
  
      RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera(#Camera, KeyX, 0, KeyY)
      
      ;RotateEntity(0, 0,0,rot)
         
      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)
  
  Dim vertx.vertex(10)
  lineVec.vector3d

	u.f: r.f
      
  txu.f : txv.f
   
  x1.f = x
  y1.f = y
  z1.f = z
  
  
  ;vector of the line between start vertex and the end vertex
  lineVec\x = x2 - x1
  lineVec\y = y2 - y1
  lineVec\z = z2 - z1
  
  
	;Dist.f = Sqr(lineVec\x*lineVec\x + lineVec\y*lineVec\y + lineVec\z*lineVec\z)
  ;Debug Dist
  tt.f = 0
  
  For i=0 To #Rings
        
	    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 #Rings-1
	  
        ;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 LineXYZ (Line3D, x.f, y.f,z.f, x2.f, y2.f,z2.f)
    
    x.f+0.00001 : y.f+0.00001 : z.f+0.00001 ; i don't know why 0.00001 is necessary
    x2.f+0.00001 : y2.f+0.00001 : z2.f+0.00001 ; if x,y,z or x2,y2,z2 are zero !!!
    CreateMesh(Line3D, #PB_Mesh_LineList , #PB_Mesh_Static)
    
    MeshVertexColor(RGB(255,0,0)) 
    MeshVertexPosition(x, y, z) 
    MeshVertexPosition(x2, y2, z2) 
   
    FinishMesh(#True)
    
    CreateEntity(Line3D,MeshID(Line3D),MaterialID(0) )
    tube = Line3D + 2000 
    CreateMesh(tube , #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )
    SetMeshMaterial(tube , MaterialID(2))
    ;; 0.00001 : necessary if all x,t,z are zero
    DrawTube (x+0.00001, y+0.00001, z+0.00001, x2, y2, z2)
    FinishMesh(tube)
    NormalizeMesh(tube)
    BuildMeshTangents(tube)
    CreateEntity(tube,MeshID(tube),MaterialID(2))
    AttachEntityObject(Line3D,"",EntityID(tube))
    
      
    
  EndProcedure
  
 
 
the second code with physics:

Code: Select all

#CameraSpeed = 0.05
#RADIUS  = 0.1 ;tube thickness
#sphere = 17
#RedMaterial = 18

Global bands = 8 ;number of points of every ring (circle)
#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)
Declare LineXYZ (Line3D, x.f, y.f, z.f, x2.f, y2.f, z2.f)

    
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

Define.f KeyX, KeyY, MouseX, MouseY

Enumeration
  #Window = 500
  #Plane
  #Camera
  #Light1
    
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)

If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "thick lines , W toggle wire/solid Frame ...., mouse and arrow keys to move/ rotate the camera ")
  If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
    
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, 1, 10, 10, #PB_Absolute)
    CameraLookAt(#Camera,1,0,0)
    CameraBackColor(#Camera, RGB(200,200,200))
    
    CreateMaterial(0, LoadTexture(0, "white.jpg"))
    DisableMaterialLighting(0, #False)
    SetMaterialColor(0, #PB_Material_AmbientColor, RGB(250, 255, 0))
    SetMaterialColor(0, #PB_Material_SpecularColor, RGB(255, 255, 0))

    CreateMaterial(1, LoadTexture(1, "MRAMOR6X6.jpg"))
    MaterialCullingMode(1, #PB_Material_NoCulling)

    CreateMaterial(2, LoadTexture(2, "ground_diffuse.png"))
    ;CreateMaterial(2, LoadTexture(2, "wood.jpg"))
    MaterialCullingMode(2, #PB_Material_NoCulling)
    DisableMaterialLighting(2, #False)
    SetMaterialColor(2, #PB_Material_AmbientColor, RGB(250, 255, 0))
    SetMaterialColor(2, #PB_Material_SpecularColor, RGB(255, 255, 0))
    
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    GetScriptMaterial(#RedMaterial, "Color/Red")
    
    CreateLight(#Light1, RGB(255, 255, 255), 0, 20, 20)
    AmbientColor(RGB(255, 255, 255))
  
  EndIf
EndIf
EnableWorldPhysics(#True)

CreatePlane(#plane, 600, 600, 100, 100, 100, 100)
CreateEntity(#plane,MeshID(#plane),MaterialID(1), 0, 0, 0)
EntityPhysicBody(#plane, #PB_Entity_StaticBody)

CreateSphere(#sphere , 0.09)
CreateEntity(#sphere, MeshID(#sphere), MaterialID(#RedMaterial) , 3,5,-2)
EntityPhysicBody(#sphere, #PB_Entity_SphereBody)

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

wireFrame = 1

;doc: draw thick lines from x,y,z to x2,y2,z2
;doc: LineXYZ(#mesh, x,y,z, x2,y2,z2)
LineXYZ(1,  1,0.4,-2,  3,4,-2) ;:HideEntity(1,1) ;to hide the thin lines
LineXYZ(2,  5,4,-2,  3,0,3)  ;:HideEntity(2,1)
LineXYZ(3,  5,4,-2,  0,0,0)  ;:HideEntity(3,1)

;For i=4 To 500 ; make a huge tubes jungle
;LineXYZ(i,  Random(10,0),Random(10,0),Random(10,0),  Random(10,0),Random(10,0),Random(10,0))
;HideEntity(i,1)
;Next

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
            
      EndIf
  
      RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera(#Camera, KeyX, 0, KeyY)
      
      ;RotateEntity(0, 0,0,rot)
         
      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)
  
  Dim vertx.vertex(10)
  lineVec.vector3d

   u.f: r.f
      
  txu.f : txv.f
   
  x1.f = x
  y1.f = y
  z1.f = z
  
  
  ;vector of the line between start vertex and the end vertex
  lineVec\x = x2 - x1
  lineVec\y = y2 - y1
  lineVec\z = z2 - z1
  
  
   ;Dist.f = Sqr(lineVec\x*lineVec\x + lineVec\y*lineVec\y + lineVec\z*lineVec\z)
  ;Debug Dist
  tt.f = 0
  
  For i=0 To #Rings
        
       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 #Rings-1
     
        ;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 LineXYZ (Line3D, x.f, y.f,z.f, x2.f, y2.f,z2.f)
    
    x.f+0.00001 : y.f+0.00001 : z.f+0.00001 ; i don't know why 0.00001 is necessary
    x2.f+0.00001 : y2.f+0.00001 : z2.f+0.00001 ; if x,y,z or x2,y2,z2 are zero !!!
    CreateMesh(Line3D, #PB_Mesh_LineList , #PB_Mesh_Static)
    
    MeshVertexColor(RGB(255,0,0)) 
    MeshVertexPosition(x, y, z) 
    MeshVertexPosition(x2, y2, z2) 
   
    FinishMesh(#True)
    
    CreateEntity(Line3D,MeshID(Line3D),MaterialID(0) )
    tube = Line3D + 2000 
    CreateMesh(tube , #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )
    SetMeshMaterial(tube , MaterialID(2))
    ;; 0.00001 : necessary if all x,t,z are zero
    DrawTube (x+0.00001, y+0.00001, z+0.00001, x2, y2, z2)
    FinishMesh(tube)
    NormalizeMesh(tube)
    BuildMeshTangents(tube)
    CreateEntity(tube,MeshID(tube),MaterialID(2))
    AttachEntityObject(Line3D,"",EntityID(tube))
    EntityPhysicBody(tube, #PB_Entity_StaticBody)
    
      
    
  EndProcedure
  
 
 

Re: thick and thin lines, and tubes of all shapes

Posted: Thu Nov 27, 2014 11:19 am
by applePi
adding more choices for the function: LineXYZ:
LineXYZ(mesh, x,y,z, x2,y2,z2, Radius.f, TubeShape, Material)
mesh: is the thin line mesh which guides the weaving of the tube around it
radius: tube radius
TubeShape: 3 means triangular tube shape, 4 rectangular and so on
Material: the number of the material you have previously defined
here is an arial picture of several tubes with different shapes and orientations made easily
direct the camera inside the big tube and make a tour.
Image

Edit: added physics to the big 7 sides tube and rotating it around itself while a sphere inside it.

Code: Select all

#CameraSpeed = 0.2

#Rings = 2 ;number of Rings over all the Line (always 2, start ring and end ring)
#sphere = 17
#RedMaterial = 18

Global tube
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, Radius.f, TubeShape)
Declare LineXYZ (Line3D, x.f, y.f, z.f, x2.f, y2.f, z2.f, Radius.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

Define.f KeyX, KeyY, MouseX, MouseY

Enumeration
  #Window = 500
  #Plane
  #Camera
  #Light1
    
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)

If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "thick lines , W toggle wire/solid Frame ...., mouse and arrow keys to move/ rotate the camera ")
  If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
    
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, -40, 40, 30, #PB_Absolute)
    CameraLookAt(#Camera,1,10,-25)
    CameraBackColor(#Camera, RGB(200,200,200))
    
    CreateMaterial(0, LoadTexture(0, "white.jpg"))
    DisableMaterialLighting(0, #True)
    
    CreateMaterial(1, LoadTexture(1, "MRAMOR6X6.jpg"))
    MaterialCullingMode(1, #PB_Material_NoCulling)

    CreateMaterial(2, LoadTexture(2, "ground_diffuse.png"))
    MaterialCullingMode(2, #PB_Material_NoCulling)
    DisableMaterialLighting(2, #False)
        
    CreateMaterial(3, LoadTexture(3, "wood.jpg"))
    DisableMaterialLighting(3, #False)
    MaterialCullingMode(3, #PB_Material_NoCulling)
    
    GetScriptMaterial(#RedMaterial, "Color/Red")
    
    CreateLight(#Light1, RGB(255, 255, 255), 0, 20, 20)
    AmbientColor(RGB(255, 255, 255))
  
  EndIf
EndIf

CreatePlane(#plane, 600, 600, 100, 100, 100, 100)
CreateEntity(#plane,MeshID(#plane),MaterialID(1), 0, 0, 0)

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

wireFrame = 1

;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: LineXYZ(#mesh, x,y,z, x2,y2,z2, Radius.f, TubeShape, Material)
LineXYZ(1,  1,0,-2,  1,6,-2, 1, 4, 2) ;:HideEntity(1,1) ;to hide the thin lines
LineXYZ(2,  5,4,-2,  3,0,3, 0.1, 8, 2)  ;:HideEntity(2,1)
LineXYZ(3,  20,10,-2,  0,0,0, 1, 3, 3)  ;:HideEntity(3,1)
LineXYZ(4,  -12,0,-20,  -12,5,-20, 10, 5, 3)
LineXYZ(5,  16,0,-20,  16,7,-20, 10, 4, 3)
LineXYZ(6,  0,0,-45,  0,6,-45, 15, 3, 3)
;LineXYZ(7,  0,18,-60,  0,18,-120, 15, 7, 2)
LineXYZ(7,  0,0,30,  0,0,-30, 15, 7, 2) ;we make a gigantic tube at center
MoveEntity(tube, 0,18,-90) ;then we move it to any place so when it is rotating it is rotating correctly around itself 

EnableWorldPhysics(#True)
CreateSphere(#sphere , 2)
CreateEntity(#sphere, MeshID(#sphere), MaterialID(#RedMaterial) , 0,18,-90)
EntityPhysicBody(#sphere, #PB_Entity_SphereBody)
EntityPhysicBody(tube, #PB_Entity_StaticBody)

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
            
      EndIf
  
      RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera(#Camera, KeyX, 0, KeyY)
      RotateEntity(tube, 0,0,1, #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

Procedure  DrawTube (x.f, y.f,z.f, x2.f, y2.f,z2.f, Radius.f, TubeShape)
  
  Dim vertx.vertex(10)
  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
  
  
   ;Dist.f = Sqr(lineVec\x*lineVec\x + lineVec\y*lineVec\y + lineVec\z*lineVec\z)
  ;Debug Dist
  tt.f = 0
  
  For i=0 To #Rings
        
       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 #Rings-1
     
        ;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 LineXYZ (Line3D, x.f, y.f,z.f, x2.f, y2.f,z2.f, Radius.f, TubeShape, Material)
    
    x.f+0.00001 : y.f+0.00001 : z.f+0.00001 ; i don't know why 0.00001 is necessary
    x2.f+0.00001 : y2.f+0.00001 : z2.f+0.00001 ; if x,y,z or x2,y2,z2 are zero !!!
    CreateMesh(Line3D, #PB_Mesh_LineList , #PB_Mesh_Static)
    
    MeshVertexColor(RGB(255,0,0)) 
    MeshVertexPosition(x, y, z) 
    MeshVertexPosition(x2, y2, z2) 
   
    FinishMesh(#True)
    
    CreateEntity(Line3D,MeshID(Line3D),MaterialID(0) )
    tube = Line3D + 2000 
    CreateMesh(tube , #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )
    ;SetMeshMaterial(tube , MaterialID(Material))
    ;; 0.00001 : necessary if all x,t,z are zero
    DrawTube (x+0.00001, y+0.00001, z+0.00001, x2, y2, z2, Radius, TubeShape)
    FinishMesh(tube)
    NormalizeMesh(tube)
    BuildMeshTangents(tube)
    CreateEntity(tube,MeshID(tube),MaterialID(Material))
    ;AttachEntityObject(Line3D,"",EntityID(tube))
    
      
    
  EndProcedure
  
 
 

Re: thick and thin lines, and tubes of all shapes

Posted: Thu Nov 27, 2014 4:27 pm
by IdeasVacuum
That is very nice work applePi, though it is still one entity type (mesh) masquerading as another type (wireframe). PB already has wireframe types in the 2D Drawing lib, so we just need Fred to add Z...........

Re: thick and thin lines, and tubes of all shapes

Posted: Thu Nov 27, 2014 9:00 pm
by applePi
IdeasVacuum said: so we just need Fred to add Z...........
you are right IdeasVacuum, every effort to add Z to the FlatLand will be great, even we may need someday 4D coordinate, there is a good book called "The Fourth Dimension Toward a Geometry of Higher Reality" by Rudy Rucker.
my last attempt is to represent Hilbert curve http://www.purebasic.fr/english/viewtop ... 12&t=60397 by the tubes
Image
in fact there is no necessity to make 2 meshes one for the line and one for the tube, it is suffice to make a tube guided by the line or the curve, but the omega oil effect seems to end.
note: there is a need to connect the pipes with a pipe elbow, but this is another project for the future.
Edit:: shortening the code more, no need to create lines first. just the tubes

Code: Select all

Enumeration
  #Window = 500
  #ground
  #Camera
  #Light1
  #sphere
    
EndEnumeration

#CameraSpeed = 3
#RADIUS  = 1.5 ;tube thickness

Global bands = 8 ;number of points of every ring (circle)

#Rings = 2 ;number of Rings over all the tube 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(100)

Declare DrawTube (x.f, y.f,z.f, x2.f, y2.f, z2.f)
Declare LineXYZ (Line3D, x.f, y.f, z.f, x2.f, y2.f, z2.f)

Global.f x0, y0
;Global tubeee
x0 = 0: y0 = 0
Define.f KeyX, KeyY, MouseX, MouseY

Procedure Hilbert(depth.i, dx.f, dy.f)
  Static tubeee
  tubeee+1
  If depth > 1 
 
    Hilbert(depth - 1, dy, dx)
    LineXYZ(tubeee,  x0,0,y0,  x0+dx, 0, y0+dy)
    x0 + dx: y0 + dy
   
  
    Hilbert(depth - 1, dx, dy)
    LineXYZ(tubeee,  x0,0,y0,  x0+dy, 0, y0+dx)
    x0 + dy: y0 + dx
 
  
  
    Hilbert(depth - 1, dx, dy)
    LineXYZ(tubeee,  x0,0,y0,  x0-dx, 0, y0-dy)
    x0 - dx: y0 - dy
  
    
    Hilbert(depth - 1, -dy, -dx)
  EndIf
  
EndProcedure
	 
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

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, "thick lines , W toggle wire/solid Frame ...., mouse and arrow keys to move/ rotate the camera ")
  If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
    
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, 100, 150, 350, #PB_Absolute)
    CameraLookAt(#Camera,100,-100,80)
    CameraBackColor(#Camera, RGB(200,200,200))
    
    CreateMaterial(0, LoadTexture(0, "white.jpg"))
    DisableMaterialLighting(0, #False)
    SetMaterialColor(0, #PB_Material_AmbientColor, RGB(250, 255, 0))
    SetMaterialColor(0, #PB_Material_SpecularColor, RGB(255, 255, 0))

    CreateMaterial(1, LoadTexture(1, "MRAMOR6X6.jpg"))
    MaterialCullingMode(1, #PB_Material_NoCulling)

    CreateMaterial(2, LoadTexture(2, "ground_diffuse.png"))
    ;CreateMaterial(2, LoadTexture(2, "wood.jpg"))
    MaterialCullingMode(2, #PB_Material_NoCulling)
    DisableMaterialLighting(2, #False)
    SetMaterialColor(2, #PB_Material_AmbientColor, RGB(250, 255, 0))
    SetMaterialColor(2, #PB_Material_SpecularColor, RGB(255, 255, 0))
    
    CreateMaterial(0, LoadTexture(0, "wood.jpg"))
    DisableMaterialLighting(0, #True)
    
    CreateLight(#Light1, RGB(255, 255, 255), 0, 20, 20)
    AmbientColor(RGB(255, 255, 255))
  
  EndIf
EndIf


wireFrame = 1
depth.i = 6
Hilbert(depth, 8, 0)
CreateCube(#ground, 1)
CreateEntity(#ground,MeshID(#ground),MaterialID(0), 120, -25, 100)
ScaleEntity(#ground, 300,1, 300)
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
            
      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)
  
  Dim vertx.vertex(2)
  lineVec.vector3d

	u.f: r.f
      
  txu.f : txv.f
   
  x1.f = x
  y1.f = y
  z1.f = z
  
  
  ;vector of the line between start vertex and the end vertex
  lineVec\x = x2 - x1
  lineVec\y = y2 - y1
  lineVec\z = z2 - z1
  
  
	;Dist.f = Sqr(lineVec\x*lineVec\x + lineVec\y*lineVec\y + lineVec\z*lineVec\z)
  ;Debug Dist
  tt.f = 0
  
  For i=0 To #Rings
        
	    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 #Rings-1
	  
        ;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 LineXYZ (Line3D, x.f, y.f,z.f, x2.f, y2.f,z2.f)
    Static tube
    
    tube + 1 ; tube mesh ID
    
    CreateMesh(tube , #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )
    SetMeshMaterial(tube , MaterialID(2))
    ; 0.00001 : necessary if all x,t,z are zero
    DrawTube (x+0.00001, y+0.00001, z+0.00001, x2, y2, z2)
    FinishMesh(tube)
    NormalizeMesh(tube)
    BuildMeshTangents(tube)
    CreateEntity(tube,MeshID(tube),MaterialID(2))
    
  EndProcedure