i want to implement the tubes in MP3D, the following
first code is the PB Ogre example , it plotes tubes from x1,y1,z1 to x2,y2,z2 in any tube start radius and tube end radius.
in the cartesian coordinates it looks drawn exactly, look the floor square: every square are 1 unit. as an example look the conic tube it is positioned on the ground at (+1,0,-2)
the
second code: is trying to imitate the first code in
MP3D
i can't make it looks like the first code regarding the positions of the tube,
also can we correct the camera move and rotation to be exactly like the first code.
if we make the simple camera rotation (one function ) behaves like the first code then we get rid from the complex coding for moving+rotating the camera
3- how we can texture the floor like the first code , ie many squares by more than the original texture squares numbers?
first code: in PB Ogre engine:
Code: Select all
#CameraSpeed = 0.05
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)
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, "Tubes, 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: the tube extents from x,y,z to x2,y2,z2
;doc: TubeXYZ(#mesh, x,y,z, x2,y2,z2, RadiusS, RadiusE, TubeShape, Material)
TubeXYZ(1, 1,0,-2, 1,4,-2, 0.1, 1, 16, 2) ; RadiusS: tube Start radius, RadiusE: tube end radius
TubeXYZ(2, 5,4,-2, 3,0,3, 0.1, 0.1, 8, 2) ; TubeShape: 3 triangular, 4 square, etc, 16 almost circular
TubeXYZ(3, 5,4,-2, 0,0,0, 0.1, 0.1, 8, 2) ; 2 is the material number
Repeat
Event = WindowEvent()
If ExamineMouse()
MouseX = -MouseDeltaX()/20
MouseY = -MouseDeltaY()/20
RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
EndIf
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
KeyX = -#CameraSpeed
ElseIf KeyboardPushed(#PB_Key_Right)
KeyX = #CameraSpeed
Else
KeyX = 0
MoveCamera(#Camera, KeyX, 0, KeyY)
EndIf
If KeyboardPushed(#PB_Key_Up)
KeyY = -#CameraSpeed
ElseIf KeyboardPushed(#PB_Key_Down)
KeyY = #CameraSpeed
Else
KeyY = 0
MoveCamera(#Camera, KeyX, 0, KeyY)
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
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
Else
MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End
;beginning of frenet sqaure approximation 5 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
;end of frenet sqaure approximation 5 procedures
Procedure DrawTube (x.f, y.f,z.f, x2.f, y2.f,z2.f, RadiusS.f, RadiusE.f, TubeShape)
#Rings = 2 ; the start and end tube circles.
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 ;number of points of every ring (circle):
;continue: 2 flat tube, 3 triangular tube, 4 rectangular, 8 almost cylindrical tube
;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 #Rings ; 3 points because Frenet proc needs the third point coordinates to calc the middle point
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
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(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 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)
FinishMesh(tube)
NormalizeMesh(tube)
BuildMeshTangents(tube)
CreateEntity(tube,MeshID(tube),MaterialID(Material))
EndProcedure
second code: in PB MP3D engine:
Code: Select all
#CameraSpeed = 0.1
Define.f KeyX, KeyY, MouseX, MouseY
Structure vector3d
x.f
y.f
z.f
EndStructure
Structure vertex
x.f
y.f
z.f
EndStructure
Declare DrawTube (x.f, y.f,z.f, x2.f, y2.f, z2.f, RadiusS.f, RadiusE.f, TubeShape)
ExamineDesktops()
MP_Graphics3D (DesktopWidth(0),DesktopHeight(0),0,2)
SetWindowTitle(0, "........Tubes .. ")
MP_Viewport(0,0,DesktopWidth(0),DesktopHeight(0)-30)
camera=MP_CreateCamera()
light=MP_CreateLight(2)
MP_LightSetColor (light, RGB(255,255,255))
camera = MP_CreateCamera()
MP_CameraSetRange(camera, 1, 2024)
MP_PositionEntity(camera, 0, 8, -10)
;MP_EntityLookAt(camera, 0, 0, 0)
Global Mesh
Quit.b = #False
;==============================================================
tex$ = #PB_Compiler_Home + "Examples/3D/Data/Textures/" + "ground_diffuse.png"
Global Texture = MP_LoadTexture(tex$)
MP_EntitySetTexture (Mesh, Texture )
MP_MaterialEmissiveColor (Texture,0,255,255,255)
MP_EntityLookAt(light,0,0,0)
plane2 = MP_CreatePlane(10, 10)
;MP_ScaleMesh(plane2,0.1,0.1,0.1)
MP_RotateEntity(plane2, 90, 0, 0)
tex$ = #PB_Compiler_Home + "Examples/3D/Data/Textures/" + "MRAMOR6X6.jpg"
Global Texture2 = MP_LoadTexture(tex$)
;MP_ResizeTexture(Texture2,400,400)
MP_EntitySetTexture (plane2, Texture2 )
MP_MaterialEmissiveColor (Texture2,0,255,255,255)
;doc: the tube extents from x,y,z to x2,y2,z2
;doc: TubeXYZ(#mesh, x,y,z, x2,y2,z2, RadiusS, RadiusE, TubeShape
DrawTube(1, 0,-2, 1, 4,-2, 0.1,1, 16) ; RadiusS: tube Start radius, RadiusE: tube end radius
DrawTube(5, 4,-2, 3, 0,3 , 0.2,0.2,8) ; TubeShape: 3 triangular, 4 square, etc, 16 almost circular
DrawTube(5, 4,-2, 0, 0,0 , 0.2,0.2,8)
;InitMouse()
Procedure.f MP_EntityDistance(c,o)
Protected vx.f=MP_EntityGetX(o)-MP_EntityGetX(c),vy.f=MP_EntityGetY(o)-MP_EntityGetY(c),vz.f=MP_EntityGetZ(o)-MP_EntityGetZ(c)
ProcedureReturn Sqr(vx*vx+vy*vy+vz*vz)
EndProcedure
Procedure Orbitar(c,dx.d,dy.d,dz.d,o,r.d)
;Funcion para orbitar una entidad '*c' alrededor de otra '*o' siendo 'dx' y 'dy' los incrementos de las coordenadas sobre la superficie de una esfera de orbitaci?n de radio 'r'. 'dz' es el incremento del radio 'r'.
;Function to make a 3D entity '*c' to orbitate around another 3D entity '*o' being 'dx' y 'dy' the increments of the coords over the orbitation sphere surface with radius 'r'. 'dz' is the increment of the radius 'r'.
MP_MoveEntity(c,dx,dy,0)
MP_PointEntity(c,o)
MP_MoveEntity(c,0,0,Sqr(dx*dx+dy*dy+r*r)-r+dz)
EndProcedure
m.f=MP_EntityDistance(camera,mesh)
Repeat
Event = WindowEvent()
;If ExamineMouse()
;MouseX.f = -MP_MouseDeltaX()/100
;MouseY.f = -MP_MouseDeltaY()/100
Orbitar(camera,-MP_MouseDeltaX()/20,MP_MouseDeltaY()/20,MP_MouseDeltaWheel()/3,mesh,m)
;MP_RotateEntity(camera, MouseY, MouseX, 0)
;MP_RotateEntity(camera, 0, 0, 0, 0)
;EndIf
If MP_KeyDown(#PB_Key_Left)
KeyX = -#CameraSpeed
ElseIf MP_KeyDown(#PB_Key_Right)
KeyX = #CameraSpeed
Else
KeyX = 0
MP_MoveEntity(camera, KeyX, 0, KeyY)
EndIf
If MP_KeyDown(#PB_Key_Down)
KeyY = -#CameraSpeed
ElseIf MP_KeyDown(#PB_Key_Up)
KeyY = #CameraSpeed
Else
KeyY = 0
MP_MoveEntity(camera, KeyX, 0, KeyY)
EndIf
If MP_KeyDown(#PB_Key_Escape)
Quit = #True
EndIf
MP_DrawText (1,1,"..... Tubes")
MP_DrawText (1,15,"..... Tubes")
x+1
MP_RenderWorld()
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
;end of frenet approx procedures
; main program
Procedure DrawTube (x.f, y.f,z.f, x2.f, y2.f,z2.f, RadiusS.f, RadiusE.f, TubeShape)
Static e
#Rings = 2 ;number of Rings over all the Line (always 2, start ring and end ring)
x.f+0.00001 : y.f+0.00001 : z.f+0.00001 ; 0.00001 : necessary if all x,t,z are zero
x2.f+0.00001 : y2.f+0.00001 : z2.f+0.00001 ; if x,y,z or x2,y2,z2 are zero !!!
Mesh = MP_CreateMesh()
MP_EntitySetTexture (Mesh, Texture )
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 ; 2 flat tube, 3 triangular tube, 4 rectangular, 8 almost cylindrical tube
;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 #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
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
MP_AddVertex (mesh, x, y,z,0,txu,txv)
txv = txv + 1/#Rings
Next
txv = 0
txu = txu + 1/bands
Next
v.l
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
EndProcedure