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

Code: Select all
Define.f KeyX, KeyY, MouseX, MouseY
Enumeration
#Window = 500
#plane
#Camera
#Light1
#Light2
#sphere
#mat
#tex
#BillboardGroup
EndEnumeration
#CameraSpeed = 1
#Rings = 2 ;number of Rings over all the Line (always 2, start ring and end ring)
Structure vector3d
x.f
y.f
z.f
EndStructure
Structure vertex
x.f
y.f
z.f
EndStructure
Dim vertx.vertex(32)
Declare DrawTube (x.f, y.f,z.f, x2.f, y2.f, z2.f, RadiusS.f, RadiusE.f, TubeShape)
Declare TubeXYZ (tube, x.f, y.f, z.f, x2.f, y2.f, z2.f, RadiusS.f, RadiusE.f, TubeShape, Material)
Procedure vector_cross(*v1.vector3d, *v2.vector3d, *vout.vector3d)
*vout\x = (*v1\y * *v2\z) - (*v2\y * *v1\z)
*vout\y = (*v1\z * *v2\x) - (*v2\z * *v1\x)
*vout\z = (*v1\x * *v2\y) - (*v2\x * *v1\y)
EndProcedure
Procedure.f vector_magnitude(*v.vector3d)
mag.f
mag = Sqr(*v\x * *v\x + *v\y * *v\y + *v\z * *v\z)
If mag = 0:mag = 1:EndIf
ProcedureReturn mag
EndProcedure
Procedure vector_normalize (*v.vector3d)
mag.f
mag = vector_magnitude(*v)
*v\x = *v\x / mag
*v\y = *v\y / mag
*v\z = *v\z / mag
EndProcedure
Procedure vector_add (*v1.vector3d, *v2.vector3d, *vout.vector3d)
*vout\x = *v1\x + *v2\x
*vout\y = *v1\y + *v2\y
*vout\z = *v1\z + *v2\z
EndProcedure
Procedure vector_sub (*v1.vector3d, *v2.vector3d, *vout.vector3d)
*vout\x = *v1\x - *v2\x
*vout\y = *v1\y - *v2\y
*vout\z = *v1\z - *v2\z
EndProcedure
If InitEngine3D()
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts",#PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite()
InitKeyboard()
InitMouse()
ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)
OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "Cone ... , W toggle wire/solid Frame ..., H hide/unhide the sun..., mouse and arrow keys to move/ rotate the camera ")
OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
CreateCamera(#Camera, 0, 0, 100, 100)
MoveCamera(#Camera, 0, 50, 110, #PB_Absolute)
CameraLookAt(#Camera,0,0,0)
CameraBackColor(#Camera, RGB(197,225,235))
CreateMaterial(0, LoadTexture(0, "white.jpg"))
DisableMaterialLighting(0, #True)
CreateMaterial(1, LoadTexture(1, "snow_1024.jpg"))
MaterialCullingMode(1, #PB_Material_NoCulling)
CreateMaterial(2, LoadTexture(2, "ground_diffuse.png"))
MaterialCullingMode(2, #PB_Material_NoCulling)
DisableMaterialLighting(2, #False)
CreateLight(#Light1, RGB(200, 200, 200), 0, 45, 45)
AmbientColor(RGB(200, 200, 200))
CreateLight(#Light2, RGB(200, 200, 200), -5, 15, -5)
CreatePlane(#plane, 200, 200, 50, 50, 10, 10)
CreateEntity(#plane,MeshID(#plane),MaterialID(1), 0, 0, 0)
;glLineWidth_(5)
CreateLine3D(7, 0, 0.05, 0, RGB(255, 0, 0), 100, 0.05, 0, RGB(255, 0, 0)) ; Axis X
CreateLine3D(8, 0, 0, 0, RGB( 0, 255, 0), 0, 100, 0, RGB( 0, 255, 0)) ; Axis Y
CreateLine3D(9, 0, 0.05, 0, RGB( 0, 0, 255), 0, 0.05, 100, RGB( 0, 0, 255)) ; Axis Z
;doc: draw thick lines from x,y,z to x2,y2,z2 with thickness Radius and TubeShape is the number of points makes the tube cross section polygon
;doc: TubeXYZ(#mesh, x,y,z, x2,y2,z2, TubeRadiusStart.f,TubRadiusEnd.f, TubeShape, Material)
;TubeXYZ(2, 20,0,-2, 20,30,-2, 15, 0, 32, 2)
TubeXYZ(2, 0,0,0, 0,30,0, 35, 0, 32, 2)
EnableWorldPhysics(#True)
EntityPhysicBody(#plane, #PB_Entity_StaticBody, 1, 1, 0.1)
CreateSphere(#sphere, 4)
CreateEntity(#sphere, MeshID(#sphere), MaterialID(2), 0, 4,0)
; Create electric light ; or use the method in staticGeometry.pb example
LoadTexture(#tex , "Lensflare5.jpg") ; for the sprite
CreateMaterial(#mat, TextureID(#tex))
SetMaterialColor(#mat, #PB_Material_AmbientColor, RGB(1,1,1))
SetMaterialColor(#mat, #PB_Material_DiffuseColor, RGB(1,1,1))
DisableMaterialLighting(#mat, 1)
MaterialBlendingMode(#mat, #PB_Material_Add )
CreateBillboardGroup(#BillboardGroup, MaterialID(#mat), 10,10, 0, 0, 0)
AddBillboard(#BillboardGroup, -5, 15, -5)
AddBillboard(#BillboardGroup, 0, 45, 45)
WorldShadows(#PB_Shadow_Modulative , -1, RGB(200, 200, 200))
;WorldShadows(#PB_Shadow_Additive)
;EntityRenderMode(#plane, 0)
wireFrame = 1: hide = 1
Repeat
Event = WindowEvent()
If ExamineMouse()
MouseX = -MouseDeltaX()/20
MouseY = -MouseDeltaY()/20
EndIf
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
KeyX = -#CameraSpeed
ElseIf KeyboardPushed(#PB_Key_Right)
KeyX = #CameraSpeed
Else
KeyX = 0
EndIf
If KeyboardPushed(#PB_Key_Up)
KeyY = -#CameraSpeed
ElseIf KeyboardPushed(#PB_Key_Down)
KeyY = #CameraSpeed
Else
KeyY = 0
EndIf
If KeyboardReleased(#PB_Key_W)
If wireFrame
MaterialShadingMode(2, #PB_Material_Wireframe)
wireFrame ! 1
Else
MaterialShadingMode(2, #PB_Material_Solid)
wireFrame ! 1
EndIf
EndIf
If KeyboardReleased(#PB_Key_H)
If hide
HideBillboardGroup(#BillboardGroup, 1)
hide ! 1
EntityRenderMode(#sphere, 0)
EntityRenderMode(2, 0) ; 2 is the Cone
Else
HideBillboardGroup(#BillboardGroup, 0)
hide ! 1
EntityRenderMode(#sphere, #PB_Entity_CastShadow )
EntityRenderMode(2, #PB_Entity_CastShadow ) ; 2 is the Cone
EndIf
EndIf
EndIf
RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
MoveCamera(#Camera, KeyX, 0, KeyY)
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
Else
MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End
Procedure DrawTube (x.f, y.f,z.f, x2.f, y2.f,z2.f, RadiusS.f, RadiusE.f, TubeShape)
Dim vertx.vertex(2)
lineVec.vector3d
u.f: r.f
txu.f : txv.f
x1.f = x
y1.f = y
z1.f = z
bands = TubeShape
;vector of the line between start vertex and the end vertex
lineVec\x = x2 - x1
lineVec\y = y2 - y1
lineVec\z = z2 - z1
tt.f = 0
For i=0 To 2
x = x1 + lineVec\x * tt
y = y1 + lineVec\y * tt
z = z1 + lineVec\z * tt
tt + 1
vertx(i)\x = x
vertx(i)\y = y
vertx(i)\z = z
Next
current_point.vector3d
next_point.vector3d
T.vector3d
B.vector3d
N.vector3d
p.f
For i = 0 To 1
If i=0 ; to manage the radius of tube start and tube end
Radius.f = RadiusS
Else
Radius.f=RadiusE
EndIf
;center point
current_point\x = vertx(i)\x
current_point\y = vertx(i)\y
current_point\z = vertx(i)\z
;next point For Frenet square
next_point\x = vertx(i+1)\x
next_point\y = vertx(i+1)\y
next_point\z = vertx(i+1)\z
;T = P' - P
vector_sub(next_point, current_point, T)
;N = P' + P
vector_add(next_point, current_point, N)
;B = T x N
vector_cross(T, N, B)
;N = B x T
vector_cross(B, T, N)
;Normalize vectors Or Else it won't work
vector_normalize(B)
vector_normalize(N)
For j = 0 To bands
new_point_x.f
new_point_y.f
;rotate around the current point using normal rotation makes bands
new_point_x = Sin(j * (#PI*2) / bands) * Radius
new_point_y = Cos(j * (#PI*2) / bands) * Radius
;this is the coordinates of our point along the curve
x = N\x * new_point_x + B\x * new_point_y + current_point\x
y = N\y * new_point_x + B\y * new_point_y + current_point\y
z = N\z * new_point_x + B\z * new_point_y + current_point\z
MeshVertexPosition(x, y, z)
MeshVertexTextureCoordinate(txu, txv)
MeshVertexNormal(1, 1, 1)
txv = txv + 1/#Rings
Next
txv = 0
txu = txu + 1/bands
Next
v.l
For j = 0 To bands -1
;MeshFace(v,v+1,v + bands+1)
;MeshFace(v + bands+1,v + bands+2,v+1 )
MeshFace(v,v + bands+1, v+1)
MeshFace(v + bands+1, v + bands+2, v+1 )
v + 1
Next
EndProcedure
Procedure TubeXYZ (tube, x.f, y.f,z.f, x2.f, y2.f,z2.f, RadiusS.f, RadiusE.f, TubeShape, Material)
x.f+0.00001 : y.f+0.00001 : z.f+0.00001 ; +0.00001 necessary if x,y,z or x2,y2,z2 are zero !!!
x2.f+0.00001 : y2.f+0.00001 : z2.f+0.00001
CreateMesh(tube , #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )
DrawTube (x, y, z, x2, y2, z2, RadiusS, RadiusE, TubeShape)
NormalizeMesh(tube)
BuildMeshTangents(tube)
FinishMesh(tube)
CreateEntity(tube,MeshID(tube),MaterialID(Material))
EndProcedure