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
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,

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