Hi falsam
this is a not complete answer, many issues remains.
it seems we should add
NormalizeMesh(tube)
BuildMeshTangents(tube)
before
FinishMesh(tube) and not after and the tubes will not disappears with shadow additive.
i think the vertices are connected clockwise on one of the triangles and it should be counter clockwise.
so we replace
MeshFace(v,v+1,v + bands+1)
MeshFace(v + bands+1,v + bands+2,v+1 )
with
MeshFace(v,v + bands+1, v+1)
MeshFace(v + bands+1, v + bands+2, v+1 )
i have done experiment on a simple construction labeling its vertices , i post it at the end just if needed
also we apply Samuel advice regarding
MeshVertexNormal(0, 1, 0) after
MeshVertexPosition(x, y, z)
the dilemma is that we need to give every tube the feature:
EntityRenderMode(tube, 0)
so we can't show the shadow of the tubes itself on the ground
note that line 16-18:
divisions = 10 ie the number of the tubes make the whole donut,
and
bands = 8 ie the shape of every tube, and here it is octagonal. try bands = 20 and divisions =20
i am not happy with the example, but you can use it as a dark environment like that in the legendary '
Another World' Dos game. i have added a yellow sphere in the place of the light just as a guide. the light here are inside the tubes
move the camera inside the tube with keys and mouse
i will post in a minutes an example about the shadow .
Code: Select all
Enumeration
#Window = 500
#ground
#Camera
#Light1
#Light2
#sphere
#plane
#RedMaterial
#YellowMaterial
EndEnumeration
#CameraSpeed = 4
#RADIUS = 20 ;tube thickness
Global bands = 8 ;number of points of every ring (circle)
#Rings = 2 ;number of Rings over all the tube Line (always 2, start ring and end ring)
Global divisions = 10
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)
Declare LineXYZ (Line3D, x.f, y.f, z.f, x2.f, y2.f, z2.f)
Declare tubesCircle()
Global.f x0, y0
;Global tubeee
x0 = 0: y0 = 0
Define.f KeyX, KeyY, MouseX, MouseY
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
Define.f KeyX, KeyY, MouseX, MouseY
Global tube
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(#PB_Compiler_Home+"Examples\3D\Data\GUI",#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Packs/desert.zip", #PB_3DArchive_Zip)
InitSprite()
InitKeyboard()
InitMouse()
ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)
If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "thick lines , 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)
Parse3DScripts()
OpenWindow3D(33,0,0,200,100,"Engine Stats")
TextGadget3D(33,2,0,70,30,"")
ShowGUI(255,0)
CreateCamera(#Camera, 0, 0, 100, 100)
MoveCamera(#Camera, 200, 300, 150, #PB_Absolute)
CameraLookAt(#Camera,0,0,0)
CameraBackColor(#Camera, RGB(200,255,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, "wood.jpg"))
DisableMaterialLighting(0, #True)
GetScriptMaterial(#RedMaterial, "Color/Red")
GetScriptMaterial(#YellowMaterial, "Color/Yellow")
SetMaterialColor(#YellowMaterial, #PB_Material_SelfIlluminationColor, RGB(255,255,0))
;CreateLight(#Light1, RGB(255, 255, 255), 0, 20, 20)
CreateLight(#Light1, RGB(255, 255, 255), 100, 0, -10)
;CreateLight(#Light2, RGB(255, 255, 255), 200, 100, 10)
AmbientColor(RGB(100, 100, 100))
CreateSphere(1222, 2); just a pointer to the light position
CreateEntity(1222, MeshID(1222), MaterialID(#YellowMaterial), 100, 0, -10)
EndIf
EndIf
CreateSphere(#sphere, 7)
CreateEntity(#sphere, MeshID(#sphere), MaterialID(#RedMaterial), 95, 14,0)
EntityPhysicBody(#sphere, #PB_Entity_SphereBody, 1,5,1)
WorldShadows(#PB_Shadow_Additive)
;WorldShadows(#PB_Shadow_Modulative)
CreateCube(#plane,1)
CreateEntity(#plane,MeshID(#plane),MaterialID(0), 0, -21, 0)
ScaleEntity(#plane, 300,1, 300)
wireFrame = 1
tubesCircle()
EntityPhysicBody(tube, #PB_Entity_StaticBody)
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
EndIf
RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
MoveCamera(#Camera, KeyX, 0, KeyY)
RenderWorld()
FlipBuffers()
SetGadgetText3D(33,"FPS: "+StrF(Engine3DStatus(#PB_Engine3D_Current),2))
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)
Dim vertx.vertex(10)
lineVec.vector3d
u.f: r.f
txu.f : txv.f
x1.f = x
y1.f = y
z1.f = z
;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
;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(0, 1, 0)
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 LineXYZ (Line3D, x.f, y.f,z.f, x2.f, y2.f,z2.f)
tube = Line3D
CreateMesh(tube , #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )
SetMeshMaterial(tube , MaterialID(2))
;; 0.00001 : necessary if all x,t,z are zero
DrawTube (x+0.00001, y+0.00001, z+0.00001, x2, y2, z2)
NormalizeMesh(tube)
BuildMeshTangents(tube)
FinishMesh(tube)
CreateEntity(tube,MeshID(tube),MaterialID(2))
EntityRenderMode(tube, 0)
EndProcedure
Procedure tubesCircle()
For i=1 To divisions
tubeee+1
X.f=tempX.f:Z.f=tempZ.f
X.f=X+#PI*2/divisions
Z.f=Z+#PI*2/divisions
XX.f=Cos(X)*100
ZZ.f=Sin(Z)*100
tempX.f=X: tempZ.f=Z
X.f=X+#PI*2/divisions
Z.f=Z+#PI*2/divisions
XX2.f=Cos(X)*100
ZZ2.f=Sin(Z)*100
LineXYZ(tubeee, xx,0,zz, xx2, 0, zz2)
Next
EndProcedure
the test i have made to see the connections of a simple construction, some numbers are over each other but we can guess it, i may have errors it is an horrible task to connect vertices correctly . here i have used this
LineXYZ(6, 0,1,-45, 0,7,-45, 15, 3, 3) here the red '3' determine it is a triangular tube:
LineXYZ(#mesh, x,y,z, x2,y2,z2, Radius.f, TubeShape, Material)
Code: Select all
#CameraSpeed = 1
#Rings = 2 ;number of Rings over all the Line (always 2, start ring and end ring)
#sphere = 17
#RedMaterial = 18
Global tube
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, Radius.f, TubeShape)
Declare LineXYZ (Line3D, x.f, y.f, z.f, x2.f, y2.f, z2.f, Radius.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
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)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/fonts", #PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite()
InitKeyboard()
InitMouse()
ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)
If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "thick lines , 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, -40, 40, 30, #PB_Absolute)
CameraLookAt(#Camera,1,10,-25)
CameraBackColor(#Camera, RGB(200,200,200))
CreateMaterial(0, LoadTexture(0, "white.jpg"))
DisableMaterialLighting(0, #True)
CreateMaterial(1, LoadTexture(1, "MRAMOR6X6.jpg"))
MaterialCullingMode(1, #PB_Material_NoCulling)
CreateMaterial(2, LoadTexture(2, "ground_diffuse.png"))
MaterialCullingMode(2, #PB_Material_NoCulling)
DisableMaterialLighting(2, #False)
CreateMaterial(3, LoadTexture(3, "wood.jpg"))
DisableMaterialLighting(3, #False)
MaterialCullingMode(3, #PB_Material_NoCulling)
MaterialShadingMode(3, #PB_Material_Wireframe)
GetScriptMaterial(#RedMaterial, "Color/Red")
CreateLight(#Light1, RGB(255, 255, 255), 0, 100, 20)
AmbientColor(RGB(100, 100, 100))
EndIf
EndIf
Global SphereMesh = CreateSphere(#PB_Any, 1)
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: 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: LineXYZ(#mesh, x,y,z, x2,y2,z2, Radius.f, TubeShape, Material)
LineXYZ(6, 0,1,-45, 0,7,-45, 15, 3, 3)
;MoveEntity(tube, 0,18,-90) ;then we move it to any place so when it is rotating it is rotating correctly around itself
WorldShadows(#PB_Shadow_Modulative)
WorldShadows(#PB_Shadow_Additive)
;MaterialShadingMode(3, #PB_Material_Solid)
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
EndIf
RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
MoveCamera(#Camera, KeyX, 0, KeyY)
;RotateEntity(tube, 0,1,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
Procedure DrawTube (x.f, y.f,z.f, x2.f, y2.f,z2.f, Radius.f, TubeShape)
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)
;Sphere = CreateEntity(#PB_Any, MeshID(SphereMesh), #PB_Material_None , x,y,z)
CreateText3D(txt, Str(txt))
Text3DColor(txt, RGBA(255, 0, 0, 255))
Text3DAlignment(txt, #PB_Text3D_HorizontallyCentered)
;AttachEntityObject(txt, "", Text3DID(txt))
xv=xv+x+0.1
MoveText3D(txt, x, y, z)
txt+1
txv = txv + 1/#Rings
Next
txv = 0
txu = txu + 1/bands
Next
v.l
Debug "the connections of the vertices"
For j = 0 To bands -1
MeshFace(v,v + bands+1, v+1)
MeshFace(v + bands+1, v + bands+2, v+1 )
Debug Str(v)+" "+Str(v + bands+1)+" "+Str(v+1)
Debug Str(v+bands+1)+" "+Str(v+bands+2)+" "+Str(v+1)
v + 1
Next
EndProcedure
Procedure LineXYZ (Line3D, x.f, y.f,z.f, x2.f, y2.f,z2.f, 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 !!!
tube = Line3D + 2000
CreateMesh(tube , #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )
;SetMeshMaterial(tube , MaterialID(Material))
;; 0.00001 : necessary if all x,t,z are zero
DrawTube (x+0.00001, y+0.00001, z+0.00001, x2, y2, z2, Radius, TubeShape)
NormalizeMesh(tube)
BuildMeshTangents(tube)
FinishMesh(tube)
;NormalizeMesh(tube)
;BuildMeshTangents(tube)
CreateEntity(tube,MeshID(tube),MaterialID(Material))
;AttachEntityObject(Line3D,"",EntityID(tube))
EndProcedure