March 05, 2021, 07:22:52 AM

Author Topic: [bb] 3D Engine by jfk EO-11110 [ 1+ years ago ]  (Read 489 times)

Offline BlitzBot

[bb] 3D Engine by jfk EO-11110 [ 1+ years ago ]
« on: June 29, 2017, 12:28:39 AM »
Title : 3D Engine
Author : jfk EO-11110
Posted : 1+ years ago

Description : Simple 3D engine with linear texturemapping (for Blitz 2D)

Code :
Code: BlitzBasic
  1. ; Demo: Framework for a simplyfied 3D Engine featuring linear Texturemapping.
  2. ; Minor bugs. Supports Quads only. Someone should add Perspective Correction.
  3. ; Z-order by Quads and not by Pixel. Goodie: Renderer is using only Integers!
  4. ; No "hidden Quads removal" Function implemented yet - depends heavily on usage...
  5. ; Send obscene amounts of cash to howaboutpeace@utopia.gov j/k. Enjoy!
  6. ; Credits go to Toshi - thx for his Qbasic Texture Mapper (I removed all Floats) and
  7. ; to ParanoidPete and to some other PPL who are writing 3D-tutorials all the time.
  8.  
  9. ; PS: Funny: I got "fps: INFINITY" in Fullscreen Mode :) ... Move the Mouse to Zoom in.
  10.  
  11.  
  12. Graphics 320,240,16,2
  13. SetBuffer BackBuffer()
  14.  
  15. ; -- init texturemapper
  16.  
  17. texturefile$="texture256.jpg"
  18. If FileType(texturefile$)=1 Then ; if it exists then load it...
  19.  txt=LoadImage(texturefile$); use any 256*256 pixel texture
  20. Else
  21.  txt=CreateImage(256,256)   ; else create one on the fly
  22.  SetBuffer ImageBuffer(txt)
  23.  For i=0 To 255
  24.   Color i,255-i,0
  25.   Line 255-i,0,255,i
  26.   Color 255,255-i,255-i
  27.   Line 0,255-i,i,255
  28.  Next
  29.  SetBuffer BackBuffer()
  30. EndIf
  31. Global imgtxt=ImageBuffer(txt)
  32.  
  33. Dim Lefttable%(480, 2), Righttable%(480, 2)  ;Scan converter tables (make shure to reserve enough)
  34. Dim Polypoints%(3, 1) ; Array for polygon co-ords, 4 pairs(x,y) co -ords
  35. Global Miny%, Maxy%
  36. Global Pwidth%, Pheight%
  37.  
  38.  
  39. Pwidth = 255 Shl 16   ;original picture width in pixels -1 shl 16
  40. Pheight = 255 Shl 16 ;original picture height in pixels -1 shl 16
  41.  
  42. ; eo init texturemapper
  43.  
  44. Dim zbuffer(10000) ; maximum of 10k Quads (don't worry, would be too slow anyway :) )
  45.  
  46. ; Read in a mesh
  47. Restore building
  48. Read anz
  49. Dim xwww(anz),ywww(anz),zwww(anz)
  50. Dim xw(anz),yw(anz),zw(anz)
  51.  
  52. For i=0 To anz
  53.  Read xwww(i)
  54.  Read ywww(i)
  55.  Read zwww(i)
  56. Next
  57.  
  58. a=0
  59.  
  60. alpha=1
  61. beta=1
  62. gamma=1
  63.  
  64. zoom=-500 ; better alter "mausy#" to zoom in (see below)
  65.  
  66.  
  67. ; MMMMMMMMMMMMMMMMMMMMMMMMMmmmmmain
  68.  
  69. While KeyDown(1)=0
  70.  
  71.  Miny% = 32767  ;set initial smallest y co-ord of polygon After rotation
  72.  Maxy% = 0      ;set initial largest y co-ord of polygon After rotation
  73.  
  74.  ; calc frames per second
  75.  tt=MilliSecs()
  76.  fps#=1000.0/(tt-ttold)
  77.  fpsadd#=fpsadd#+fps#
  78.  fpscount=fpscount+1
  79.  If fpscount>19 Then
  80.   fpsreal#=fpsadd#/20
  81.   fpsadd#=0
  82.   fpscount=0
  83.  EndIf
  84.  ttold=tt
  85.  ; eo calc fps
  86.  
  87.  ; Cls
  88.  Color 0,0,0
  89.  Rect 0,0,320,240,1
  90.  
  91.  a=a+1.0 ; automatic rotation...
  92.  If a>359.9 Then a=0
  93.  alpha=a
  94.  beta=a
  95.  gamma=a+a Mod 360
  96.  
  97.  mausy#=0.1+(MouseY()/50.0)
  98.  ; the renderer is working with rotated Copies of the original Points to prevent degeneration by Floating Inaccuracy
  99.  For i=0 To anz
  100.   ; rotate pitch, roll and yaw
  101.   xl1#=zwww(i)*Sin(gamma)+xwww(i)*Cos(gamma)
  102.   yl1#=ywww(i)
  103.   zl1#=zwww(i)*Cos(gamma)-xwww(i)*Sin(gamma)
  104.  
  105.   xl2#=xl1
  106.   yl2#=yl1*Cos(beta)-zl1*Sin(beta)
  107.   zl2#=yl1*Sin(beta)+zl1*Cos(beta)
  108.  
  109.   xl3#=(yl2*Sin(alpha)+xl2*Cos(alpha))
  110.   yl3#=(yl2*Cos(alpha)-xl2*Sin(alpha))
  111.   zl3#=(zl2)
  112.  
  113.  
  114.   ; Projecting 3D to 2D
  115.   If yloc# - Zoom <> 0 Then yloc = Int(yl3 ) * 200 / (zl3 - Zoom)
  116.   If xloc# - Zoom <> 0 Then xloc = Int(xl3 ) * 200 / (zl3 - Zoom)
  117.  
  118.   xw(i)=((mausy#)*xloc) +160
  119.   yw(i)=((mausy#)*yloc) +120
  120.   zw(i)=(zl3+256) ; remember this for Z-sorting
  121.  Next
  122.  
  123.  ; z-sorting...
  124.  For i=0 To 10000
  125.   zbuffer(i)=-1 ; wipe out old zbuffer info (could be optimized)
  126.  Next
  127.  For i=0 To anz-3 Step 4
  128.   If zw(i)>=0 ; clip Quads behind Camera
  129.    zwmax=zw(i)
  130.    If zwmax<zw(i+1) Then zwmax=zw(i+1)
  131.    If zwmax<zw(i+2) Then zwmax=zw(i+2)
  132.    If zwmax<zw(i+3) Then zwmax=zw(i+3)
  133.    While zbuffer(zwmax)<>-1 And zwmax<10000 ; find next free slot
  134.     zwmax=zwmax+1
  135.    Wend
  136.    zbuffer(zwmax)=i
  137.   EndIf
  138.  Next
  139.  
  140.  LockBuffer ImageBuffer(txt)
  141.  LockBuffer BackBuffer()
  142.  
  143.  For i2=10000 To 0 Step -1 ; reading quads in z-order from far to near
  144.   i=zbuffer(i2)
  145.  
  146.   If i>-1 And i< anz-2 ; if it isn't -1 then it's a Quad Point 1 ID
  147.    ; Mapping...
  148.    GetPolygonPoints(i)
  149.    FindSmallLargeY()
  150.    ; Send polygon points To the scan converter
  151.    X1% = Polypoints%(0, 0)
  152.    Y1% = Polypoints%(0, 1)
  153.    X2% = Polypoints%(1, 0)
  154.    Y2% = Polypoints%(1, 1)
  155.    ScanConvert(X1%, Y1%, X2%, Y2%, 1)     ;scan top of picture
  156.    X1% = Polypoints%(1, 0)
  157.    Y1% = Polypoints%(1, 1)
  158.    X2% = Polypoints%(2, 0)
  159.    Y2% = Polypoints%(2, 1)
  160.    ScanConvert(X1%, Y1%, X2%, Y2%, 2)   ;scan Right of picture
  161.    X1% = Polypoints%(2, 0)
  162.    Y1% = Polypoints%(2, 1)
  163.    X2% = Polypoints%(3, 0)
  164.    Y2% = Polypoints%(3, 1)
  165.    ScanConvert(X1%, Y1%, X2%, Y2%, 3)  ;scan bottom of picture
  166.    X1% = Polypoints%(3, 0)
  167.    Y1% = Polypoints%(3, 1)
  168.    X2% = Polypoints%(0, 0)
  169.    Y2% = Polypoints%(0, 1)
  170.    ScanConvert(X1%, Y1%, X2%, Y2%, 4)    ;scan Left of picture
  171.  
  172.    TextureMap()
  173.    ; eo mapping
  174.   EndIf
  175.  Next
  176.  
  177.  UnlockBuffer BackBuffer()
  178.  UnlockBuffer ImageBuffer(txt)
  179.  
  180.  Color 255,255,255
  181.  Text 0,0,"fps "+fpsreal#
  182.  
  183.  Flip 0
  184. Wend
  185.  
  186. End
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193. ; --- texture mapping functions
  194.  
  195. Function GetPolygonPoints(ilocal%) ; initially read in a rectangle
  196.  For Count% = 0 To 3
  197.   Polypoints%(Count%, 0) = xw(ilocal%+Count%)
  198.   Polypoints%(Count%, 1) = yw(ilocal%+Count%)
  199.  Next
  200. End Function
  201.  
  202. Function FindSmallLargeY()
  203.  For Count% = 0 To 3
  204.   Ycoord% = Polypoints%(Count%, 1)
  205.  
  206.   If Ycoord% < Miny% Then       ; is this the New lowest y co-ord?
  207.    Miny% = Ycoord%             ; Yes...
  208.   End If
  209.  
  210.   If Ycoord% > Maxy% Then       ; is this the New highest y co-ord?
  211.    Maxy% = Ycoord%             ; Yes...
  212.   End If
  213.  Next
  214. End Function
  215.  
  216. Function ScanConvert (X1%, Y1%, X2%, Y2%, Pside)
  217.  
  218.  ; This procedure takes as defined by X1%,Y1%,x2,Y2%.
  219.  ; It also takes a var telling it which side of the picture we are
  220.  ; mapping.  The var are 1,2,3,4 for top,Right,bottom,Left. This routine decides
  221.  ; which ;side; of the polygon the Line is on, And Then calls the
  222.  ; appropriate routine.
  223.  
  224.  If Y2% < Y1% Then
  225.   temp%=X1% : X1%=X2% : X2%=temp%
  226.   temp%=Y1% : Y1%=Y2% : Y2%=temp%
  227.   Lineheight% = (Y2% - Y1%)
  228.   ScanLeftSide(X1%, X2%, Y1%, Lineheight%, Pside)
  229.  Else
  230.   Lineheight% = (Y2% - Y1%)
  231.   ScanRightSide(X1%, X2%, Y1%, Lineheight%, Pside)
  232.  End If
  233. End Function
  234.  
  235. Function ScanLeftSide (X1%, X2%, Ytop%, Lineheight%, Pside)
  236.  
  237.  ; This procedure calculates the x points for the Left side of the
  238.  ; polygon. It also calculates the x,y co-ords of the picture For the Left
  239.  ; side of the polygon.
  240.  
  241.  Lineheight% = Lineheight% + 1       ; prevent divide by zero
  242.  Xadd = (X2% - X1%) Shl 16
  243.  Xadd = Xadd / Lineheight%
  244.  
  245.  
  246.  If Pside = 1 Then
  247.   Px = Pwidth% - 1
  248.   Py = 0
  249.   Pxadd = -Pwidth%  / Lineheight%
  250.   Pyadd = 0
  251.  End If
  252.  If Pside = 2 Then
  253.   Px = Pwidth%
  254.   Py = Pheight%
  255.   Pxadd = 0
  256.   Pyadd = -Pheight%  / Lineheight%
  257.  End If
  258.  If Pside = 3 Then
  259.   Px = 0
  260.   Py = Pheight%
  261.   Pxadd = Pwidth%  / Lineheight%
  262.   Pyadd = 0
  263.  End If
  264.  If Pside = 4 Then
  265.   Px = 0
  266.   Py = 0
  267.   Pxadd = 0
  268.   Pyadd = Pheight%  / Lineheight%
  269.  End If
  270.  
  271.  x = X1% Shl 16
  272.  For y% = 0 To Lineheight%
  273.   Ytopy%=Ytop%+y%
  274.   If Ytopy%<0 Then Ytopy%=0
  275.   Lefttable(Ytopy%, 0) = x Sar 16    ;polygon x
  276.   Lefttable(Ytopy%, 1) = Px          ;picture x
  277.   Lefttable(Ytopy%, 2) = Py          ;picture y
  278.   x = x + Xadd                       ;Next polygon x
  279.   Px = Px + Pxadd                    ;Next picture x
  280.   Py = Py + Pyadd                    ;Next picture y
  281.  Next
  282. End Function
  283.  
  284. Function ScanRightSide (X1%, X2%, Ytop%, Lineheight%, Pside)
  285.  
  286.  ; This procedure calculates the x points For the Right side of the ;
  287.  ; polygon. It also calculates the x,y co-ords of the picture For the
  288.  ; Right side of the polygon.
  289.  
  290.  Lineheight% = Lineheight% + 1    ; No divide by zero
  291.  Xadd = (X2% - X1%) Shl 16
  292.  Xadd = Xadd / Lineheight%
  293.  
  294.  
  295.  If Pside = 1 Then
  296.   Px = 0
  297.   Py = 0
  298.   Pxadd = Pwidth% / Lineheight%
  299.   Pyadd = 0
  300.  End If
  301.  If Pside = 2 Then
  302.   Px = Pwidth%
  303.   Py = 0
  304.   Pxadd = 0
  305.   Pyadd = Pheight% / Lineheight%
  306.  End If
  307.  If Pside = 3 Then
  308.   Px = Pwidth%
  309.   Py = Pheight%
  310.   Pxadd = -Pwidth% / Lineheight%
  311.   Pyadd = 0
  312.  End If
  313.  If Pside = 4 Then
  314.   Px = 0
  315.   Py = Pheight%
  316.   Pxadd = 0
  317.   Pyadd = -Pheight% / Lineheight%
  318.  End If
  319.  
  320.  x = X1% Shl 16
  321.  For y% = 0 To Lineheight%
  322.   Ytopy%=Ytop%+y%
  323.   If Ytopy%<0 Then Ytopy%=0
  324.   Righttable(Ytopy%, 0) = x Sar 16   ;polygon x
  325.   Righttable(Ytopy%, 1) = Px         ;picture x
  326.   Righttable(Ytopy%, 2) = Py         ;picture y
  327.   x = x + Xadd                       ;Next polygon x
  328.   Px = Px + Pxadd                    ;Next picture x
  329.   Py = Py + Pyadd                    ;Next picture y
  330.  Next
  331. End Function
  332.  
  333.  
  334.  
  335.  
  336.  
  337. Function TextureMap()
  338. ; This is the actual mapping routine. Only linerar mapping, no perspective correction :/
  339. ; It takes the co-ords that have been calculated by the scan converter
  340. ; And 'traces' across the original picture in between them looking at
  341. ; the pixel Color And Then plotting a pixel in that Color in the
  342. ; current position within the polygon.
  343.  
  344. ; If you were able to optimze this in speed or accuracy then please let us know.
  345.  
  346.  For y% = Miny% To Maxy%
  347.   If y>0 And y<=239 ; clipping y
  348.    Polyx1% = Lefttable((y%), 0)    ;get Left polygon x
  349.    Px1 = Lefttable(y%, 1)          ;get Left picture x
  350.    Py1 = Lefttable(y%, 2)          ;get Left picture y  
  351.  
  352.    Polyx2% = Righttable((y%), 0)   ;get Right polygon x
  353.    Px2 = Righttable(y%, 1)         ;get Right picture x
  354.    Py2 = Righttable(y%, 2)         ;get Right picture y
  355.    Linewidth% = Polyx2% - Polyx1%  ;what is the width of this polygon Line
  356.    Linewidth%=Linewidth% Or 1      ;prevent divide by zero
  357.    Pxadd = ((Px2 - Px1)) / Linewidth% ;squash picture xdist into poly xdist
  358.    Pyadd = ((Py2 - Py1)) / Linewidth% ;squash picture ydist into poly ydist
  359.  
  360.    For x% = Polyx1% To Polyx2%
  361.      If x>0 And x<=319 ; clipping x
  362.       Col%=ReadPixelFast((Px1 Shr 16),(Py1 Shr 16),imgtxt)
  363.       WritePixelFast x%,y%,Col%
  364.      EndIf
  365.      Px1 = Px1 + Pxadd        ; move x picture co-ord
  366.      Py1 = Py1 + Pyadd        ; move y picture co-ord
  367.    Next
  368.   EndIf
  369.  Next
  370. End Function
  371.  
  372. ; eo  texture mapping functions
  373.  
  374.  
  375. .building
  376. ; a simple cube mesh: 24 Points (unshared Vertices) and 6 Quads (must be clockwise):
  377. ; (Of course you could implement a Loading Function as well)
  378. Data 23  ; number of pts -1
  379. ;    x   y   z
  380.  
  381. Data -100,-100,-100
  382. Data -100,100,-100
  383. Data -100,100,100
  384. Data -100,-100,100
  385.  
  386. Data -100,-100,-100
  387. Data  -100,-100,100
  388. Data  100,-100, 100
  389. Data 100,-100, -100
  390.  
  391. Data -100,100,-100
  392. Data  100,100,-100
  393. Data  100,100, 100
  394. Data -100,100, 100
  395.  
  396. Data 100,-100,-100
  397. Data 100,-100,100
  398. Data 100,100,100
  399. Data 100,100,-100
  400.  
  401. Data -100,100,100
  402. Data 100,100,100
  403. Data 100,-100,100
  404. Data -100,-100,100
  405.  
  406. Data -100,100,-100
  407. Data -100,-100,-100
  408. Data 100,-100,-100
  409. Data 100,100,-100


Comments :


jfk EO-11110(Posted 7 months ago)

 Additional note: was able to quadruple the framerate by grabing the texture pixels from an 2D array, instead of the imagebuffer (don't know why I didn't do that in the first place).Also, draw instead z order from near to far and count drawn pixels(and draw+count only untouched ones), then skip rendering if amount reaches n of screen-pixels. Also, render to intermediate array, so no readpixel is required (for checking if pixel untouched).


Flanker(Posted 7 months ago)

 Nice work here ! Very interesting.


jfk EO-11110(Posted 7 months ago)

 Thanks, as you have seen, the one in the blitz3d discussion is the successor. So the incorrect linear texturemapping here is rather of historical interest.


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal