PDA

View Full Version : Möbius strip



primo
14-08-2016, 10:50
Mobius strip is a paper strip in which A connect to D and B connect to C.
A------------------------C
........................
B------------------------D

it is a strange entity , we can't determine its up or down so it is causing confusion, look its lighting on the following demos which are the same demos but done in 2 ways
the first demo depends on lesson 4
http://psch.thinbasic.com/old/tbgl_lesson4.html

Uses "TBGL"
Uses "UI"
Uses "math"

DIM hWnd as dword
Dim x, y, z, u, v As Single
Dim wireframe As Long

' We will initialize OpenGL and internal buffers
' Function also returns window handle
hWnd = TBGL_CreateWindowEx("Mobius Strip - press 'W' for wire/solid frame...... press ESC to quit", 640, 480, 32, %TBGL_WS_WINDOWED )

tbgl_ShowWindow ' This will display the window on the screen
TBGL_BackColor 255,255,255
TBGL_UseLighting(%TRUE)
TBGL_UseLightSource(%GL_LIGHT0, %TRUE)

TBGL_GetAsyncKeyState(-1) ' Reset status of the all keys to prevent immediate quit
'TBGL_PolygonLook %GL_LINE
while TBGL_IsWindow(hWnd) ' While window exists, we will draw and check for ESCAPE
If TBGL_GetWindowKeyOnce( hWnd, %VK_W) Then 'display wireFrame or solid frame
If wireframe = 0 Then
TBGL_PolygonLook %GL_LINE
wireframe = 1
Else
TBGL_PolygonLook %GL_FILL
wireframe = 0
End If
End If

tbgl_ClearFrame ' This clears the frame and prepares it for drawing

TBGL_Camera 0,2,4,0,0,0 ' We will look from point 0,0,10 to 0,0,0 ( origin of coordinates )

TBGL_Color 0, 255, 0
TBGL_PushMatrix
TBGL_Rotate 90, 1, 0, 0
TBGL_Rotate GetTickCount/50, 0, 0, 1
DrawQuads
tbgl_PopMatrix


tbgl_DrawFrame ' This will display the scene

' When ESCAPE is pressed, we will leave the main loop
IF TBGL_GetWindowKeyState( hWnd, %VK_ESCAPE ) THEN EXIT while

Wend

tbgl_DestroyWindow ' This will destroy the window

Sub DrawQuads( )
u=0
TBGL_BeginPoly %GL_QUAD_STRIP

While u <= 2*Pi
v = -0.5
While v<= 0.5
x = Cos(u) * ( 1 + (v/2 * Cos(u/2)) )
y = Sin(u) * ( 1 + (v/2 * Cos(u/2)) )
z = v/2 * Sin(u/2)
TBGL_Vertex x,y,z
v+1
Wend
v = -0.5
u + 0.1
Wend
'connect the last 2 points to the first 2 points in reverse
v = 0.5 :u=0
While v>= -0.5
x = Cos(u) * ( 1 + (v/2 * Cos(u/2)) )
y = Sin(u) * ( 1 + (v/2 * Cos(u/2)) )
z = v/2 * Sin(u/2)
TBGL_Vertex x,y,z
v-1
Wend
TBGL_EndPoly

end sub

the second demo is using the GBuffer

Uses "TBGL"
Uses "math"

Function TBMain()
Local hWnd As DWord
Local i,wireframe As Long
Local FrameRate As Double
' -- Create and show window
hWnd = TBGL_CreateWindowEx("Mobius strip using GBuffers - press 'W' for wire/solid Frame,...press ESC to quit", 600, 600, 32, %TBGL_WS_WINDOWED Or %TBGL_WS_CLOSEBOX)
TBGL_ShowWindow
TBGL_BackColor 255,255,255
'TBGL_PolygonLook %GL_LINE
' -- Create 3D points buffer
Dim gbQuad As DWord = TBGL_GBufferCreate(%TBGL_QUADSTRIP, %TBGL_3D)
Global Nb As DWord = 128
' -- Define data for it
Global VertexA(Nb) As TBGL_TVECTOR3F
Global ColorA(Nb) As TBGL_TRGB
Global NormalA(Nb) As TBGL_TVECTOR3F

