Funnel, Tube extension, Helix and many balls
Posted: Sun Nov 10, 2013 10:34 am
a continuation of the Tubes and pipes Tubes and pipes subject . here is the balls falling into a funnel and a tube extension then marching through a helical tube then falling to the ground , and after falling into the dark space their entities are deleted if its height (EntityY) are less than -7 (the ground are on Y = -6, i have learned Linked lists 2 days ago and used it in the procedure balls() so if there are errors please report, i replace the for/next loop. it seems the Entities deletions works okay .
about 1/10 of the balls escape the funnel and helix through the thin walls.
about 1/10 of the balls escape the funnel and helix through the thin walls.

Code: Select all
Enumeration
#plane
#cube
#ball
#Cone
#Tube_extension
EndEnumeration
Declare Cone(incr.f)
Declare tube_extension() ; 0.25 of a torus
Declare balls()
Global meshesNum
#manyPi = 10 * #PI ;PI For rotation
#NUM_RINGS = 360
;#NUM_RINGS = 70
#NUM_BANDS = 32
;#RING_RAD = 2.0
#BAND_RAD = 0.5 ; thickness of the tube
Global stop = 1
Global.f rot = 1
Global Dim ball(1000)
Global num
Global stoneNum
Structure vector3d
x.f
y.f
z.f
EndStructure
Declare DrawTube (Rings.l, Bands.l, BandRadius.f)
Quit.b = #False
ExamineDesktops()
OpenWindow(3, 0, 0, DesktopWidth(0), DesktopHeight(0), "Helix tube with Balls, Arrow keys and mouse to move/rotate ... W .toggle wire/solid ", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
;Initialize environment
InitEngine3D()
InitSprite()
OpenWindowedScreen(WindowID(3), 0, 0, DesktopWidth(0), DesktopHeight(0), 0, 0, 0)
InitKeyboard()
InitMouse()
SetFrameRate(60)
Add3DArchive(".", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
CreateMaterial(1, LoadTexture(1, "clouds.jpg"))
CreatePlane(#plane, 20, 20, 1, 1, 1, 1)
CreateEntity (#plane, MeshID(#plane), MaterialID(1))
MoveEntity(#plane,0,-6,0)
EntityPhysicBody(#plane, #PB_Entity_StaticBody)
CreateLight(0,RGB(255,255,255),-100,40,30)
AmbientColor(RGB(100,100,100))
CreateCamera(0, 0, 0, 100, 100)
MoveCamera(0, 0, 4, 12)
MoveCamera(0, 5, 10, 0)
;RotateCamera(0, -60,90,0)
CameraLookAt(0, 0, 2, 0)
;RotateCamera(0, -15, 0, 0)
;CreateMaterial(0, LoadTexture(0, "terrain_texture.jpg"))
CreateMaterial(0, LoadTexture(0, "wood.jpg"))
CreateMaterial(1, LoadTexture(1, "wood.jpg"))
MaterialCullingMode(0, #PB_Material_NoCulling)
;MaterialBlendingMode(0, #PB_Material_AlphaBlend )
MaterialShadingMode(0, #PB_Material_Wireframe)
DisableMaterialLighting(0, 1)
CreateMesh(1, #PB_Mesh_TriangleList, #PB_Mesh_Static )
SetMeshMaterial(1, MaterialID(0))
DrawTube (#NUM_RINGS, #NUM_BANDS, #BAND_RAD)
NormalizeMesh(1)
FinishMesh(1)
CreateEntity(1, MeshID(1), MaterialID(0))
MoveEntity(1,0,2,-2)
EntityPhysicBody(1, #PB_Entity_StaticBody ,0.1)
RotateEntity(1,90,250,0)
CreateMesh(#Tube_extension, #PB_Mesh_TriangleList, #PB_Mesh_Static)
SetMeshMaterial(#Tube_extension, MaterialID(0))
tube_extension() ; calling the tube_extension proc , for making 1/4 of a torus
EntityPhysicBody(#Tube_extension, #PB_Entity_StaticBody ,1,0.01,2)
CreateCube(#cube, 1) ; the block (fountain) wich direct the balls to the funnel
fountain = CreateEntity(#PB_Any,MeshID(#cube), MaterialID(1))
ScaleEntity(fountain,2,1,1)
MoveEntity(fountain,3,6,-1.5)
RotateEntity(fountain, 0, 0,135)
EntityPhysicBody(fountain,#PB_Entity_StaticBody ,100)
CreateMaterial(3, LoadTexture(3, "white.jpg"))
SetMaterialColor(3, #PB_Material_SelfIlluminationColor, RGB(255,0,0))
CreateSphere(#ball, 0.06)
CreateMesh(#Cone, #PB_Mesh_TriangleList, #PB_Mesh_Static)
Cone(0.05) ; the Funnel construction
EntityPhysicBody(#Cone, #PB_Entity_StaticBody ,1,0.01,2)
Global NewList Spheres()
ExamineKeyboard()
Global.f keyX, ketY, MouseY, MouseX
Repeat
Event = WindowEvent()
If KeyboardReleased(#PB_Key_W)
If wire=1
MaterialShadingMode(0, #PB_Material_Wireframe)
wire = 0
ElseIf wire = 0
MaterialShadingMode(0, #PB_Material_Solid)
wire = 1
EndIf
EndIf
If ExamineMouse()
MouseX = -MouseDeltaX()/10
MouseY = -MouseDeltaY()/10
EndIf
If ExamineKeyboard()
If KeyboardReleased(#PB_Key_G)
If gravity = 0
WorldGravity(1)
Else
WorldGravity(-9.806)
EndIf
gravity ! 1
EndIf
If KeyboardPushed(#PB_Key_Left)
KeyX = -0.5
ElseIf KeyboardPushed(#PB_Key_Right)
KeyX = 0.5
Else
KeyX = 0
EndIf
If KeyboardPushed(#PB_Key_Up)
KeyY = -0.5
ElseIf KeyboardPushed(#PB_Key_Down)
KeyY = 0.5
Else
KeyY = 0
EndIf
EndIf
RotateCamera(0, MouseY, MouseX, 0, #PB_Relative)
MoveCamera (0, KeyX, 0, KeyY)
;Delay(10)
balls()
RenderWorld()
FlipBuffers()
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Escape)
Quit = #True
EndIf
Until Quit = #True Or Event = #PB_Event_CloseWindow
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
Procedure DrawTube (Rings.l, Bands.l, BandRadius.f)
x.f: y.f: z.f
op.f = 1
txu.f : txv.f
For i = 0 To rings + 1
current_point.vector3d
next_point.vector3d
T.vector3d
B.vector3d
N.vector3d
p.f
;center point
p = op * i * #manyPi / rings
current_point\x = Cos(p)
current_point\y = Sin(p)
current_point\z = 0.2 * p
;next point For Frenet square
p = op * (i + 1) * #manyPi / rings
next_point\x = Cos(p)
next_point\y = Sin(p)
next_point\z = 0.2 * 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 * 2*#PI / bands) * #BAND_RAD
new_point_y = Cos(j * 2*#PI / 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
MeshVertexPosition(x, y, z)
MeshVertexTextureCoordinate(txu, txv)
MeshVertexNormal(x, y, z)
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
MeshFace(v,v+1,v + bands+1)
MeshFace(v + bands+1,v + bands+2,v+1 )
v + 1
Next
Next
EndProcedure
Procedure Cone(incr.f) ; incr determines the radius of the bigger nozzle
x.f: y.f :z.f : u.f: v.f: r.f
majorOrbit.l = 100 : minorOrbit.l = 20
majorStep.f = 2 * #PI / majorOrbit
minorStep.f = 2 * #PI / minorOrbit
i.l: j.l: txu.f : txv.f
SmallNozzle.f = 1 ; dertmine the radius of the smaller nozzle
For i = 0 To majorOrbit
If i > 40 ; the beginning point of the wider circles than the tube circles
SmallNozzle.f + incr ; incr determines the radius of the bigger nozzle
EndIf
v = i * majorStep
For j = 0 To minorOrbit
u = j * minorStep
r = 4 * (1 - (Cos(u)/2))
x = Cos(u)*10 * SmallNozzle
y = Sin(u)*10 * SmallNozzle
;z = Sin(v)
z+0.02
MeshVertexPosition(x, y, z);
MeshVertexTextureCoordinate(txu, txv)
MeshVertexNormal(x, y, z)
; texture the whole bottle with one picture stretched
txv = txv + 1/minorOrbit ; texture coordinates
Next
txv = 0
txu = txu + 1/majorOrbit
Next
For i = 0 To majorOrbit-1
For j = 0 To minorOrbit
MeshFace(t,t+1,t + minorOrbit+1)
MeshFace(t + minorOrbit+1,t + minorOrbit+2,t+1 )
If i=majorOrbit-1 And j=minorOrbit-1 ;bypass the last triangle
minorOrbit-1
EndIf
t + 1
Next
Next
NormalizeMesh(#Cone)
FinishMesh(#True)
CreateEntity(#Cone, MeshID(#Cone), MaterialID(0))
ScaleEntity(#Cone,0.03, 0.03, 0.03)
MoveEntity(#Cone, 1.5, 4.5, -1.1,#PB_Absolute)
RotateEntity(#Cone,-90,0,0)
EndProcedure
Procedure tube_extension()
x.f: y.f :z.f : u.f=0 :txu.f : txv.f
rMajor.f = 2 : rMinor.f = 0.5
majorRadius.f = 2: minorRadius.f = 0.5: numMajor.l = 50: numMinor.l = 25
majorStep.f = 0.5 * #PI / (numMajor+0);
minorStep.f = 2 * #PI / (numMinor+0)
i.l: j.l
For i = 0 To numMajor
t.f = i * majorStep;
For j = 0 To numMinor
u.f = j * minorStep;
x = Cos(t) * (majorRadius + minorRadius * Cos(u))
y = Sin(t) * (majorRadius + minorRadius * Cos(u))
z.f = minorRadius * Sin(u)
tt+1
;If tt>1326 :Break:EndIf
MeshVertexPosition(x, y, z);
MeshVertexTextureCoordinate(txu, txv)
MeshVertexNormal(x, y, z)
txv = txv + 1/numMinor ; texture coordinates
Next
txv = 0
txu = txu + 1/numMajor ;texture coordinates
Next
;Debug tt: Debug t
v.l=0 :tt=0
For i = 0 To numMajor
For j = 0 To numMinor-1
tt+1
If tt>1273 :Break:EndIf
MeshFace(v,v+1,v + numMinor+1)
MeshFace(v + numMinor+1,v + numMinor+2,v+1 )
If i=numMajor-1 And j=numMinor-1 ;bypass the last triangle
;numMinor-1
EndIf
v + 1
Next
Next
;last vertex to connect:
NormalizeMesh(#Tube_extension)
FinishMesh(#True)
CreateEntity(#Tube_extension, MeshID(#Tube_extension), MaterialID(0))
RotateEntity(#Tube_extension, 0,0,-90)
MoveEntity(#Tube_extension,-0.4,4.0, -1.1,#PB_Absolute)
EndProcedure
Procedure balls()
OneBall = CreateEntity(#PB_Any, MeshID(#ball), MaterialID(3), 2.0, 6.6, -1.5)
AddElement(Spheres()) : Spheres() = OneBall
SetMaterialColor(3, #PB_Material_SelfIlluminationColor, RGB(255,0,0))
EntityPhysicBody(OneBall, #PB_Entity_SphereBody, 1)
ApplyEntityImpulse(OneBall, 0, 2,0)
meshesNum = ListSize(Spheres())
If meshesNum > 300
ForEach Spheres()
TempMesh = Spheres()
;If IsEntity(TempMesh)
If EntityY(TempMesh) < -7 Or EntityY(TempMesh) > 40
FreeEntity(TempMesh)
DeleteElement(Spheres() )
EndIf
;EndIf
Next
EndIf
EndProcedure