in a previous post i have posted a knot example but with points and then with big points, because i don't know then how to make custom or free oriented tubes. until i have found a freebasic code which have inside it an algorithm to align rings *circles" perpendicular to a curve at a corresponding points, look my new post in 3D section for details:
http://www.purebasic.fr/english/viewtop ... 36&t=56642
now here is the knot made from tube, it is displayed great, but with a very small annoyance, it takes it too much time compared to the corresponding example i have posted for PB Ogre.
this MP3D code have
#NUM_RINGS = 180 ; number of rings over all the tube
#NUM_BANDS = 16 ; number of points of every ring (circle)
and it is displayed after 4 seconds on my old pc with Geforce 210,
but in my example for PB ogre it is:
#NUM_RINGS = 360 ; number of rings over all the tube
#NUM_BANDS = 32 ; number of points of every ring (circle)
and it is displayed immediately, using 360 and 32 in MP3D will displayed after 25 seconds. so could it be something in my code ??.
notes:
1- press S to save the tube to "knot.x" file
2-a fun part when you press "D" key to delete parts of the tube
Code: Select all
#TWOPI = 2 * #PI ;PI For rotation
#NUM_RINGS = 180 ; number of rings over all the tube
#NUM_BANDS = 16 ; number of points of every ring (circle)
#BAND_RAD = 0.5 ;tube thickness
#BUTTON = 6
;Global.f rot = 1
Global stop = 0
Structure vector3d
x.f
y.f
z.f
EndStructure
Declare DrawTube (Rings.l, Bands.l,BandRadius.f)
Quit.b = #False
ExamineDesktops()
MP_Graphics3D (DesktopWidth(0),DesktopHeight(0),0,2) ; Erstelle ein WindowsFenster #Window = 0
SetWindowTitle(0, "Tubes .. press space to toggle rotation, press S to save to knot.x file")
ButtonGadget(#BUTTON, 0, DesktopHeight(0)-60, 60, 30, "rotate/stop")
MP_Viewport(0,0,DesktopWidth(0),DesktopHeight(0)-60)
camera=MP_CreateCamera()
light=MP_CreateLight(2)
MP_LightSetColor (light, RGB(255,255,255))
MP_PositionCamera(camera, 0, 5, 10)
MP_CameraLookAt(camera,0,0,0)
MP_PositionEntity(light, 0, 10, 20)
MP_EntityLookAt(light,0,0,0)
Global Mesh = MP_CreateMesh()
SetActiveGadget(#BUTTON)
Quit.b = #False
;==============================================================
tex$ = #PB_Compiler_Home + "Examples/3D/Data/Textures/" + "terrain_texture.jpg"
Texture = MP_LoadTexture(tex$)
MP_EntitySetTexture (Mesh, Texture )
MP_MaterialEmissiveColor (Texture,0,255,255,255)
MP_PositionCamera(camera, 0, 0, 10)
MP_CameraLookAt(camera,0,0,0)
MP_PositionEntity(light, 0 , 0, 10)
MP_EntityLookAt(light,0,0,0)
DrawTube (#NUM_RINGS, #NUM_BANDS, #BAND_RAD )
MP_PositionEntity (Mesh,0,0,-3)
;MP_ScaleEntity(Mesh, 0.5, 0.5, 0.5)
rot.l=1 :stopFlag = 1 : wireFrame.b = 0
xs.f = 1:ys.f = 1:zs.f = 1
x.f: y.f :z.f: x0.f: y0.f=1 :z0.f
rotx.f:roty.f=0.5:rotz.f :rotx0.f: roty0.f: rotz0.f
h.f=0:up.f=0.1:depth.f=3
x.f=90: y.f=0: z.f=0 :indx = 126
Repeat
Event = WindowEvent()
If Event = #PB_Event_Gadget
Select EventGadget()
Case #BUTTON
If rot = 0
rot = 1
rotx= rotx0:roty=roty0:rotz=rotz0 ; restore rotation status
stopFlag = 1
Else
rot = 0
rotx0= rotx:roty0=roty:rotz0=rotz ;back up rotation status
rotx=0:roty=0:rotz=0
stopFlag = 0
EndIf
EndSelect
EndIf
If stopFlag=1
x + rotx
y + roty
z + rotz
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
If MP_KeyDown(#PB_Key_Up) ; rotate left
rotx=1:roty=0:rotz=0
rotx0 = rotx: roty0 = roty :rotz0 = rotz
x + rotx
y + roty
z + rotz
stopFlag=0
rot = 0
ElseIf MP_KeyDown(#PB_Key_Down) ; rotate right
rotx=-1:roty=0:rotz=0
rotx0 = rotx: roty0 = roty :rotz0 = rotz
x + rotx
y + roty
z + rotz
stopFlag=0
rot = 0
ElseIf MP_KeyDown(#PB_Key_Right) ; rotate up
rotx=0:roty=1:rotz=0
rotx0 = rotx: roty0 = roty :rotz0 = rotz
x + rotx
y + roty
z + rotz
stopFlag=0
rot = 0
ElseIf MP_KeyDown(#PB_Key_Left) ; rotate down
rotx=0:roty=-1:rotz=0
rotx0 = rotx: roty0 = roty :rotz0 = rotz
x + rotx
y + roty
z + rotz
stopFlag=0
rot = 0
EndIf
If MP_KeyDown(#PB_Key_PageUp) ; scale up model
xs.f + 0.01:ys.f + 0.01:zs.f + 0.01
MP_ScaleEntity(Mesh,xs,ys,zs)
ElseIf MP_KeyDown(#PB_Key_PageDown) ; scale down model
xs -0.01:ys -0.01:zs- 0.01
If xs<0 :xs=0:ys=0:zs=0:EndIf
MP_ScaleEntity(Mesh,xs,ys,zs)
EndIf
If MP_KeyDown(#PB_Key_Pad8) ; up move
up + 0.01
MP_PositionEntity(Mesh,h,up,depth)
ElseIf MP_KeyDown(#PB_Key_Pad2) ; down move
up - 0.01
MP_PositionEntity(Mesh,h,up,depth)
ElseIf MP_KeyDown(#PB_Key_Pad6)
h + 0.01
MP_PositionEntity(Mesh,h,up,depth)
ElseIf MP_KeyDown(#PB_Key_Pad4)
h - 0.01
MP_PositionEntity(Mesh,h,up,depth)
ElseIf MP_KeyDown(#PB_Key_Q) ; forward move
depth - 0.01
MP_PositionEntity(Mesh,h,up,depth)
ElseIf MP_KeyDown(#PB_Key_A) ; inward move
depth + 0.01
MP_PositionEntity(Mesh,h,up,depth)
ElseIf MP_KeyHit(#PB_Key_W) ; display wire frame for the material
If wireFrame=0
MP_Wireframe (1)
wireFrame ! 1
ElseIf wireFrame=1
MP_Wireframe (0)
wireFrame ! 1
EndIf
ElseIf MP_KeyDown(#PB_Key_D)
MP_FreeTriangle(Mesh, 1)
;indx -1: MP_FreeVertex(Mesh ,indx)
ElseIf MP_KeyDown(#PB_Key_S)
MP_SaveMesh("knot.x",Mesh)
EndIf
If MP_KeyDown(#PB_Key_Escape)
Quit = #True
EndIf
MP_DrawText (1,1,"press W _wireFrame, D _ delete triangles")
MP_DrawText (1,15,"keyPad keys: up.down.left.right")
MP_RotateEntity(Mesh, 90+x, y, z)
MP_RenderWorld() ; Erstelle die Welt
MP_Flip ()
Until Quit = #True Or Event = #PB_Event_CloseWindow
;beginning of frenet approx procedures
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
; main program
Procedure DrawTube (Rings.l, Bands.l, BandRadius.f)
x.f: y.f: z.f
op.f = 1
txu.f : txv.f
current_point.vector3d ; current point on tube curve
next_point.vector3d ; next point on tube curve
T.vector3d
B.vector3d
N.vector3d
p.f
For i = 0 To rings + 1
;center point
p = op * i * #TWOPI / rings
current_point\x = Cos(p) + 2.5*Cos(-2*p)
current_point\y = Sin(p) + 3.5*Sin(-2*p)
current_point\z = 2 * Sin(3*p)
;next point For Frenet square
p = op * (i + 1) * #TWOPI / rings
next_point\x = Cos(p) + 2.5*Cos(-2*p)
next_point\y = Sin(p) + 3.5*Sin(-2*p)
next_point\z = 2 * Sin(3*p)
;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 - 1
new_point_x.f
new_point_y.f
;rotate around the current point using normal rotation makes bands
new_point_x = Sin(j * #TWOPI / bands) * #BAND_RAD
new_point_y = Cos(j * #TWOPI / bands) * #BAND_RAD
;this is the coords 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
MP_AddVertex (Mesh, x, y,z,0,txu,txv)
txv = txv + 1/bands
Next
txv = 0
;txu = txu + 1/rings
txu = txu + 1/bands
Next
v.l
For i = 0 To rings - 1
For j = 0 To bands - 1
MP_AddTriangle (Mesh,v,v+1,v + bands+1)
MP_AddTriangle (Mesh,v + bands+1,v + bands+2,v+1 )
v + 1
Next
;MP_EntitySetNormals(Mesh)
Next
EndProcedure