FillArrays ' call the sub to fill VertexA , ColorA arrays
For i = 1 To Nb
ColorA(i).r = Rnd(128, 255)'0
ColorA(i).g = Rnd(128, 255)'255
ColorA(i).b = Rnd(128, 255)'0
Next

For i = 1 To Nb
NormalA(i).x = 0
NormalA(i).y = 1
NormalA(i).z = 0
Next

' -- Create buffer dynamically linked to the arrays above
TBGL_GBufferDefineFromArray(gbQuad, %TBGL_DYNAMIC, CountOf(VertexA), VertexA(1), ColorA(1), NormalA(1))
TBGL_UseLighting(%TRUE)
TBGL_UseLightSource(%GL_LIGHT0, %TRUE)

' -- Resets status of all keys
TBGL_ResetKeyState()

' -- Main loop
While TBGL_IsWindow(hWnd)
If TBGL_GetWindowKeyOnce( hWnd, %VK_W) Then
If wireframe = 0 Then
TBGL_PolygonLook %GL_LINE
wireframe = 1
Else
TBGL_PolygonLook %GL_FILL
wireframe = 0
End If
End If
'init
FrameRate = TBGL_GetFrameRate
TBGL_ClearFrame
TBGL_Camera(0, 10, 20, 0, 0, 0)
TBGL_Rotate 90, 1, 0, 0
TBGL_Rotate GetTickCount/50, 0, 0, 1
' -- Render it
TBGL_GBufferRender(gbQuad)
TBGL_DrawFrame
' -- ESCAPE key to exit application
If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While
Wend

' -- Destroy window
TBGL_DestroyWindow
End Function

Sub FillArrays()

Dim x, y, z, u, v As Single
v = -0.5
Dim N As DWord = 1
While u <= 2*Pi
v = -0.5
While v<= 0.5
x = Cos(u) * ( 1 + (v/2 * Cos(u/2)) )
y = Sin(u) * ( 1 + (v/2 * Cos(u/2)) )
z = v/2 * Sin(u/2)

VertexA(N).x = x*6
VertexA(N).y = y*6
VertexA(N).z = z*6

v+1 : N + 1
Wend

v = -0.5
u + 0.1
Wend

VertexA(N).x = VertexA(2).x
VertexA(N).y = VertexA(2).y
VertexA(N).z = VertexA(2).z
N+1
VertexA(N).x = VertexA(1).x
VertexA(N).y = VertexA(1).y
VertexA(N).z = VertexA(1).z

End Sub



9621

Petr Schreiber
14-08-2016, 22:37
Very cool example! Would you like some help with calculating proper normals?


Petr

primo
15-08-2016, 08:58
Yes Petr of course i need help for better Normals and lighting for all parts of Mobius strip, i thought first it is not possible.
the lighting of this kind of shapes cause confusion, it is suitable as a question in computer Lab exam .
i have tried it again and the best result i can get is this (in the second demo)
For i = 1 To Nb
NormalA(i).x = Rnd(-1,1)
NormalA(i).y = Rnd(-1,1)
NormalA(i).z = Rnd(-1,1)
Next
at least the strip will not darken totaly for some moments while rotating

Petr Schreiber
17-08-2016, 23:35
The normal calculation should be deterministic, I will dive into it this weekend :)


Stay tuned,
Petr

Petr Schreiber
21-08-2016, 11:40
One of the possible approaches, based on: http://psch.thinbasic.com/old/tbgl_lesson6.html



Uses "TBGL", "math"

Function TBMain()
long i, wireframe
double FrameRate
' -- Create and show window
dword hWnd = TBGL_CreateWindowEx("Mobius strip using GBuffers - press 'W' for wire/solid Frame,...press ESC to quit", 600, 600, 32, %TBGL_WS_WINDOWED Or %TBGL_WS_CLOSEBOX)
TBGL_ShowWindow
TBGL_BackColor 255,255,255

' -- Create 3D points buffer
Dword gbQuad = TBGL_GBufferCreate(%TBGL_QUADSTRIP, %TBGL_3D)

