thick and thin lines, and tubes of all shapes

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

thick and thin lines, and tubes of all shapes

Post 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
Last edited by applePi on Thu Nov 27, 2014 11:12 am, edited 1 time in total.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: thick and thin lines

Post 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?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: thick and thin lines

Post 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
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: thick and thin lines

Post 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
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 756
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: thick and thin lines

Post 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
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: thick and thin lines

Post 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
  
 
 
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

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

Post 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
  
 
 
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

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

Post 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...........
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

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

Post 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
  
 
 
Post Reply