## Tile - the perspective way

Game development specific discussions.
leopardpm
Posts: 1792
Joined: Feb 28, 2009 20:58

### Re: Tile - the perspective way

nice Dodicat! I like how the size of the circles change with perspective
Tourist Trap
Posts: 2756
Joined: Jun 02, 2015 16:24

### Re: Tile - the perspective way

dodicat wrote:A grid, similar to tourist ...

My arms are detaching from my shoulders ;-) It's an amazing piece of art. I'll try to figure out how it works!

Any idea on how transform square to any quadrangle in a linear fashion, pixel -> pixel mapping ?
leopardpm
Posts: 1792
Joined: Feb 28, 2009 20:58

### Re: Tile - the perspective way

without going through the code, and knowing Dodicat, he is probably 'just' rotating the end-points through 3D space... the 3D -> 2D(screen) function is pretty simple and fast.

just looked at the code... yeah, except he sets up everything with tricky vector stuff and matrix manipulations(i think!?)... I can never de-code his code...

here is a reference I use to plot 3D to 2D(screen): http://freespace.virgin.net/hugo.elias/routines/3d_to_2d.htm
there are alot of google hits on this as well
dodicat
Posts: 5893
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: Tile - the perspective way

The axial rotate is Rodriue's method.
Dot and cross products I am afraid.
It's the easiest way to do it.
Here are some actual coloured tiles.
But the method is not very analytical.

Code: Select all

`Screen 20,32dim as integer xres,yresscreeninfo xres,yres#include "crt.bi"Type sincos    As Single s,cEnd TypeType v3    As Single x,y,z    As Ulong col    Declare Property length As Single    Declare Property unit As v3    Declare Function AxialRotate(As v3,As sincos,As V3) As v3    Declare Function perspective(eyepoint As v3) As v3    #define vct Type<v3>    #define dot *    #define cross ^End TypeOperator + (v1 As v3,v2 As v3) As v3Return Type<v3>(v1.x+v2.x,v1.y+v2.y,v1.z+v2.z)End OperatorOperator -(v1 As v3,v2 As v3) As v3Return Type<v3>(v1.x-v2.x,v1.y-v2.y,v1.z-v2.z)End OperatorOperator * (f As Single,v1 As v3) As v3 Return vct(f*v1.x,f*v1.y,f*v1.z)End OperatorOperator *(v1 As v3,f As Single) As v3Return f*v1End OperatorOperator * (v1 As v3,v2 As v3) As Single 'dot productReturn v1.x*v2.x+v1.y*v2.y+v1.z*v2.zEnd OperatorOperator ^ (v1 As v3,v2 As v3) As v3     'cross productReturn Type<v3>(v1.y*v2.z-v2.y*v1.z,-(v1.x*v2.z-v2.x*v1.z),v1.x*v2.y-v2.x*v1.y)End OperatorOperator /(v1 As v3,n As Single) As v3Return Type<v3>(v1.x/n,v1.y/n,v1.z/n)End OperatorProperty v3.length As SingleReturn Sqr(this.x*this.x+this.y*this.y+this.z*this.z)End PropertyProperty v3.unit As v3 'normalizeDim n As Single=this.lengthIf n=0 Then n=1e-20Return This/nEnd PropertyFunction v3.AxialRotate(centre As v3,Angle As sincos,norm As V3) As v3    Dim As v3 V=This-centre    Var ret= (V*angle.C+(Norm cross V)*angle.S+Norm*(Norm dot V)*(1-angle.c))+centre     Return vct(ret.x,ret.y,ret.z,col)End FunctionFunction v3.perspective(eyepoint As v3) As v3    Dim As Single   w=1+(this.z/eyepoint.z)    If w=0 Then w=1e-20    Var ret= eyepoint+(This-eyepoint)/w    Return vct(ret.x,ret.y,ret.z,col)End FunctionFunction Regulate(Byval MyFps As long,Byref fps As long) As long    Static As Double timervalue,lastsleeptime,t3,frames    Dim As Double t=Timer    frames+=1    If (t-t3)>=1 Then t3=t:fps=frames:frames=0    Dim As long sleeptime=lastsleeptime+((1/myfps)-T+timervalue)*1000    If sleeptime<1 Then sleeptime=1    lastsleeptime=sleeptime    timervalue=T    Return sleeptimeEnd FunctionSub drawarray(a() As V3) 'draw the lines only    For n As long=Lbound(a) To Ubound(a)-2 Step 2        if n<> ubound(a)\2-1 then Line(a(n).x,a(n).y)-(a(n+1).x,a(n+1).y),rgb(0,0,1)    Next nEnd Sub'========================================================Redim As V3 pts()Dim As double pi=4*Atn(1)'create all the pointsDim As long ctr,fps,ctr2Dim As Long k=400 'the z depthredim as v3 c()For n As long=1 To 200 Step 4    ctr+=1    k=-k    Redim Preserve pts(1 To ctr)    pts(ctr)=Type<V3>(20*ctr+10,yres/2,-k)Next n'the points are now on the horizontal planereDim As V3 rot(Lbound(pts) To Ubound(pts))var tmp=ubound(pts)'create another set, 90 degrees to first set, by rotating round the y axisFor n As long=Lbound(pts) To Ubound(pts)    rot(n)=pts(n).axialrotate(Type(xres/2,yres/2,0),Type<sincos>(Sin(pi/2),Cos(pi/2)),Type<v3>(0,1,0))    next nredim as V3 T(1 to tmp*2)'add the two sets into T()memcpy(@T(1),@pts(1),(Ubound(pts)-Lbound(pts)+1)*Sizeof(V3))memcpy(@T(Ubound(pts)),@rot(1),(Ubound(rot)-Lbound(rot)+1)*Sizeof(V3))'temp set points verticaldim as V3 temp(lbound(T) to ubound(T))For n As long=Lbound(T) To Ubound(T)    temp(n)=T(n).axialrotate(Type(xres/2,yres/2,0),Type<sincos>(Sin(pi/2),Cos(pi/2)),Type<v3>(1,0,0))Next n'get the centres of each tile for painting (not very scientific) for x as integer=215 to 800 step 40     for y as integer=30+80 to 600+80 step 40         ctr2+=1         redim preserve c(1 to ctr2)         c(ctr2)=type<V3>(x,y,0)     next y next x 'rotate the centres back to horizontal, give a random colour For n As long=Lbound(C) To Ubound(C)    C(n)=C(n).axialrotate(Type(xres/2,yres/2,0),Type<sincos>(Sin(-pi/2),Cos(-pi/2)),Type<v3>(1,0,0))    c(n).col=rgb(rnd*255,rnd*255,rnd*255)Next nDim As v3 axis=(0,1,0)'now tilt this y axis forwardaxis=axis.axialrotate(Type<v3>(0,0,0),Type<sincos>(Sin(.4),Cos(.4)),Type<v3>(1,0,0))axis=axis.unit'normalize the new y axis'tilt all the points the same angle as the y axis (above)For n As long=Lbound(T) To Ubound(T)    T(n)=T(n).axialrotate(Type(1024/2,768/2,0),Type<sincos>(Sin(.4),Cos(.4)),Type<v3>(1,0,0))Next n'and tilt the tile centres forwardfor n as integer=1 to ubound(c) c(n)=c(n).axialrotate(Type(1024/2,768/2,0),Type<sincos>(Sin(.4),Cos(.4)),Type<v3>(1,0,0))Next n   'rot for the points,crot for the centres.redim rot(lbound(t) to ubound(T)):redim crot(1 to ubound(c)) as V3Dim As sincos angDim As Single zDo    z+=.01    ang=Type<sincos>(Sin(z),Cos(z))    Screenlock    Cls    Draw String(50,50),"FPS = " &fps    For n As long=Lbound(T) To Ubound(T)        rot(n)=T(n).axialrotate(Type<v3>(xres\2,yres\2,0),ang,axis)        rot(n)=rot(n).perspective(Type<v3>(xres\2,yres\2,900))'900 deep for the eyepoint    Next n        For n As long=Lbound(crot) To Ubound(crot)        crot(n)=c(n).axialrotate(Type<v3>(xres\2,yres\2,0),ang,axis)        crot(n)=crot(n).perspective(Type<v3>(xres\2,yres\2,900))'900 deep for the eyepoint    Next n        drawarray(rot())        for n as integer=lbound(crot) to ubound(crot)        paint(crot(n).x,crot(n).y),c(n).col,rgb(0,0,1)        next n        Screenunlock    Sleep regulate(40,fps)Loop Until inkey=chr(27)Sleep  `
Tourist Trap
Posts: 2756
Joined: Jun 02, 2015 16:24

