GetMeshData(#Mesh,0, MeshData(), #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_Tangent , 0, MeshVertexCount(#Mesh)-1)
which direct the results to the structured array MeshData.
also we can use :
NormalizeMesh(#Mesh)
BuildMeshTangents(#Mesh)
to create normals and tangents info for the mesh.
to plot a normal line from a vertex on the object surface we use:
plot line [from vertex0 to (vertex0 + its normal)]
imagine the normal as a shift applied to vertex0 to get a new position, then we draw a line from vertex0 to the new virtual position in which vertex0 is looking at or directed its eye to. (the line should be perpendicular to the surface) . we can multiply the normal by a number so to make the line bigger or smaller as needed.
the PB sphere have intrinsic normal and tangents so we don't need
NormalizeMesh(#Mesh)
BuildMeshTangents(#Mesh)
but if we apply NormalizeMesh(#Mesh) (uncomment line 66) we see some lines are going inside in addition to the outside, is this a bug in NormalizeMesh(#Mesh): visit the sphere interior to see these internal lines along the dark vertical line of wood texture .
but this "may be bug" does not happened with "sphere.mesh" i have found in ogre package (OgreSDK_vc9_v1-7-4), that sphere is very strange, it seems designed manually, and does not have tangents and can't be created with BuildMeshTangents(#Mesh). just enjoy that strange sphere and try to texture it.
if you want download this "sphere.mesh" from here: http://www.2shared.com/file/hJwV3Con/sphere.html click the smaller download button and not the big one.

i have used this code also with a terrain mesh generated by Basic Terrain Generator by Samuel here http://forum.purebasic.com/english/view ... 36&t=59954 and gives good results
Code: Select all
#CameraSpeed = 1
#Mesh = 50
#Normals = 55
#Tangents = 60
Global Dim MeshData.PB_MeshVertex(0)
Global xx.f, yy.f
Global ArrSize
Define.f KeyX, KeyY, MouseX, MouseY
Enumeration
#Window
#Plane
#Camera
#Light1
#Light2
#cyl
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)
;Add3DArchive("C:\OgreSDK\OgreSDK_vc9_v1-7-4\media\models",#PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite()
InitKeyboard()
InitMouse()
ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)
Total=50
If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "spikey , W toggle wireFrame ... arrow keys and mouse to move and rotate")
If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
CreateCamera(#Camera, 0, 0, 100, 100)
MoveCamera(#Camera, 0, 10, 40, #PB_Absolute)
CameraLookAt(#Camera,0,0,0)
CameraBackColor(#Camera, RGB(250,250,250))
CreateLight(#Light1, RGB(0, 0, 0), -20, 40, 20)
SetLightColor(#Light1, #PB_Light_DiffuseColor, RGB(255,255,255))
AmbientColor(RGB(255, 255, 255))
CreateMaterial(5, LoadTexture(5, "wood.jpg"))
MaterialCullingMode(5, #PB_Material_NoCulling)
;MaterialShadingMode(5, #PB_Material_Wireframe)
CreateSphere(#Mesh,10,16,16)
;LoadMesh(#Mesh, "terrain0.mesh")
;LoadMesh(#Mesh, "sphere.mesh")
CreateEntity(#Mesh,MeshID(#Mesh), MaterialID(5),0,0,0 )
;NormalizeMesh(#Mesh)
;BuildMeshTangents(#Mesh)
GetMeshData(#Mesh,0, MeshData(), #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_Tangent , 0, MeshVertexCount(#Mesh)-1)
ArrSize = ArraySize(MeshData())
;Debug ArrSize
;creating Normals and Tangents lines
CreateMesh(#Normals, #PB_Mesh_LineList , #PB_Mesh_Dynamic)
For c=0 To ArrSize
; the vertex on the object surface
x.f = MeshData(c)\x
y.f = MeshData(c)\y
z.f = MeshData(c)\z
nx.f = MeshData(c)\NormalX
ny.f = MeshData(c)\NormalY
nz.f = MeshData(c)\NormalZ
tx.f = MeshData(c)\TangentX
ty.f = MeshData(c)\TangentY
tz.f = MeshData(c)\TangentZ
; for normals; find the next vertex to draw line with vertex on the object surface
x2.f = x+nx*3 : y2.f = y+ny*3: z2.f = z+nz*3
; for tangents; find the next vertex to draw line with vertex on the object surface
x3.f = x+tx*1 : y3.f = y+ty*1: z3.f = z+tz*1
MeshVertexPosition(x, y, z) ;vertex on the object surface
MeshVertexColor(RGB(255,0,0))
MeshVertexPosition(x2, y2, z2) ; for normals
MeshVertexColor(RGB(255,0,0))
MeshVertexPosition(x, y, z) ;vertex on the object surface
MeshVertexColor(RGB(0,255,0))
MeshVertexPosition(x3, y3, z3) ; for tangents
MeshVertexColor(RGB(0,255,0))
Next c
FinishMesh(#True)
CreateMaterial(0, LoadTexture(0, "White.jpg"))
DisableMaterialLighting(0, #True)
SetMeshMaterial(#Normals, MaterialID(0))
CreateEntity(#Normals,MeshID(#Normals),MaterialID(0))
AttachEntityObject(#mesh,"",EntityID(#Normals))
EndIf
EndIf
;HideEntity(#Mesh,#True)
RotateEntity(#mesh, 0,20,0)
wireFrame = 1
Repeat
If ExamineMouse()
MouseX = -MouseDeltaX()/20
MouseY = -MouseDeltaY()/20
EndIf
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
KeyX = -0.2
ElseIf KeyboardPushed(#PB_Key_Right)
KeyX = 0.2
Else
KeyX = 0
EndIf
If KeyboardPushed(#PB_Key_Up)
KeyY = -0.2
ElseIf KeyboardPushed(#PB_Key_Down)
KeyY = 0.2
Else
KeyY = 0
EndIf
If KeyboardReleased(#PB_Key_W)
If wireFrame
MaterialShadingMode(5, #PB_Material_Wireframe)
wireFrame ! 1
Else
MaterialShadingMode(5, #PB_Material_Solid)
wireFrame ! 1
EndIf
EndIf
EndIf
RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
MoveCamera(#Camera, KeyX, 0, KeyY)
RotateEntity(#mesh, 0.0,0.1,0.0,#PB_Relative)
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
Else
MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
Endthe same above code but added tubes over the Normals lines, the function TubeXYZ :
Code: Select all
TubeXYZ (tube, x.f, y.f,z.f, x2.f, y2.f,z2.f, Radius.f, TubeShape, Material)http://www.dbfinteractive.com/forum/ind ... pic=5993.0
http://www.blackpawn.com/texts/pqtorus/
now i forgot the interior of the function completely (100%), but i use it comfortably, (should be added to PB native functions or something like it, your kids will enjoy designing buildings using tubes in different shapes and orientation.

still there is a problem: to align a cube correctly with the normal line, i see "FetchOrientation.pb" in the official examples ...
Code: Select all
#CameraSpeed = 1
#Mesh = 50
#Normals = 55
#Tangents = 60
Declare TubeXYZ (Line3D, x.f, y.f, z.f, x2.f, y2.f, z2.f, Radius.f, TubeShape, Material)
Global Dim MeshData.PB_MeshVertex(0)
Structure vector3d
x.f
y.f
z.f
EndStructure
Structure vertex
x.f
y.f
z.f
EndStructure
Dim vertx.vertex(32)
Define.f KeyX, KeyY, MouseX, MouseY
Enumeration
#Window
#Plane
#Camera
#Light1
#Light2
#cyl
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)
;Add3DArchive("C:\OgreSDK\OgreSDK_vc9_v1-7-4\media\models",#PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite()
InitKeyboard()
InitMouse()
ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)
Total=50
If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "Normals & Tangents, ....W toggle wire/solid Frame ... arrow keys/ mouse to move/ rotate Camera")
If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
CreateCamera(#Camera, 0, 0, 100, 100)
MoveCamera(#Camera, 0, 20, 30, #PB_Absolute)
CameraLookAt(#Camera,0,0,0)
CameraBackColor(#Camera, RGB(250,250,250))
CreateLight(#Light1, RGB(0, 0, 0), -20, 40, 20)
SetLightColor(#Light1, #PB_Light_DiffuseColor, RGB(255,255,255))
AmbientColor(RGB(255, 255, 255))
CreateMaterial(2, LoadTexture(2, "clouds.jpg"))
MaterialCullingMode(2, #PB_Material_NoCulling)
CreateMaterial(5, LoadTexture(5, "wood.jpg"))
MaterialCullingMode(5, #PB_Material_NoCulling)
;MaterialShadingMode(5, #PB_Material_Wireframe)
CreateSphere(#Mesh,10,16,16)
;LoadMesh(#Mesh, "terrain0.mesh")
;LoadMesh(#Mesh, "sphere.mesh")
;LoadMesh(#Mesh, "terr.mesh")
CreateEntity(#Mesh,MeshID(#Mesh), MaterialID(5),0,0,0 )
;NormalizeMesh(#Mesh)
;BuildMeshTangents(#Mesh)
GetMeshData(#Mesh,0, MeshData(), #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_Tangent , 0, MeshVertexCount(#Mesh)-1)
ArrSize = ArraySize(MeshData())
;Debug ArrSize
;creating Normals and tangents lines
CreateMesh(#Normals, #PB_Mesh_LineList , #PB_Mesh_Dynamic)
For c=0 To ArrSize
x.f = MeshData(c)\x
y.f = MeshData(c)\y
z.f = MeshData(c)\z
nx.f = MeshData(c)\NormalX
ny.f = MeshData(c)\NormalY
nz.f = MeshData(c)\NormalZ
tx.f = MeshData(c)\TangentX
ty.f = MeshData(c)\TangentY
tz.f = MeshData(c)\TangentZ
x2.f = x+nx*3 : y2.f = y+ny*3: z2.f = z+nz*3 ; for normals
x3.f = x+tx*1 : y3.f = y+ty*1: z3.f = z+tz*1 ; for tangents
MeshVertexPosition(x, y, z) ; vertex on the surface
MeshVertexColor(RGB(255,0,0))
MeshVertexPosition(x2, y2, z2) ; for normals, find the next vertex to draw line with vertex on the object surface
MeshVertexColor(RGB(255,0,0))
MeshVertexPosition(x, y, z) ; vertex on the surface
MeshVertexColor(RGB(0,255,0))
MeshVertexPosition(x3, y3, z3) ; for tangents
MeshVertexColor(RGB(0,255,0))
Next c
FinishMesh(#True)
CreateMaterial(0, LoadTexture(0, "White.jpg"))
DisableMaterialLighting(0, #True)
SetMeshMaterial(#Normals, MaterialID(0))
CreateEntity(#Normals,MeshID(#Normals),MaterialID(0))
AttachEntityObject(#mesh,"",EntityID(#Normals))
;;ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
; again but for the purpose to draw tube between vertex 1 and vertex 2
For c=0 To ArrSize
x.f = MeshData(c)\x
y.f = MeshData(c)\y
z.f = MeshData(c)\z
nx.f = MeshData(c)\NormalX
ny.f = MeshData(c)\NormalY
nz.f = MeshData(c)\NormalZ
x2 = x+nx*3 : y2 = y+ny*3: z2 = z+nz*3
TubeXYZ(c+100, x,y,z, x2,y2,z2, 0.2, 8, 2)
AttachEntityObject(#mesh,"",EntityID(c+100))
Next
;;oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
EndIf
EndIf
;HideEntity(#Mesh,#True)
RotateEntity(#mesh, 0,20,0)
wireFrame = 1
Repeat
If ExamineMouse()
MouseX = -MouseDeltaX()/20
MouseY = -MouseDeltaY()/20
EndIf
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
KeyX = -0.2
ElseIf KeyboardPushed(#PB_Key_Right)
KeyX = 0.2
Else
KeyX = 0
EndIf
If KeyboardPushed(#PB_Key_Up)
KeyY = -0.2
ElseIf KeyboardPushed(#PB_Key_Down)
KeyY = 0.2
Else
KeyY = 0
EndIf
If KeyboardReleased(#PB_Key_W)
If wireFrame
MaterialShadingMode(5, #PB_Material_Wireframe)
wireFrame ! 1
Else
MaterialShadingMode(5, #PB_Material_Solid)
wireFrame ! 1
EndIf
EndIf
EndIf
RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
MoveCamera(#Camera, KeyX, 0, KeyY)
RotateEntity(#mesh, 0.0,0.1,0.0,#PB_Relative)
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
Else
MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End
;oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
;oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
;oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
;oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
;the beginning of the Tubes construction code, from here to the end of this page
#Rings = 2 ;number of Rings over all the Line (always 2, start ring and end ring)
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 TubeXYZ (tube, x.f, y.f,z.f, x2.f, y2.f,z2.f, Radius.f, TubeShape, Material)
;TubeXYZ(#mesh, x,y,z, x2,y2,z2, Radius.f, TubeShape, Material)
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(tube , #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )
;; 0.00001 : necessary if all x,t,z are zero
Dim vertx.vertex(10)
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
;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(1, 1, 1)
xv=xv+x+0.1
txt+1
txv = txv + 1/#Rings
Next
txv = 0
txu = txu + 1/bands
Next
v.l
For j = 0 To bands -1
MeshFace(v,v + bands+1, v+1)
MeshFace(v + bands+1, v + bands+2, v+1 )
v + 1
Next
NormalizeMesh(tube)
BuildMeshTangents(tube)
FinishMesh(tube)
;NormalizeMesh(tube)
;BuildMeshTangents(tube)
CreateEntity(tube,MeshID(tube),MaterialID(Material))
EndProcedure



