Page 1 of 1

Small vector 3D engine example

Posted: Sun Oct 06, 2002 4:40 pm
by BackupUser
Restored from previous forum. Originally posted by fweil.

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.D3o file content

'
' 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

Posted: Sun Oct 06, 2002 4:54 pm
by BackupUser
Restored from previous forum. Originally posted by blueb.

Amazing work Francois! :)

I can see many possiblilites that I'd like to try.

This will give me a very good starting point.

Thanks,
--blueb

Posted: Sun Oct 06, 2002 5:43 pm
by BackupUser
Restored from previous forum. Originally posted by fweil.

I am trying some new objects now and trying to understand what could be an object generator, or an object editor to create compatible files with this first display program.

Really pleased that you find it useful right now.

KRgrds

Francois Weil
14, rue Douer
F64100 Bayonne

Posted: Sun Oct 06, 2002 6:43 pm
by BackupUser
Restored from previous forum. Originally posted by fred.

Nice code !

Fred - AlphaSND

Posted: Mon Oct 07, 2002 2:48 am
by BackupUser
Restored from previous forum. Originally posted by Hi-Toro.

Really cool -- it's nice to have a very simple 3D engine written in Basic to learn from :)


--
See ya,
James L Boyd.
http://www.hi-toro.com/
--

Posted: Mon Oct 07, 2002 5:56 am
by BackupUser
Restored from previous forum. Originally posted by fweil.

Have a look at http://www.nasca.fr/software/3DoFiles/

There are some goodies ...

Francois Weil
14, rue Douer
F64100 Bayonne