single detail = 0.01
dword Nb = CalculateBufferSize(detail)
' -- Define data for it
dim VertexA(Nb) As TBGL_TVECTOR3F
dim ColorA(Nb) As TBGL_TRGB
dim NormalA(Nb) As TBGL_TVECTOR3F

BuildGeometry(vertexA, detail)
CalculateNormals(vertexA, normalA)
PaintGeometry(colorA)

' -- Create buffer dynamically linked to the arrays above
TBGL_GBufferDefineFromArray(gbQuad, %TBGL_DYNAMIC, CountOf(VertexA), VertexA(1), ColorA(1), NormalA(1))
TBGL_UseLighting(%TRUE)
TBGL_UseLightSource(%GL_LIGHT0, %TRUE)

' -- Resets status of all keys
TBGL_ResetKeyState()
single time
' -- Main loop
While TBGL_IsWindow(hWnd)
If TBGL_GetWindowKeyOnce( hWnd, %VK_W) Then
If wireframe = 0 Then
TBGL_PolygonLook %GL_LINE
wireframe = 1
Else
TBGL_PolygonLook %GL_FILL
wireframe = 0
End If
End If

FrameRate = TBGL_GetFrameRate
TBGL_ClearFrame
TBGL_Camera(0, 10, 20, 0, 0, 0)
TBGL_Rotate 90, 1, 0, 0
TBGL_Rotate time/50, 0, 0, 1
' -- Render it
TBGL_GBufferRender(gbQuad)
TBGL_DrawFrame

' -- ESCAPE key to exit application
If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While
time+= 1/FrameRate*1000
Wend

' -- Destroy window
TBGL_DestroyWindow
End Function


function CalculateBufferSize(detail as single) as long
single u, v

dword N = 1
While u <= 2 * Pi
v = -0.5
While v <= 0.5
v+1 : N + 1
Wend
u + detail
Wend
return n+1
end function


Sub BuildGeometry(byref vertexA() As tbgl_tVector3F, detail as single)

single x, y, z, u, v

dword N = 1
While u <= 2 * Pi
v = -0.5
While v <= 0.5
x = Cos(u) * ( 1 + (v/2 * Cos(u/2)) )
y = Sin(u) * ( 1 + (v/2 * Cos(u/2)) )
z = v/2 * Sin(u/2)

vertexA(N).x = x*6
vertexA(N).y = y*6
vertexA(N).z = z*6

v+1 : N + 1
Wend
u + detail
Wend

VertexA(N).x = VertexA(2).x
VertexA(N).y = VertexA(2).y
VertexA(N).z = VertexA(2).z
N+1
VertexA(N).x = VertexA(1).x
VertexA(N).y = VertexA(1).y
VertexA(N).z = VertexA(1).z
End Sub


sub CalculateNormals(byref vertexA() as tbgl_tVector3F, byref normalA() as tbgl_tVector3F)
single ux, uy, uz,
vx, vy, vz,
nx, ny, nz

long i, j
For i = 1 To countOf(NormalA)-3 step 4
ux = vertexA(i+1).x - vertexA(i).x
uy = vertexA(i+1).y - vertexA(i).y
uz = vertexA(i+1).z - vertexA(i).z


vx = vertexA(i+2).x - vertexA(i).x
vy = vertexA(i+2).y - vertexA(i).y
vz = vertexA(i+2).z - vertexA(i).z

nx = uy * vz - uz * vy
ny = -(ux * vz - uz * vx)
nz = ux * vy - uy * vx

for j = 0 to 3
NormalA(i+j).x = nx
NormalA(i+j).y = ny
NormalA(i+j).z = nz
next
Next

end sub


sub PaintGeometry(byref colorA() as tbgl_tRGB)
long i
For i = 1 To countOf(ColorA)
ColorA(i).r = 255
ColorA(i).g = 128
ColorA(i).b = 64
Next
end sub


Petr

primo
21-08-2016, 14:27
Thanks Petr for this impressive example, also the lesson 6 is very useful.
i though first that you will use a continuous calculations of Normals while the strip rotating but you have used a fixed values and it works.
a very little talk in the web about the normals of not orientable objects, so this adds more to the available literature .