• Print

Author Topic: A Simple Exploration of _MAPTRIANGLE(3D) Perspective  (Read 103 times)

Richard Notley

  • Sr. Member
  • ****
  • Posts: 349
  • QwerKey
A Simple Exploration of _MAPTRIANGLE(3D) Perspective
« on: April 23, 2018, 10:29:32 am »
We saw in my Program "3D Bouncing Balls" (qv) the marvellous properties of _MAPTRIANGLE(3D), where quite simple code gives a very realistic representation of 3D effects.  It did appear, however, that the shape of the spherical balls was distorted when the balls were away from the centre of the screen.

The code here shows a simple display of  _MAPTRIANGLE(3D) perspective.  There are 5 views of the same pyramid.  The pyramid sits on a yellow square and points directly upwards to the viewer.

When the pyramid is at the screen centre (x- and y- are zero in the  _MAPTRIANGLE 3D space) the top of the pyramid is closer to the viewer than is the base, although it is not actually obvious because each of the 4 sides is geometrically the same.

However, when the pyramid moves away from the screen centre, the perspective changes the observed geometries of the faces, as it must, to give the 3D effect on the 2D screen.

This is exactly what was observed with the balls, where this effect gives rise to distortions as the sphere is no longer symmetrical.

What I would like to remark upon is the sheer brilliance of the  _MAPTRIANGLE(3D) QB64 construction - whoever implemented this must be in the genius category.

An inspection of the code here will show that for the different views I have not altered the order of the  _MAPTRIANGLE(3D) statements for the faces of the pyramids.  Yet the program somehow knows not to display the hidden face.  How on earth is that implemented when there is no actual code to say "this face is behind the others - do not display it"?

Richard


Code: [Select]
' Explore _MAPTRIANGLE perspective

CONST True = -1`, False = 0`
_TITLE "3D Bouncing Balls"
RANDOMIZE (TIMER)

CONST Uscreen% = 1000, Vscreen% = 800
CONST Pi! = 4 * ATN(1), PerspDist% = 550
'DIM MapConv%(NoPhis%%, NoAlphas%%, 1, 2)

''Conversion from 2D
'FOR N%% = 0 TO NoPhis%%
'    FOR M%% = 0 TO NoAlphas%%
'        MapConv%(N%%, M%%, 0, 0) = 128 + CINT(127 * SIN((Pi! / 2) - M%% * Alpha!) * COS(N%% * Phi!))
'        MapConv%(N%%, M%%, 0, 1) = 128 + CINT(127 * SIN((Pi! / 2) - M%% * Alpha!) * SIN(N%% * Phi!))
'        MapConv%(N%%, M%%, 1, 0) = CINT(Rad1%% * SIN((Pi! / 2) - M%% * Alpha!) * COS(N%% * Phi!))
'        MapConv%(N%%, M%%, 1, 1) = CINT(Rad1%% * SIN((Pi! / 2) - M%% * Alpha!) * SIN(N%% * Phi!))
'        MapConv%(N%%, M%%, 1, 2) = CINT(Rad1%% * COS((Pi! / 2) - M%% * Alpha!))
'    NEXT M%%
'NEXT N%%

'Screen Background
TempImage& = _NEWIMAGE(Uscreen%, Vscreen%, 32)
_DEST TempImage&
COLOR _RGB(255, 255, 255), _RGB(10, 60, 60)
CLS
FOR UCol% = 0 TO Uscreen% - 1
    FOR VCol% = 0 TO Vscreen% - 1
        PSET (UCol%, VCol%), _RGB(100, INT(180 * UCol% / Uscreen%), INT(180 * VCol% / Vscreen%))
    NEXT VCol%
NEXT UCol%
Background& = MakeHardware&(TempImage&)