### Re: Tile - the perspective way

dodicat wrote:The axial rotate is Rodriue's method.

I'll try all that. Sounds nice. Rodrigue rotation is a must you're right, and not so difficult. I've already used that some times ago.
dodicat
Posts: 5893
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: Tile - the perspective way

It's so easy, it's more or less a one liner
The statement here:
https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
and my statement in the function:
Var ret= (V*angle.C+(Norm cross V)*angle.S+Norm*(Norm dot V)*(1-angle.c))+centre
where angle.C is just cos(angle)
and
angle.s is just sin(angle)
and Norm is just (K) the unit vector pointing the axis direction.
Tourist Trap
Posts: 2756
Joined: Jun 02, 2015 16:24

### Re: Tile - the perspective way

dodicat wrote:It's so easy, it's more or less a one liner
The statement here:
https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
and my statement in the function:
Var ret= (V*angle.C+(Norm cross V)*angle.S+Norm*(Norm dot V)*(1-angle.c))+centre
where angle.C is just cos(angle)
and
angle.s is just sin(angle)
and Norm is just (K) the unit vector pointing the axis direction.

Yes it's not very hard. But I have difficulties to do the 3D -> 2D final projection. When I had used rodrigues before, it was on 3D software (gmax). No projection was required. I'm so weak at projecting on screen that I use intersections, far more computations for cpu...
Tourist Trap
Posts: 2756
Joined: Jun 02, 2015 16:24

### Re: Tile - the perspective way

Oh damn, I finally made it with this bilinear mapping. The formula was just a little huge. Anyway now, this part of the work is complete:

Code: Select all

`'case_study-----------------------'perspective transform of an image'---------------------------------const as string   imgFileName => "planet.bmp"const as long     imgW          =>  200const as long     imgH          =>  260const as ulong    imgTransColor => rgb(255,0,255)const as long     screenWidth   => 800const as long     screenHeight  => 400#include "fbgfx.bi"declare sub BiLinearXY(byval Img   as fb.IMAGE ptr)'(ui routine)declare function DrawWindowFrame(byval as fb.IMAGE ptr) as fb.IMAGE ptrdeclare sub DrawExitButton(byval as boolean=FALSE)declare function TestFrameWorkForMouse() as booleantype SCREENTEST extends OBJECT    declare static sub TestScreen()    static as integer  scrW    static as integer  scrHend typetype MOUSETEST extends SCREENTEST    declare static function TestMouse() as long    static as long  gmX    static as long  gmY    static as long  gmBtnend typetype BUTTON extends MOUSETEST    declare constructor()    declare constructor(byval as long, _                         byval as long, _                         byval as long, _                         byval as long, _                         byval as string)    declare property CenterXForText() as long    declare property CenterYForText() as long    declare property MouseClick() as boolean    declare sub TestButton()    declare sub DrawButton()    static as long      fontWidth    static as long      fontHeight    static as double    clickDelay        as long     _topLeftCornerX        as long     _topLeftCornerY        as long     _width        as long     _height        as string   _text        as boolean  _mouseOver        as boolean  _mouseClickend typedim as integer SCREENTEST.scrW       => -1dim as integer SCREENTEST.scrH       => -1sub SCREENTEST.TestScreen()    screenInfo (SCREENTEST.scrW, SCREENTEST.scrH)end subdim as long MOUSETEST.gmX       => -1dim as long MOUSETEST.gmY       => -1dim as long MOUSETEST.gmBtn     => -1function MOUSETEST.TestMouse() as long    '---->    return getMouse (MOUSETEST.gmX, _                      MOUSETEST.gmY, _                      , _                      MOUSETEST.gmBtn)end functiondim as long     BUTTON.fontWidth   => 8dim as long     BUTTON.fontHeight  => 8dim as double   BUTTON.clickDelay  => 0.8constructor BUTTON()    BASE()    '   dim as integer scrW, scrH   screenInfo  scrW, scrH    with THIS        ._topLeftCornerX    => scrW\3        ._topLeftCornerY    => scrH\3        ._width             => scrW\3        ._height            => scrH\3        ._text              => left("default button", _                                     len("default button")*BUTTON.fontWidth\8)        ._mouseOver         => FALSE        ._mouseClick        => FALSE    end withend constructorconstructor BUTTON(byval TLCX  as long, _                    byval TLCY  as long, _                    byval W     as long, _                    byval H     as long, _                    byval Text  as string)    BASE()    '    with THIS        ._topLeftCornerX    => TLCX        ._topLeftCornerY    => TLCY        ._width             => W        ._height            => H        ._text              => left(Text, _                                     len(Text)*BUTTON.fontWidth\8)        ._mouseOver         => FALSE        ._mouseClick        => FALSE    end withend constructorproperty BUTTON.CenterXForText() as long    '---->    return THIS._topLeftCornerX + _           ( THIS._width - len(THIS._text)*BUTTON.fontWidth )\2end propertyproperty BUTTON.CenterYForText() as long    '---->    return THIS._topLeftCornerY + _            ( THIS._height - BUTTON.fontHeight )\2end propertyproperty BUTTON.MouseClick() as boolean    '---->    return (THIS._mouseOver and THIS._mouseClick)end propertysub BUTTON.TestButton()    static as double    clickTime    if TIMER<(clickTime + BUTTON.clickDelay) then         if THIS._mouseOver=TRUE then THIS._mouseOver = FALSE        exit sub    else        if THIS._mouseClick=TRUE then THIS._mouseClick = FALSE    end if    '    THIS.TestMouse()    '    if THIS.gmX>=THIS._topLeftCornerX                   and _        THIS.gmX<(THIS._topLeftCornerX + THIS._width)    and _        THIS.gmY>=THIS._topLeftCornerY                   and _        THIS.gmY<(THIS._topLeftCornerY + THIS._height)   then        if THIS._mouseOver=FALSE then THIS._mouseOver = TRUE        if THIS.gmBtn=+1    then            if THIS._mouseClick=FALSE then                 THIS._mouseClick    = TRUE                clickTime           = TIMER            end if        else            if THIS._mouseClick=TRUE then THIS._mouseClick = FALSE        end if    else        if THIS._mouseOver=TRUE then THIS._mouseOver = FALSE        if THIS._mouseClick=TRUE then THIS._mouseClick = FALSE    end if    end subsub BUTTON.DrawButton()    THIS.TestButton()    '    dim as long x   = THIS._topLeftCornerX    dim as long y   = THIS._topLeftCornerY    dim as long w   = THIS._width    dim as long h   = THIS._height    dim as string t = THIS._text    '    dim as ulong bckgColor    if  THIS._mouseClick    then        bckgColor  = rgb(100,190,140)    elseif THIS._mouseOver  then        bckgColor  = rgb(100,100,160)    else        bckgColor  = rgb(100,100,100)    end if        '    line (x,y)-step(w,h), , b    line (x + 1,y + 1)-step(w - 1,h - 1), bckgColor, bf    draw string (THIS.CenterXForText,THIS.CenterYForText), tend sub'-------------------------------------------randomize TIMERscreenRes screenWidth, _           screenHeight, _           32, _           1, _           fb.GFX_NO_FRAME'note:'gfx screen should always be initialized before image creationSCREENTEST.TestScreen()dim as fb.IMAGE ptr drawingImgdim as fb.IMAGE ptr clearDrawingImgdrawingImg      => DrawWindowFrame(drawingImg)clearDrawingImg => DrawWindowFrame(clearDrawingImg)dim as integer drawingZoneWdim as integer drawingZoneHimageInfo drawingImg, drawingZoneW, drawingZoneHdim as fb.IMAGE ptr     tileImgtileImg =>  imageCreate(imgW, imgH, imgTransColor, 32)bLoad imgFileName, tileImgdim as BUTTON   testBtn     => BUTTON(SCREENTEST.scrW - 480, _                                       SCREENTEST.scrH - 320, _                                      120, _                                       12, _                                       "Test")'---------------main_loop---------------dim as double   startTimedim as double   endTimedim as boolean  quitOrder   => FALSEdo    SCREENTEST.TestScreen()    MOUSETEST.TestMouse()   quitOrder   = TestFrameWorkForMouse()    screenLock       cls      imageInfo DrawWindowFrame(drawingImg), _                   drawingZoneW, _                   drawingZoneH      DrawExitButton(quitOrder)                put (060, 120), tileImg, TRANS                        testBtn.DrawButton()        if testBtn.MouseClick then            DrawWindowFrame(clearDrawingImg)            draw string (10,54), "pixel transfer.."                startTime   = TIMER                BilinearXY(tileImg)                endTime     = TIMER            draw string (10,40),  "op. time="& str(cSng(endTime - startTime))            if (endTime - startTime)>0.01 then                 draw string (140,54), "slow"            else                draw string (140,54), "fast"            end if            get (04,28)-step(drawingZoneW - 1,drawingZoneH -1), drawingImg        end if           screenUnlock   if quitOrder then         '(quit)        imageDestroy tileImg        imageDestroy drawingImg        sleep 200        end 0    else        '(standard delay)        sleep 15   end ifloop until inkey=chr(27)    '(explicit clean up)imageDestroy tileImgimageDestroy drawingImg'-------------program_termination-------------sleepend 0'(ui)function DrawWindowFrame(byval DrawingZone as fb.IMAGE ptr) as fb.IMAGE ptr   line (00,00)-(SCREENTEST.scrW - 1, SCREENTEST.scrH - 1), _          rgb(200,190,220), _          bf    for x as long = 0 to SCREENTEST.scrW\10        line (04 + 4*x,04)-(SCREENTEST.scrW - 1 - 4, 24), _              rgb(190 - x,200,090 + x), _              bf    next x    for x as long = 0 to SCREENTEST.scrW\10        line (04 + 2*x,24)-(SCREENTEST.scrW - 1 - 4 - 2*x, SCREENTEST.scrH - 1 - 4), _              rgb(100 + x,100 + x\2,120 + x), _              bf    next x    line (04,24)-(SCREENTEST.scrW - 1 - 4, 28), _          rgb(200,200,220), _          bf   draw string (08,12), _                 "TEST FRAMEWORK FOR PERSPECTIVE - FB1.04" & _                 " (note: window not movable not resizable)", _                 rgb(030,050,140)    if DrawingZone<>0 then        put (04,28), DrawingZone, TRANS    else        DrawingZone = imageCreate(SCREENTEST.scrW - 8, _                                   SCREENTEST.scrH - 32, _                                   imgTransColor, _                                   32)    end if    '    '---->    return DrawingZoneend functionsub DrawExitButton(byval QuitOrderSent as boolean=FALSE)   line (SCREENTEST.scrW - 1 - 4 - 18, 5)-(SCREENTEST.scrW - 1 - 5, 22), _          rgb(250,80,80), _          bf   draw string (SCREENTEST.scrW - 1 - 4 - 12,12), "X"   if QuitOrderSent then      line (SCREENTEST.scrW - 1 - 4 - 16, 7)- _              (SCREENTEST.scrW - 1 - 6, 20), _              rgb(140,120,080), _              bf   end ifend subfunction TestFrameWorkForMouse() _                         as boolean   dim as boolean QuitOrder   if MOUSETEST.gmX>(SCREENTEST.scrW - 1 - 4 - 18) and _      MOUSETEST.gmX<(SCREENTEST.scrW - 1 - 5) and _      MOUSETEST.gmY>5 and _       MOUSETEST.gmY<22 then         if MOUSETEST.gmBtn=+1 then          QuitOrder = TRUE         end if   else      QuitOrder = FALSE   end if   '---->   return QuitOrderend function'***Bilinear stuff***sub BiLinearXY(byval Img   as fb.IMAGE ptr)    'original image rectangle    dim as single   x0 = 0, y0 = 0    dim as single   x1 = imgW - 1, y1 = 0    dim as single   x2 = imgW - 1, y2 = imgH - 1    dim as single   x3 = 0, y3 = imgH - 1    'set up a new quadrangle    dim as single   xA = x0 + imgW/2 + (rnd()*45 - 89), yA = y0 + (rnd()*85)    dim as single   xB = x1 + imgW/2 + (rnd()*40 - 79), yB = y1 + (rnd()*20 - 40)    dim as single   xC = x2 + imgW/2 + (rnd()*40 - 79), yC = y2 + (rnd()*20 - 40)    dim as single   xD = x3 + imgW/2 + (rnd()*40 - 79), yD = y3 + (rnd()*20 - 40)    '    line (xA + 400,yA + 120)-(xB + 400,yB + 120), rgb(255,0,255)    line step-(xC + 400,yC + 120)    line step-(xD + 400,yD + 120)    line step-(xA + 400,yA + 120)    '    dim as double   a    dim as double   b    dim as double   c    dim as double   d    dim as double   e    dim as double   f    dim as double   g    dim as double   h    '    a   = ((((x3-x2)*xB+(x2-x3)*xA)*y2+((x1-x3)*xC+(x3-x1)*xA)*y1+((x3-x0)*xC+(x0-x3)*xB)*y0)*y3+(((x2-x1)*xD+(x1-x2)*xA)*y1+((x0-x2)*xD+(x2-x0)*xB)*y0)*y2+((x1-x0)*xD+(x0-x1)*xC)*y0*y1)/((((x1-x0)*x3+(x0-x1)*x2)*y2+((x0-x2)*x3+x1*x2-x0*x1)*y1+((x2-x1)*x3-x0*x2+x0*x1)*y0)*y3+(((x2-x1)*x3-x0*x2+x0*x1)*y1+((x0-x2)*x3+x1*x2-x0*x1)*y0)*y2+((x1-x0)*x3+(x0-x1)*x2)*y0*y1)    b   = (((x1-x0)*x3*xC+(x0-x2)*x3*xB+(x2-x1)*x3*xA)*y3+((x0-x1)*x2*xD+(x2*x3-x0*x2)*xB+(x1*x2-x2*x3)*xA)*y2+((x1*x2-x0*x1)*xD+(x0*x1-x1*x3)*xC+(x1*x3-x1*x2)*xA)*y1+((x0*x1-x0*x2)*xD+(x0*x3-x0*x1)*xC+(x0*x2-x0*x3)*xB)*y0)/((((x1-x0)*x3+(x0-x1)*x2)*y2+((x0-x2)*x3+x1*x2-x0*x1)*y1+((x2-x1)*x3-x0*x2+x0*x1)*y0)*y3+(((x2-x1)*x3-x0*x2+x0*x1)*y1+((x0-x2)*x3+x1*x2-x0*x1)*y0)*y2+((x1-x0)*x3+(x0-x1)*x2)*y0*y1)    c   = -(((x1-x0)*xC+(x0-x2)*xB+(x2-x1)*xA)*y3+((x0-x1)*xD+(x3-x0)*xB+(x1-x3)*xA)*y2+((x2-x0)*xD+(x0-x3)*xC+(x3-x2)*xA)*y1+((x1-x2)*xD+(x3-x1)*xC+(x2-x3)*xB)*y0)/((((x1-x0)*x3+(x0-x1)*x2)*y2+((x0-x2)*x3+x1*x2-x0*x1)*y1+((x2-x1)*x3-x0*x2+x0*x1)*y0)*y3+(((x2-x1)*x3-x0*x2+x0*x1)*y1+((x0-x2)*x3+x1*x2-x0*x1)*y0)*y2+((x1-x0)*x3+(x0-x1)*x2)*y0*y1)    d   = -((((x0*x3-x0*x2)*xB+(x1*x2-x1*x3)*xA)*y2+((x0*x1-x0*x3)*xC+(x2*x3-x1*x2)*xA)*y1+((x1*x3-x0*x1)*xC+(x0*x2-x2*x3)*xB)*y0)*y3+(((x0*x2-x0*x1)*xD+(x1-x2)*x3*xA)*y1+((x0*x1-x1*x2)*xD+(x2-x0)*x3*xB)*y0)*y2+((x1-x0)*x2*xD+(x0-x1)*x3*xC)*y0*y1)/((((x1-x0)*x3+(x0-x1)*x2)*y2+((x0-x2)*x3+x1*x2-x0*x1)*y1+((x2-x1)*x3-x0*x2+x0*x1)*y0)*y3+(((x2-x1)*x3-x0*x2+x0*x1)*y1+((x0-x2)*x3+x1*x2-x0*x1)*y0)*y2+((x1-x0)*x3+(x0-x1)*x2)*y0*y1)       e   = ((((x2-x1)*y1+(x0-x2)*y0)*y2+(x1-x0)*y0*y1)*yD+(((x1-x3)*y1+(x3-x0)*y0)*y3+(x0-x1)*y0*y1)*yC+(((x3-x2)*y2+(x0-x3)*y0)*y3+(x2-x0)*y0*y2)*yB+(((x2-x3)*y2+(x3-x1)*y1)*y3+(x1-x2)*y1*y2)*yA)/((((x1-x0)*x3+(x0-x1)*x2)*y2+((x0-x2)*x3+x1*x2-x0*x1)*y1+((x2-x1)*x3-x0*x2+x0*x1)*y0)*y3+(((x2-x1)*x3-x0*x2+x0*x1)*y1+((x0-x2)*x3+x1*x2-x0*x1)*y0)*y2+((x1-x0)*x3+(x0-x1)*x2)*y0*y1)    f   = -(((x1-x0)*x2*y2+(x0*x1-x1*x2)*y1+(x0*x2-x0*x1)*y0)*yD+((x0-x1)*x3*y3+(x1*x3-x0*x1)*y1+(x0*x1-x0*x3)*y0)*yC+((x2-x0)*x3*y3+(x0*x2-x2*x3)*y2+(x0*x3-x0*x2)*y0)*yB+((x1-x2)*x3*y3+(x2*x3-x1*x2)*y2+(x1*x2-x1*x3)*y1)*yA)/((((x1-x0)*x3+(x0-x1)*x2)*y2+((x0-x2)*x3+x1*x2-x0*x1)*y1+((x2-x1)*x3-x0*x2+x0*x1)*y0)*y3+(((x2-x1)*x3-x0*x2+x0*x1)*y1+((x0-x2)*x3+x1*x2-x0*x1)*y0)*y2+((x1-x0)*x3+(x0-x1)*x2)*y0*y1)    g   = (((x1-x0)*y2+(x0-x2)*y1+(x2-x1)*y0)*yD+((x0-x1)*y3+(x3-x0)*y1+(x1-x3)*y0)*yC+((x2-x0)*y3+(x0-x3)*y2+(x3-x2)*y0)*yB+((x1-x2)*y3+(x3-x1)*y2+(x2-x3)*y1)*yA)/((((x1-x0)*x3+(x0-x1)*x2)*y2+((x0-x2)*x3+x1*x2-x0*x1)*y1+((x2-x1)*x3-x0*x2+x0*x1)*y0)*y3+(((x2-x1)*x3-x0*x2+x0*x1)*y1+((x0-x2)*x3+x1*x2-x0*x1)*y0)*y2+((x1-x0)*x3+(x0-x1)*x2)*y0*y1)    h   = -((((x0*x2-x0*x1)*y1+(x0*x1-x1*x2)*y0)*y2+(x1-x0)*x2*y0*y1)*yD+(((x0*x1-x0*x3)*y1+(x1*x3-x0*x1)*y0)*y3+(x0-x1)*x3*y0*y1)*yC+(((x0*x3-x0*x2)*y2+(x0*x2-x2*x3)*y0)*y3+(x2-x0)*x3*y0*y2)*yB+(((x1*x2-x1*x3)*y2+(x2*x3-x1*x2)*y1)*y3+(x1-x2)*x3*y1*y2)*yA)/((((x1-x0)*x3+(x0-x1)*x2)*y2+((x0-x2)*x3+x1*x2-x0*x1)*y1+((x2-x1)*x3-x0*x2+x0*x1)*y0)*y3+(((x2-x1)*x3-x0*x2+x0*x1)*y1+((x0-x2)*x3+x1*x2-x0*x1)*y0)*y2+((x1-x0)*x3+(x0-x1)*x2)*y0*y1)    '    dim as single xTprev, yTprev    dim as single xT, yT    dim as single x, y    dim as ulong lastColor    for x = 0 to (imgW - 1) step .5        for y = 0 to (imgH - 1) step .5            xT = a*x + b*y + c*x*y + d            yT = e*x + f*y + g*x*y + h            lastColor = point(x,y,Img)            pSet (xT + 400, yT + 120), lastColor        next y        '    next x    /'    for x as long = 0 to (imgW - 1)        for y as long = 0 to (imgH - 1)            dim as single xT = a*x + b*y + c*x*y + d            dim as single yT = e*x + f*y + g*x*y + h            pSet (xT + 400, yT + 120), point(x,y,Img)        next y            next x    '/end sub'(EOF)`
leopardpm
Posts: 1792
Joined: Feb 28, 2009 20:58

