I post here a sample of 3D screen vector drawing we discussed and made on the french forum with cederavic.
There is nothing highly clever in it but it is interesting to come back on some aspects of drawing basics, like 3D rotation, and also to some Purebasic subtelties (see the accelerator code when maintaining a key pressed).
One good feature here is the possibility to load a descriptor file of an object to draw. The descriptor file parser is simple but works fine and allows an easy object coding.
It may remain some small things to tune in the code. Like the perspective calculation which I find poor and inacurate ATM.
After the source code, I place also to descriptor files examples.
I don't know if any of you have an idea on how to code an object generator ? It would be an idea.
Last thing, the program has low comments, what is rather unusual for me. Depending on interest I will measure upon answers, I will enhance it or not.
KRgrds
Code: Select all
#MaxPoints = 1000
#XAxis = 1
#YAXis = 2
#ZAxis = 3
CounterKR.l
CounterKL.l
CounterKU.l
CounterKD.l
CounterKA.l
CounterKS.l
Smooth.l
WindowXSize.l
WindowYSize.l
XCenter.l
YCenter.l
Distance.l
NPoints.l
NVectors.l
Dim MyVectors.l(#MaxPoints, 2)
Dim My3DPoints.f(#MaxPoints, 3)
Dim My2DPoints.l(#MaxPoints, 2)
Global CounterKR, CounterKL, CounterKU, CounterKD, CounterKA, CounterKS, Smooth
Global WindowXSize, WindowYSize, XCenter, YCenter, Distance, NPoints, NVectors
Global My2DPoints, My3DPoints, MyVectors
; PPlot a point using color if the point's coordinates are within the window
Procedure MyPlot(x.l, y.l, color.l)
If x >= 0 And x = 0 And y 0
My2DPoints(i, #XAxis) = (My3DPoints(i, #XAxis) * Distance) / MyDiv + XCenter
My2DPoints(i, #YAxis) = (My3DPoints(i, #YAxis) * Distance) / MyDiv + YCenter
EndIf
Next
; Start drawing vectors and vertex
StartDrawing(ScreenOutput())
For i = 0 To NVectors
LineXY(My2DPoints(MyVectors(i, 1), #XAxis), WindowYSize - My2DPoints(MyVectors(i, 1), #YAxis), My2DPoints(MyVectors(i, 2), #XAxis), WindowYSize - My2DPoints(MyVectors(i, 2), #YAxis), #blue)
Next
For i = 0 To NPoints
MyPlot(My2DPoints(i, #XAxis), My2DPoints(i, #YAxis), #red)
Next
; End of drawing
StopDrawing()
EndProcedure
; Move the object
Procedure XYZMove(n.l, axis.l)
For i = 0 To NPoints
My3DPoints(i, axis) = My3DPoints(i, axis) + n
Next
EndProcedure
Procedure MoveIt(n.l)
If (n & 1)
CounterKR + (n & 1)
XYZMove(CounterKR >> Smooth, 1)
ElseIf (n & 2)
CounterKL - (n & 2) >> 1
XYZMove(CounterKL >> Smooth, 1)
ElseIf (n & 4)
CounterKU + (n & 4) >> 2
XYZMove(CounterKU >> Smooth, 2)
ElseIf (n & 8)
CounterKD - (n & 8) >> 3
XYZMove(CounterKD >> Smooth, 2)
ElseIf(n & 16)
CounterKA - (n & 16) >> 4
XYZMove(CounterKA >> Smooth, 3)
ElseIf(n & 32)
CounterKS + (n & 32) >> 5
XYZMove(CounterKS >> Smooth, 3)
EndIf
EndProcedure
;
; Main starts here
;
Quit.l
AngleStep.f
FileName.s
CurrentDirectory.s
CurrentDirectory = Space(255)
GetCurrentDirectory_(255, @CurrentDirectory)
; Libraries initialization
InitSprite()
InitKeyboard()
; Variables initialization
Distance = 700
Quit = #FALSE
Smooth = 3
AngleStep = 0.0174532
; Arrays initialization using a descriptor file
FileName = OpenFileRequester("Select a file", CurrentDirectory + "\*.3Do", "3D Object|*.3Do|All files|*.*", 0)
If FileName ""
NPoints = 0
NVectors = 0
If ReadFile(0, FileName)
Repeat
;
; Parse descriptor file
; replace tabs with spaces, remove leading and trailing spaces, split numbers in arrays
;
a$ = LTrim(RTrim(ReplaceString(LCase(ReadString()), Chr(9), " ")))
If Left(a$, 1) = "'" Or Len(a$) = 0
ElseIf Left(a$, 5) = "point" ; read a 3 numbers space separated list
b$ = Mid(a$, FindString(a$, " ", 1) + 1, Len(a$) - FindString(a$, " ", 1) - 1 + 1)
My3DPoints(NPoints, #XAxis) = Val(Mid(b$, 1, FindString(b$, " ", 1) - 1))
b$ = Mid(b$, FindString(b$, " ", 1) + 1, Len(b$) - FindString(b$, " ", 1) - 1 + 1)
My3DPoints(NPoints, #YAxis) = Val(Mid(b$, 1, FindString(b$, " ", 1) - 1))
My3DPoints(NPoints, #ZAxis) = Val(Mid(b$, FindString(b$, " ", 1) + 1, Len(b$) - FindString(b$, " ", 1) - 1 + 1))
NPoints + 1
ElseIf Left(a$, 6) = "vector" ; read a 2 numbers space separated list
b$ = Mid(a$, FindString(a$, " ", 1) + 1, Len(a$) - FindString(a$, " ", 1) - 1 + 1)
MyVectors(NVectors, 1) = Val(Mid(b$, 1, FindString(b$, " ", 1) - 1))
MyVectors(NVectors, 2) = Val(Mid(b$, FindString(b$, " ", 1) + 1, Len(b$) - FindString(b$, " ", 1) - 1 + 1))
NVectors + 1
EndIf
Until Eof(0)
CloseFile(0)
EndIf
; Screen mode start
If OpenScreen(1280, 1024, 16, "PB M3D")
WindowXSize = 1280
WindowYSize = 1024
ElseIf OpenScreen(1024, 768, 16, "PB M3D")
WindowXSize = 1024
WindowYSize = 768
ElseIf OpenScreen(800, 600, 16, "PB M3D")
WindowXSize = 800
WindowYSize = 600
ElseIf OpenScreen(640, 480, 16, "PB M3D")
WindowXSize = 640
WindowYSize = 480
Else
Quit = #TRUE
EndIf
XCenter = WindowXSize / 2
YCenter = WindowYSize / 2
; Main loop
While Quit #TRUE
; Keyboard exam
ExamineKeyboard()
; Object move
If KeyboardPushed(#PB_Key_Right)
MoveIt(1)
EndIf
If KeyboardPushed(#PB_Key_Left)
MoveIt(2)
EndIf
If KeyboardPushed(#PB_Key_Up)
MoveIt(4)
EndIf
If KeyboardPushed(#PB_Key_Down)
MoveIt(8)
EndIf
If KeyboardPushed(#PB_Key_Add)
MoveIt(16)
EndIf
If KeyboardPushed(#PB_Key_Subtract)
MoveIt(32)
EndIf
If KeyboardPushed(#PB_Key_F1)
My3DRotate(AngleStep, 0.0, 0.0)
EndIf
If KeyboardPushed(#PB_Key_F2)
My3DRotate(-AngleStep, 0.0, 0.0)
EndIf
If KeyboardPushed(#PB_Key_F5)
My3DRotate(0.0, AngleStep, 0.0)
EndIf
If KeyboardPushed(#PB_Key_F6)
My3DRotate(0.0, -AngleStep, 0.0)
EndIf
If KeyboardPushed(#PB_Key_F9)
My3DRotate(0.0, 0.0, AngleStep)
EndIf
If KeyboardPushed(#PB_Key_F10)
My3DRotate(0.0, 0.0, -AngleStep)
EndIf
; Object display
DisplayObject()
; Program exit
If KeyboardPushed(#PB_Key_Escape)
Quit = #TRUE
EndIf
; Flip buffers
FlipBuffers()
ClearScreen(0, 0, 0)
; Main loop end
Wend
; Program end
EndIf
End
'
' Cube
'
Point(0) -100 -100 -100
Point(1) -100 -100 100
Point(2) -100 100 -100
Point(3) -100 100 100
Point(4) 100 -100 -100
Point(5) 100 -100 100
Point(6) 100 100 -100
Point(7) 100 100 100
Vector(1) 0 4
Vector(2) 4 6
Vector(3) 6 2
Vector(4) 2 0
Vector(5) 1 5
Vector(6) 5 7
Vector(7) 7 3
Vector(8) 3 1
Vector(9) 0 1
Vector(10) 2 3
Vector(11) 4 5
Vector(12) 6 7
House.3Do file content
'
' Simple house drawn with a cube covered by a pyramid
'
Point(0) -100 0 -100
Point(1) 100 0 -100
Point(2) 100 0 100
Point(3) -100 0 100
Point(4) -100 100 -100
Point(5) 100 100 -100
Point(6) 100 100 100
Point(7) -100 100 100
Point(8) 0 200 0
Vector(0) 0 1
Vector(1) 1 2
Vector(2) 2 3
Vector(3) 3 0
Vector(4) 4 5
Vector(5) 5 6
Vector(6) 6 7
Vector(7) 7 4
Vector(8) 4 0
Vector(9) 5 1
Vector(10) 6 2
Vector(11) 7 3
Vector(12) 4 8
Vector(13) 5 8
Vector(14) 6 8
Vector(15) 7 8
Francois Weil
14, rue Douer
F64100 Bayonne