'Square image
TempImage& = _NEWIMAGE(256, 256, 32)
_DEST TempImage&
COLOR _RGB(255, 255, 0), _RGB(255, 255, 0)
CLS
Square1& = MakeHardware&(TempImage&)
TempImage& = _NEWIMAGE(256, 256, 32)
_DEST TempImage&
COLOR _RGB(0, 255, 255), _RGB(0, 255, 255)
CLS
Square2A& = MakeHardware&(TempImage&)
TempImage& = _NEWIMAGE(256, 256, 32)
_DEST TempImage&
COLOR _RGB(0, 255, 255), _RGB(0, 225, 225)
CLS
Square2B& = MakeHardware&(TempImage&)
TempImage& = _NEWIMAGE(256, 256, 32)
_DEST TempImage&
COLOR _RGB(0, 255, 255), _RGB(0, 195, 195)
CLS
Square2C& = MakeHardware&(TempImage&)
TempImage& = _NEWIMAGE(256, 256, 32)
_DEST TempImage&
COLOR _RGB(0, 255, 255), _RGB(0, 165, 165)
CLS
Square2D& = MakeHardware&(TempImage&)

'Create screen
SCREEN _NEWIMAGE(Uscreen%, Vscreen%, 32)
_SCREENMOVE 50, 13
_DEST 0
_DISPLAYORDER _HARDWARE 'do not even render the software layer, just the hardware one.