### Re: Tile - the perspective way

that's pretty good! a useful routine indeed
Tourist Trap
Posts: 2756
Joined: Jun 02, 2015 16:24

### Re: Tile - the perspective way

leopardpm wrote:that's pretty good! a useful routine indeed

Very kind, thanks for your attention!
However the value of this showcase here is probably more to be very straighforward with the maths involved. I solved the whole thing with Maxima (a free symbolic math solver), copied it and pasted without any other adjustement.
It would unfortunately be far too slow to do any real time texture mapping. I will try to go to the end of this however, just for the fun. It's now just a matter of a last round :)

Here a link about the math involved:
https://math.stackexchange.com/question ... -rectangle

edit : some addition here

Code: Select all

`'---------------------------------'rotation of a plane grid network'provided 3D space eye parameter'shows in a box now'---------------------------------#include "fbgfx.bi"const as double   _pi            => atn(1)*4const as ulong    _lightGrey     => rgb(205,205,205)'tile constantconst as long     imgW           => 15const as long     imgH           => 15const as ulong    imgTransColor  => rgb(255,0,255)'screen constantconst as long     screenWidth    => 800const as long     screenHeight   => 600#macro _ExitforOnEscapeKeyPressed   if inkey=chr(27) then exit for#endMacro'---------------------------------type SCREENTEST extends OBJECT   'global variable container   'storing screen parameter   declare static sub TestScreen()   static as integer  scrW   static as integer  scrHend type 'SCREENTEST <- OBJECTdim as integer SCREENTEST.scrW       => -1dim as integer SCREENTEST.scrH       => -1sub SCREENTEST.TestScreen()   screenInfo (SCREENTEST.scrW, SCREENTEST.scrH)end sub 'SCREENTEST.TestScreen()type INTERACTIONTEST extends SCREENTEST   'global variable container   'storing mouse/keyboard interaction   declare static function TestMouse() as long   declare static function TestKeyboard() as long   static as long  gmX   static as long  gmY   static as long  gmBtn   static as long  scanCodeend type 'INTERACTIONTEST <- SCREENTEST <- OBJECTdim as long INTERACTIONTEST.gmX        => -1dim as long INTERACTIONTEST.gmY        => -1dim as long INTERACTIONTEST.gmBtn      => -1dim as long INTERACTIONTEST.scanCode   => -1function INTERACTIONTEST.TestMouse() as long   return getMouse ( INTERACTIONTEST.gmX, _                     INTERACTIONTEST.gmY, _                     , _                     INTERACTIONTEST.gmBtn   )end function 'LNG:=INTERACTIONTEST.TestMouse()function INTERACTIONTEST.TestKeyboard() as long   dim as long scanCodeResult => -1   if multiKey(fb.SC_BACKSPACE) then      scanCodeResult = fb.SC_BACKSPACE   elseif   multiKey(fb.SC_SPACE)   then      scanCodeResult = fb.SC_SPACE   elseif   multiKey(fb.SC_LEFT)    andAlso   multiKey(fb.SC_UP)      then      scanCodeResult = fb.SC_LEFT + fb.SC_UP   elseif   multiKey(fb.SC_LEFT)    andAlso   multiKey(fb.SC_DOWN)    then      scanCodeResult = fb.SC_LEFT + fb.SC_DOWN   elseif   multiKey(fb.SC_RIGHT)   andAlso   multiKey(fb.SC_UP)      then      scanCodeResult = fb.SC_RIGHT + fb.SC_UP   elseif   multiKey(fb.SC_RIGHT)   andAlso   multiKey(fb.SC_DOWN)    then      scanCodeResult = fb.SC_RIGHT + fb.SC_DOWN   elseif   multiKey(fb.SC_LEFT)    then      scanCodeResult   =    fb.SC_LEFT   elseif   multiKey(fb.SC_RIGHT)   then      scanCodeResult = fb.SC_RIGHT   elseif   multiKey(fb.SC_DOWN)    then      scanCodeResult = fb.SC_DOWN   elseif   multiKey(fb.SC_UP)      then      scanCodeResult = fb.SC_UP   end if   '   while inkey<>"" : /'clean keyboard buffer'/ :wend   INTERACTIONTEST.scanCode = scanCodeResult   '   return scanCodeResultend function 'LNG:=INTERACTIONTEST.TestMouse()type POINT2D extends SCREENTEST   declare constructor()   declare constructor( byval as double, _                        byval as double, _                        byval as string, _                        byval as ulong=rgb(205,205,205)  )   declare operator Let(byval as long)   declare property OutOfScreen() as boolean   declare property DistanceToOrigin() as double   declare sub DrawPoint2D()   static as long    constructionCount      as double      _x      as double      _y      as string      _id      as ulong       _colorend type 'POINT2D <- SCREENTEST <- OBJECTdim as long POINT2D.constructionCountconstructor POINT2D()   BASE()   POINT2D.constructionCount +=> 1   THIS.TestScreen()   '   with THIS      ._x      => SCREENTEST.scrW\2      ._y      => SCREENTEST.scrH\2      ._id     => "point" & str(POINT2D.constructionCount)      ._color  => rgb(205,205,205)   end with 'THISend constructor 'POINT2D default explicit constructorconstructor POINT2D( byval X     as double, _                     byval Y     as double, _                     byval Id    as string, _                     byval C     as ulong=rgb(205,205,205)  )   BASE()   '   with THIS      ._x      => X      ._y      => Y      ._id     => Id      ._color  => C   end with 'THISend constructor 'POINT2D(valDBL,valDBL,valSTR,valULNG[rgb(205,205,205)])operator POINT2D.Let(byval SameForAllCoordinate as long)   with THIS      ._x   =   SameForAllCoordinate      ._y   =   SameForAllCoordinate   end with 'THISend operator 'POINT2D:=valLNGproperty POINT2D.OutOfScreen() as boolean   THIS.TestScreen()   '   if not( THIS._x>=0 andAlso THIS._x<=THIS.scrW andAlso _           THIS._y>=0 andAlso THIS._y<=THIS.scrH   ) then      '      return TRUE   else      '      return FALSE   end ifend property 'get BOOL:=POINT2D.OutOfScreenproperty POINT2D.DistanceToOrigin() as double      '      return sqr(THIS._x*THIS._x + THIS._y*THIS._y)end property 'get DBL:=POINT2D.DistanceToOriginsub POINT2D.DrawPoint2D()   THIS.TestScreen()   '   if THIS._x>=0 andAlso  THIS._x<=THIS.scrW andAlso _      THIS._y>=0 andAlso  THIS._y<=THIS.scrH then      circle (THIS._x, THIS._y), 4, THIS._color      circle (THIS._x, THIS._y), 2, THIS._color      draw string (THIS._x - 4, THIS._y - 12), THIS._id   end ifend sub 'POINT2D.DrawPoint2D()type SCREENBIPOINTLINE extends SCREENTEST   declare constructor()   declare constructor( byval as POINT2D, _                        byval as POINT2D=type<POINT2D>(0,0,"o"), _                        byval as ulong=rgb(205,205,205)  )   declare sub DrawLine()   declare sub DrawLineWithPoint()      as POINT2D     _p1      as POINT2D     _p2      as ulong       _lineColorend type 'SCREENBIPOINTLINE <- SCREENTEST <- OBJECTconstructor SCREENBIPOINTLINE()   BASE()   THIS.TestScreen()   '   with THIS      ._p1        => 0      ._p2        => type<POINT2D>(THIS.scrW,THIS.scrH,"Corner")      ._lineColor => rgb(205,205,205)   end with 'THISend constructor 'SCREENBIPOINTLINE default explicit constructorconstructor SCREENBIPOINTLINE(   byval P1   as POINT2D, _                                 byval P2   as POINT2D=type<POINT2D>(0,0,"o"), _                                 byval LC   as ulong=rgb(205,205,205)   )   with THIS      ._p1        => P1      ._p2        => P2      ._lineColor => LC   end with 'THISend constructor 'SCREENBIPOINTLINE(valPOINT2D,valPOINT2D[type<POINT2D>(0,0,"o"),valULNG[rgb(205,205,205)])sub SCREENBIPOINTLINE.DrawLine()   THIS.TestScreen()   '   dim as boolean   case1   => FALSE   dim as boolean   case2   => FALSE   dim as boolean   case3   => FALSE   dim as boolean   case4   => FALSE   if ( (THIS._p1)._x=(THIS._p2)._x andAlso (THIS._p1)._y=(THIS._p2)._y ) then      case1 = TRUE      'no line to draw      exit sub   elseif _      ( (THIS._p1)._x=(THIS._p2)._x andAlso (THIS._p1)._y<>(THIS._p2)._y ) then      case2 = TRUE      if (THIS._p1)._x>=0 andAlso (THIS._p1)._x<=THIS.scrW then         dim as POINT2D   i(1 to 2)         i(1)  => POINT2D((THIS._p1)._x, 0, "y=0")         i(2)  => POINT2D((THIS._p1)._x, THIS.scrH, "y=scrH")         line  (i(1)._x, i(1)._y)- _               (i(2)._x, i(2)._y), _               THIS._lineColor      else         'no line to draw         exit sub      end if   elseif _      ( (THIS._p1)._x<>(THIS._p2)._x and (THIS._p1)._y=(THIS._p2)._y ) then      case3 = TRUE      if (THIS._p1)._y>=0 andAlso (THIS._p1)._y<=THIS.scrH then         dim as POINT2D   i(1 to 2)         i(1)   => POINT2D(0, (THIS._p1)._y, "x=0")         i(2)   => POINT2D(THIS.scrW, (THIS._p1)._y, "x=scrW")         line  (i(1)._x, i(1)._y)- _               (i(2)._x, i(2)._y), _               THIS._lineColor      else         'no line to draw         exit sub      end if    elseif _      ( (THIS._p1)._x<>(THIS._p2)._x andAlso (THIS._p1)._y<>(THIS._p2)._y ) then      case4 = TRUE      dim as double   x1   => (THIS._p1)._x      dim as double   x2   => (THIS._p2)._x      dim as double   y1   => (THIS._p1)._y      dim as double   y2   => (THIS._p2)._y      'compute intersection with screen border      dim as POINT2D   i(1 to 4)      i(1)   => POINT2D(x1 - y1*(x2 - x1)/(y2 - y1), 0, "y=0")      i(2)   => POINT2D(x1 + (THIS.scrH - y1)*(x2 - x1)/(y2 - y1), THIS.scrH, "y=scrH")      i(3)   => POINT2D(0, y1 - x1*(y2 - y1)/(x2 - x1), "x=0")      i(4)   => POINT2D(THIS.scrW, y1 + (THIS.scrW - x1)*(y2 - y1)/(x2 - x1), "x=scrW")      'decide what couple of point to join      dim as long   j(1 to 2)      for index as long = 1 to 4            j(1) => index            exit for      next index      for index as long = 1 to 4         if i( j(1) )._x<>i(index)._x orElse i( j(1) )._y<>i(index)._y then               j(2) => index               exit for         end if      next index      'draw line      line  (i( j(1) )._x, i( j(1) )._y)- _            (i( j(2) )._x, i( j(2) )._y), _            THIS._lineColor   end ifend sub 'SCREENBIPOINTLINE.DrawLine()sub SCREENBIPOINTLINE.DrawLineWithPoint()   (THIS._p1).DrawPoint2D()   (THIS._p2).DrawPoint2D()   '   THIS.DrawLine()end sub 'SCREENBIPOINTLINE.DrawLineWithPoint()type SCRPOS      as integer   _scrPosX      as integer   _scrPosYend Typetype WIDHEI   as integer  _wid   as integer  _heiend typetype BOX   declare constructor()   declare constructor(byval as single, byval as single, byval as single, byval as single)   declare property Xi() as integer   declare property Xi(byval as integer)   declare property Yi() as integer   declare property Yi(byval as integer)   declare property W() as integer   declare property W(byval as integer)   declare property H() as integer   declare property H(byval as integer)   declare property Xf() as integer   declare property Xf(byval as integer)   declare property Yf() as integer   declare property Yf(byval as integer)      as SCRPOS   _scrPos      as WIDHEI   _widHeiend typeconstructor BOX()   'end constructorconstructor BOX(byval XiParam as single, byval YiParam as single, byval WParam as single, byval HParam as single)   THIS.Xi  = XiParam   THIS.Yi  = YiParam   THIS.W   = WParam   THIS.H   = HParamend constructorproperty BOX.Xi() as integer   return THIS._scrPos._scrPosXend propertyproperty BOX.Xi(byval SetValue as integer)   THIS._scrPos._scrPosX = SetValueend propertyproperty BOX.Yi() as integer   return THIS._scrPos._scrPosYEnd Propertyproperty BOX.Yi(byval SetValue as integer)   THIS._scrPos._scrPosY = SetValueend propertyproperty BOX.W() as integer   return THIS._widHei._widend propertyproperty BOX.W(byval SetValue as integer)   THIS._widHei._wid = SetValueEnd Propertyproperty BOX.H() as integer   return THIS._widHei._heiend propertyproperty BOX.H(byval SetValue as integer)   THIS._widHei._hei = SetValueend propertyproperty BOX.Xf() as integer   return ( THIS._scrPos._scrPosX + THIS._widHei._wid - 1 )end propertyproperty BOX.Xf(byval SetValue as integer)   THIS._widHei._wid = SetValue - THIS._scrPos._scrPosX + 1end propertyproperty BOX.Yf() as integer   return ( THIS._scrPos._scrPosY + THIS._widHei._hei - 1 )end propertyproperty BOX.Yf(byval SetValue as integer)   THIS._widHei._hei = SetValue - THIS._scrPos._scrPosY + 1end propertytype BOXBIPOINTLINE extends BOX   declare constructor()   declare constructor(byval as fb.IMAGE ptr, byref as BOX,byref as POINT2D, byref as POINT2D, byval as ulong)   declare sub DrawLine()   declare sub DrawLineWithPoint()      as fb.IMAGE ptr   _imageBuffer      as POINT2D        _p1      as POINT2D        _p2      as ulong          _lineColorend typeconstructor BOXBIPOINTLINE()   BASE()   '   THIS._imageBuffer = 0 ''things wont work and we wont use this constructor   with THIS      ._p1        => type<POINT2D>(THIS.Xi,THIS.Yi,"Origin")      ._p2        => type<POINT2D>(THIS.Xf,THIS.Yf,"Corner")      ._lineColor => rgb(205,205,205)   end withend constructorconstructor BOXBIPOINTLINE(byval Img as fb.IMAGE ptr, byref BoxParam as BOX,byref P1 as POINT2D, byref P2 as POINT2D, byval LineColor as ulong)   cast(BOX, THIS) = BoxParam   '   with THIS      ._imageBuffer  => Img      ._p1        => P1      ._p2        => P2      ._lineColor => rgb(205,205,205)   end with   end constructorsub BOXBIPOINTLINE.DrawLine()   dim as boolean   case1   => FALSE   dim as boolean   case2   => FALSE   dim as boolean   case3   => FALSE   dim as boolean   case4   => FALSE   if ( (THIS._p1)._x=(THIS._p2)._x andAlso (THIS._p1)._y=(THIS._p2)._y ) then      case1 = TRUE      'no line to draw      exit sub   elseif _      ( (THIS._p1)._x=(THIS._p2)._x andAlso (THIS._p1)._y<>(THIS._p2)._y ) then      case2 = TRUE      if (THIS._p1)._x>=Xi andAlso (THIS._p1)._x<=THIS.Xf then         dim as POINT2D   i(1 to 2)         i(1)  => POINT2D((THIS._p1)._x, THIS.Yi, "y=yi")         i(2)  => POINT2D((THIS._p1)._x,THIS.Yf, "y=yf")         line  THIS._imageBuffer, _                (i(1)._x - THIS.Xi, i(1)._y - THIS.Yi)- _               (i(2)._x - THIS.Xi, i(2)._y - THIS.Yi), _               THIS._lineColor      else         'no line to draw         exit sub      end if   elseif _      ( (THIS._p1)._x<>(THIS._p2)._x and (THIS._p1)._y=(THIS._p2)._y ) then      case3 = TRUE      if (THIS._p1)._y>=THIS.Yi andAlso (THIS._p1)._y<=THIS.Yf then         dim as POINT2D   i(1 to 2)         i(1)   => POINT2D(THIS.Xi, (THIS._p1)._y, "x=xi")         i(2)   => POINT2D(THIS.Xf, (THIS._p1)._y, "x=xf")         line  THIS._imageBuffer, _                (i(1)._x - THIS.Xi, i(1)._y - THIS.Yi)- _               (i(2)._x - THIS.Xi, i(2)._y - THIS.Yi), _               THIS._lineColor      else         'no line to draw         exit sub      end if    elseif _      ( (THIS._p1)._x<>(THIS._p2)._x andAlso (THIS._p1)._y<>(THIS._p2)._y ) then      case4 = TRUE      dim as double   x1   => (THIS._p1)._x      dim as double   x2   => (THIS._p2)._x      dim as double   y1   => (THIS._p1)._y      dim as double   y2   => (THIS._p2)._y      'compute intersection with screen border      dim as POINT2D   i(1 to 4)      i(1)   => POINT2D(x1 - y1*(x2 - x1)/(y2 - y1), THIS.Yi, "y=yi")      i(2)   => POINT2D(x1 + (THIS.Yf - y1)*(x2 - x1)/(y2 - y1), THIS.Yf, "y=yf")      i(3)   => POINT2D(THIS.Xi, y1 - x1*(y2 - y1)/(x2 - x1), "x=xi")      i(4)   => POINT2D(THIS.Xf, y1 + (THIS.Xf - x1)*(y2 - y1)/(x2 - x1), "x=xf")      'decide what couple of point to join      dim as long   j(1 to 2)      for index as long = 1 to 4            j(1) => index            exit for      next index      for index as long = 1 to 4         if i( j(1) )._x<>i(index)._x orElse i( j(1) )._y<>i(index)._y then               j(2) => index               exit for         end if      next index      'draw line      line  THIS._imageBuffer, _             (i( j(1) )._x - THIS.Xi, i( j(1) )._y - THIS.Yi)- _            (i( j(2) )._x - THIS.Xi, i( j(2) )._y - THIS.Yi), _            THIS._lineColor   end ifend subsub BOXBIPOINTLINE.DrawLineWithPoint()   (THIS._p1).DrawPoint2D()   (THIS._p2).DrawPoint2D()   '   THIS.DrawLine()end subtype RUNOVER3DGRID   declare constructor()   declare destructor()   declare property MidW() as single   declare property MidH() as single   declare sub TestMouse()   declare sub DrawROv3dGrid()      as fb.IMAGE ptr         _imageBuffer      as BOX                  _boundaryBox      as single               _tileW      as single               _tileH      as double               _rE      as double               _aE      as double               _rA      as double               _aA      as single ptr           _xForwardPtr      as double               _xIA      as double               _yIA      as double               _zIA      as double               _xIB      as double               _yIB      as double               _zIB      as double               _alfa      as double               _beta      as double               _xHA      as double               _yHA      as double               _xHB      as double               _yHB      as BOXBIPOINTLINE       _horizon      as BOXBIPOINTLINE       _xAxis      as BOXBIPOINTLINE       _yAxis      as boolean              _hasMouseOver      as boolean              _hasMouseClicend typeconstructor RUNOVER3DGRID()   'default constructor   THIS._imageBuffer => imageCreate(THIS._boundaryBox.W, THIS._boundaryBox.H, 0, rgb(255,0,255)) end constructordestructor RUNOVER3DGRID()   'default constructor   imageDestroy   THIS._imageBuffer   THIS._imageBuffer = 0end destructorproperty RUNOVER3DGRID.MidW() as single   return THIS._boundaryBox.W/2end propertyproperty RUNOVER3DGRID.MidH() as single   return THIS._boundaryBox.H/2end propertysub RUNOVER3DGRID.TestMouse()   'end subsub RUNOVER3DGRID.DrawROv3dGrid()   THIS.TestMouse   '   line (THIS._boundaryBox.Xi, THIS._boundaryBox.Yi)-step(THIS._boundaryBox.W, THIS._boundaryBox.H), rgb(0,100,70), bf   color 0, rgba(20,100,20, 155)   '   'parameter of the intersection with the screen edges   ' *AE inter screen_plane* = IA   ' *BE inter screen_plane* = IB   dim as double   pA   => -THIS._rE*1/(THIS._rA*sin(THIS._aA)*cos(THIS._aE) + THIS._rE)   dim as double   pB   => -THIS._rE*1/(THIS._rA*cos(THIS._aA)*cos(THIS._aE) + THIS._rE)   THIS._xIA => 0000000000 - pA*( THIS._rA*cos(THIS._aA ) )   THIS._yIA => THIS._rE*cos(THIS._aE) - pA*( -THIS._rA*sin(THIS._aA) - THIS._rE*cos(THIS._aE))   THIS._zIA => THIS._rE*sin(THIS._aE)*(1 + pA)   THIS._xIB => 000000000 - pB*( -THIS._rA*sin(THIS._aA) )   THIS._yIB => THIS._rE*cos(THIS._aE) - pB*( -THIS._rA*cos(THIS._aA) - THIS._rE*cos(THIS._aE))   THIS._zIB => THIS._rE*sin(THIS._aE)*(1 + pB)/200           'screen plane grid main X,Y axis after rotation   THIS._alfa   => acos( THIS._xIA/(sqr( THIS._xIA^2 + THIS._yIA^2 + THIS._zIA^2 )) )   THIS._beta   => acos( THIS._xIB/(sqr( THIS._xIB^2 + THIS._yIB^2 + THIS._zIB^2 )) )   THIS._xHA    => THIS._rE*tan(THIS._aE)/tan(THIS._alfa)   THIS._yHA    => -THIS._rE*tan(THIS._aE)   THIS._xHB    => THIS._rE*tan(THIS._aE)/tan(THIS._beta)   THIS._yHB    => -THIS._rE*tan(THIS._aE)      THIS._horizon  => BOXBIPOINTLINE(THIS._imageBuffer, _                           THIS._boundaryBox, _                            type<POINT2D>(THIS._boundaryBox.Xi, THIS._boundaryBox.Yi + THIS._yHA + THIS.MidH,"h0"), _                           type<POINT2D>(THIS._boundaryBox.Xf,THIS._boundaryBox.Yi + THIS._yHA + THIS.MidH,"h1"), _                           rgb(100,190,120) )   'draw horizon line   THIS._horizon.DrawLineWithPoint()   THIS._xAxis   => BOXBIPOINTLINE(THIS._imageBuffer, _                            THIS._boundaryBox, _                            type<POINT2D>(THIS._boundaryBox.Xi + THIS.MidW,THIS._boundaryBox.Yi + THIS.MidH,"o"), _                           type<POINT2D>(THIS._xHA + THIS.MidW,THIS._boundaryBox.Yi + THIS._yHA + THIS.MidH,"HA"), _                            rgb(180,100,100))   'draw X axis rotated   THIS._xAxis.DrawLineWithPoint()   THIS._yAxis   => BOXBIPOINTLINE(THIS._imageBuffer, _                            THIS._boundaryBox, _                           type<POINT2D>(THIS._boundaryBox.Xi + THIS.MidW,THIS._boundaryBox.Yi + THIS.MidH,"o"), _                           type<POINT2D>(THIS._xHB + THIS.MidW,THIS._boundaryBox.Yi + THIS._yHB + THIS.MidH,"HB"), _                            rgb(100,100,180))   'draw Y axis rotated   THIS._yAxis.DrawLineWithPoint()#macro _X(n)   (0*THIS._boundaryBox.Xi + THIS._boundaryBox.W/2) + (sgn(n)*(12)*(1/2 - sgn(n)*n) + 8 - *THIS._xForwardPtr*sin(THIS._aA))#endMacro'horizontal grid line equation#macro _Y(n)   (0*THIS._boundaryBox.Yi + THIS._boundaryBox.H/2) + (sgn(n)*(12)*(1/2 - sgn(n)*n) + 8 - *THIS._xForwardPtr*cos(THIS._aA))#endMacro'rotation of vertical grid line#macro _XRV(n,t)   ((_X(n) - THIS._boundaryBox.W/2)*cos(_pi - THIS._aA) - (t)*sin(_pi - THIS._aA) + THIS._boundaryBox.Xi + THIS._boundaryBox.W/2)#endMacro#macro _YRV(n,t)   ((_X(n) - THIS._boundaryBox.W/2)*sin(_pi - THIS._aA) + (t)*cos(_pi - THIS._aA) + THIS._boundaryBox.Yi + THIS._boundaryBox.H/2)#endMacro'rotation of horizontal grid line#macro _XRH(n,t)   ((t)*cos(-THIS._aA) - (_Y(n) - THIS._boundaryBox.H/2)*sin(-THIS._aA)  +  THIS._boundaryBox.Xi + THIS._boundaryBox.W/2)#endMacro#macro _YRH(n,t)   ((t)*sin(-THIS._aA) + (_Y(n) - THIS._boundaryBox.H/2)*cos(-THIS._aA) + THIS._boundaryBox.Yi + THIS._boundaryBox.H/2)#endMacro   'display vertical point for n=0, t=100   (type<POINT2D>(_XRV(0,100), _YRV(0,100), "y0,2", rgb(0,0,220))).DrawPoint2D()   'display vertical point for n=0, t=200   (type<POINT2D>(_XRV(0,200), _YRV(0,200), "y0,2", rgb(0,0,220))).DrawPoint2D()   'display vertical line   (type<BOXBIPOINTLINE> _   (THIS._imageBuffer, THIS._boundaryBox, type<POINT2D>(_XRV(0,-100), _YRV(0,-100),""),type<POINT2D>(_XRV(0,200), _YRV(0,200),""), rgb(0,0,120))).DrawLine()   '   'display horizontal point for n=0, t=100   (type<POINT2D>(_XRH(0,100), _YRH(0,100), "hori0,1", rgb(190,0,0))).DrawPoint2D()   'display horizontal point for n=0, t=200   (type<POINT2D>(_XRH(0,200), _YRH(0,200), "x0,2", rgb(190,0,0))).DrawPoint2D()   'display horizontal line   (type<BOXBIPOINTLINE> _   (THIS._imageBuffer, THIS._boundaryBox, type<POINT2D>(_XRH(0,-100), _YRH(0,-100),""),type<POINT2D>(_XRH(0,200), _YRH(0,200),""), rgb(150,0,0))).DrawLine()   '   'angle check#macro _BIPOINTDIST(p1P2D,p2P2D)   sqr( (p2P2D._x - p1P2D._x)^2 + (p2P2D._y - p1P2D._y)^2 )#endMacro#macro _VECTANGLE(centerP2D,p1P2D,p2P2D)   acos( ( (p1P2D._x - centerP2D._x)*(p2P2D._x - centerP2D._x) + _                  (p1P2D._y - centerP2D._y)*(p2P2D._y - centerP2D._y) ) / _                  (_BIPOINTDIST(centerP2D,p1P2D)*_BIPOINTDIST(centerP2D,p2P2D)) )#endMacro   dim as POINT2D   boxCenter   boxCenter._x   => THIS.MidW   boxCenter._y   => THIS.MidH   dim as POINT2D   vert00   vert00._x      => _XRV(0,100)   vert00._y      => _YRV(0,100)   dim as POINT2D   hori00   hori00._x      => _XRH(0,100)   hori00._y      => _YRH(0,100)   dim as POINT2D   xAxisUnit   xAxisUnit._x   => THIS.MidW + 1   xAxisUnit._y   => THIS.MidH   '   'compute and store intersection of rotated grid line with X axis      #macro _RHX(n)      ( _XRH(n,0) + ( THIS.MidH - _YRH(n,0)) * ( _XRH(n,1) - _XRH(n,0) )/( _YRH(n,1) - _YRH(n,0) ) ) '+ loopstep   #endMacro   #macro _RVX(n)      ( _XRV(n,0) + ( THIS.MidH - _YRV(n,0)) * ( _XRV(n,1) - _XRV(n,0) )/( _YRV(n,1) - _YRV(n,0) ) ) '+ loopstep   #endMacro   '   'draw perspective grid   dim as POINT2D   xAxisHorizonPoint   xAxisHorizonPoint._x   => THIS._boundaryBox.Xi + THIS._xHA  + THIS.MidW   xAxisHorizonPoint._y   => THIS._boundaryBox.Yi + THIS._yHA  + THIS.MidH   dim as POINT2D   yAxisHorizonPoint   yAxisHorizonPoint._x   => THIS._boundaryBox.Xi + THIS._xHB  + THIS.MidW   yAxisHorizonPoint._y   => THIS._boundaryBox.Yi + THIS._yHB  + THIS.MidH   '   for n as long = -20 to 20 step 1      if n=0 then continue for      'horizontal line      (type<BOXBIPOINTLINE> _      (THIS._imageBuffer, THIS._boundaryBox, type<POINT2D>(_RHX(n), THIS._boundaryBox.Yi + THIS.MidH,"H"),xAxisHorizonPoint, rgb(100,150,200))).DrawLine()      'vertical line      (type<BOXBIPOINTLINE> _      (THIS._imageBuffer, THIS._boundaryBox, type<POINT2D>(_RVX(n*1.4) , THIS._boundaryBox.Yi + THIS.MidH,"V"),yAxisHorizonPoint, rgb(100,150,200))).DrawLine()   next n   '   line  THIS._imageBuffer, _          (0,0)- _          step(THIS._boundaryBox.W,THIS._boundaryBox.H), _          rgba(0,50,0,5), _          bf   'draw sky box   line  THIS._imageBuffer, _          (0,0)- _          step(THIS._boundaryBox.W, 0*THIS._yHA  + (100/95)*THIS.MidH), _          rgba(140,150,180,5), _          bf   '   'draw view center   circle THIS._imageBuffer, (THIS.MidW, THIS.MidH), 8, rgba(220,140,155,55), , , , fend sub'-------------------------------------------------------------------------------screenRes screenWidth, _          screenHeight, _          32, _          2, _           fb.GFX_ALPHA_PRIMITIVES + fb.GFX_HIGH_PRIORITYcolor rgb(0,200,0)SCREENTEST.TestScreen()'---------------------------------'observation point parameterdim as double   rE   => 400.dim as double   aE   => .275*_pi'source plane grid orientationdim as double   rA   => 100.dim as double   aA   => 225*_pi/180dim as single ptr    xForwardPtr => new single'RUNOVER3DGRID object initializationdim as RUNOVER3DGRID    ro3Dgdro3Dgd._xForwardPtr => xForwardPtrwith ro3Dgd   ._rE  = rE   ._aE  = aE   ._rA  = rA   ._aA  = aA   ._boundaryBox.Xi  = 300   ._boundaryBox.Yi  = 140   ._boundaryBox.W   = 300   ._boundaryBox.H   = 280   ._imageBuffer     = imageCreate(._boundaryBox.W, ._boundaryBox.H, 0, rgb(255,0,255))end with'---------------------------------main_loopdo   SCREENTEST.TestScreen()   INTERACTIONTEST.TestKeyboard()   if INTERACTIONTEST.scanCode = fb.SC_UP    then *xForwardPtr += 1   if INTERACTIONTEST.scanCode = fb.SC_DOWN  then *xForwardPtr -= 1   if INTERACTIONTEST.scanCode = fb.SC_LEFT  then aA += .01   if INTERACTIONTEST.scanCode = fb.SC_RIGHT then aA -= .01   if INTERACTIONTEST.scanCode = (fb.SC_UP +  fb.SC_LEFT) then      *xForwardPtr += 1      aA += .01   end if   if INTERACTIONTEST.scanCode = (fb.SC_UP +  fb.SC_RIGHT) then      *xForwardPtr += 1      aA -= .01   end if   if aE>(_pi/2)           then aE = _pi/2 - .001   if aE<(_pi/8)           then aE = _pi/8   if aA>(3*_pi/2 - 0.003) then aA = 3*_pi/2 - .003   if aA<(_pi)             then aA = _pi + .001   with ro3Dgd      ._rE  = rE      ._aE  = aE      ._rA  = rA      ._aA  = aA   end with      screenSet 0, 1      cls      ro3Dgd.DrawROv3dGrid()      put (ro3Dgd._boundaryBox.Xi,ro3Dgd._boundaryBox.Yi), ro3Dgd._imageBuffer, pset   screenCopy 0, 1   '   sleep 5loop until inkey=chr(27)delete xForwardPtrsleepend 0'(eof)`

There is a nice fading effect by the way. At least could be nice if used correctly.

Return to “Game Dev”

### Who is online

Users browsing this forum: No registered users and 9 guests