Stereo` = True

WHILE Stereo`

    _LIMIT 120 'Game Frames/Second Rate

    Count% = Count% + 1

    _PUTIMAGE (0, 0), Background&

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square1& TO(-50, -50, -PerspDist%)-(50, -50, -PerspDist%)-(-50, 50, -PerspDist%)
    _MAPTRIANGLE (255, 255)-(0, 255)-(255, 0), Square1& TO(50, 50, -PerspDist%)-(-50, 50, -PerspDist%)-(50, -50, -PerspDist%)

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2A& TO(-40, -40, -PerspDist%)-(40, -40, -PerspDist%)-(0, 0, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2B& TO(40, -40, -PerspDist%)-(40, 40, -PerspDist%)-(0, 0, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2C& TO(40, 40, -PerspDist%)-(-40, 40, -PerspDist%)-(0, 0, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2D& TO(-40, 40, -PerspDist%)-(-40, -40, -PerspDist%)-(0, 0, 100 - PerspDist%)

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square1& TO(-50 + 400, -50, -PerspDist%)-(50 + 400, -50, -PerspDist%)-(-50 + 400, 50, -PerspDist%)
    _MAPTRIANGLE (255, 255)-(0, 255)-(255, 0), Square1& TO(50 + 400, 50, -PerspDist%)-(-50 + 400, 50, -PerspDist%)-(50 + 400, -50, -PerspDist%)

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2A& TO(-40 + 400, -40, -PerspDist%)-(40 + 400, -40, -PerspDist%)-(0 + 400, 0, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2B& TO(40 + 400, -40, -PerspDist%)-(40 + 400, 40, -PerspDist%)-(0 + 400, 0, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2C& TO(40 + 400, 40, -PerspDist%)-(-40 + 400, 40, -PerspDist%)-(0 + 400, 0, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2D& TO(-40 + 400, 40, -PerspDist%)-(-40 + 400, -40, -PerspDist%)-(0 + 400, 0, 100 - PerspDist%)

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square1& TO(-50 - 400, -50, -PerspDist%)-(50 - 400, -50, -PerspDist%)-(-50 - 400, 50, -PerspDist%)
    _MAPTRIANGLE (255, 255)-(0, 255)-(255, 0), Square1& TO(50 - 400, 50, -PerspDist%)-(-50 - 400, 50, -PerspDist%)-(50 - 400, -50, -PerspDist%)

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2A& TO(-40 - 400, -40, -PerspDist%)-(40 - 400, -40, -PerspDist%)-(0 - 400, 0, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2B& TO(40 - 400, -40, -PerspDist%)-(40 - 400, 40, -PerspDist%)-(0 - 400, 0, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2C& TO(40 - 400, 40, -PerspDist%)-(-40 - 400, 40, -PerspDist%)-(0 - 400, 0, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2D& TO(-40 - 400, 40, -PerspDist%)-(-40 - 400, -40, -PerspDist%)-(0 - 400, 0, 100 - PerspDist%)

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square1& TO(-50, -50 + 300, -PerspDist%)-(50, -50 + 300, -PerspDist%)-(-50, 50 + 300, -PerspDist%)
    _MAPTRIANGLE (255, 255)-(0, 255)-(255, 0), Square1& TO(50, 50 + 300, -PerspDist%)-(-50, 50 + 300, -PerspDist%)-(50, -50 + 300, -PerspDist%)

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2A& TO(-40, -40 + 300, -PerspDist%)-(40, -40 + 300, -PerspDist%)-(0, 0 + 300, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2B& TO(40, -40 + 300, -PerspDist%)-(40, 40 + 300, -PerspDist%)-(0, 0 + 300, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2C& TO(40, 40 + 300, -PerspDist%)-(-40, 40 + 300, -PerspDist%)-(0, 0 + 300, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2D& TO(-40, 40 + 300, -PerspDist%)-(-40, -40 + 300, -PerspDist%)-(0, 0 + 300, 100 - PerspDist%)

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square1& TO(-50, -50 - 300, -PerspDist%)-(50, -50 - 300, -PerspDist%)-(-50, 50 - 300, -PerspDist%)
    _MAPTRIANGLE (255, 255)-(0, 255)-(255, 0), Square1& TO(50, 50 - 300, -PerspDist%)-(-50, 50 - 300, -PerspDist%)-(50, -50 - 300, -PerspDist%)

    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2A& TO(-40, -40 - 300, -PerspDist%)-(40, -40 - 300, -PerspDist%)-(0, 0 - 300, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2B& TO(40, -40 - 300, -PerspDist%)-(40, 40 - 300, -PerspDist%)-(0, 0 - 300, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2C& TO(40, 40 - 300, -PerspDist%)-(-40, 40 - 300, -PerspDist%)-(0, 0 - 300, 100 - PerspDist%)
    _MAPTRIANGLE (0, 0)-(255, 0)-(0, 255), Square2D& TO(-40, 40 - 300, -PerspDist%)-(-40, -40 - 300, -PerspDist%)-(0, 0 - 300, 100 - PerspDist%)


    IF _KEYHIT = 27 THEN Stereo` = False 'Esc  to quit

    _DISPLAY

WEND

SYSTEM

FUNCTION MakeHardware& (Imagename&)
    MakeHardware& = _COPYIMAGE(Imagename&, 33)
    _FREEIMAGE Imagename&
END FUNCTION

QB64 Projects: https://www.dropbox.com/s/yzn5uf4dzztao2f/QB64%20Projects.pdf?dl=0

Petr

  • Hero Member
  • *****
  • Posts: 656
Re: A Simple Exploration of _MAPTRIANGLE(3D) Perspective
« Reply #1 on: April 23, 2018, 12:51:31 pm »
Quote
How on earth is that implemented when there is no actual code to say "this face is behind the others - do not display it"?

Maybe using parameter _CLOCKWISE and _ANTICLOCKWISE?
Thank you for sharing, 3D with MAPTRIANGLE interest me.
Coding is relax.

Richard Notley

  • Sr. Member
  • ****
  • Posts: 349
  • QwerKey
Re: A Simple Exploration of _MAPTRIANGLE(3D) Perspective
« Reply #2 on: April 24, 2018, 06:16:41 am »
Petr, none of the _MAPTRIANGLE statements in the code here have any additional arguments (and certainly neither _CLOCKWISE nor _ANTICLOCKWISE).  I have never tried _CLOCKWISE or _ANTICLOCKWISE, as they remain a mystery to me - what exactly is going clockwise or anticlockwise in a static triangle??.  So, I remain mystified as to how the software knows not put the image of the backward-facing pyramid faces.  If the equivalent _PUTIMAGE statements were used, all faces would show.

I believe that Ashish is preparing a tutorial (somewhere or other) on coding in 3D.  We shall all benefit from that, I trust.

Richard
QB64 Projects: https://www.dropbox.com/s/yzn5uf4dzztao2f/QB64%20Projects.pdf?dl=0

  • Print