Qbasicnews.com
April 09, 2020, 06:47:55 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: Back to Qbasicnews.com | QB Online Help | FAQ | Chat | All Basic Code | QB Knowledge Base
 
   Home   Help Search Login Register  
Pages: [1]
  Print  
Author Topic: solid faces on a 3d objefct  (Read 1392 times)
andy
Senior Member
**
Posts: 175



WWW
« on: January 22, 2004, 10:18:30 AM »

I have written a program to rotate a cube about anyone of its axis at a time. using matrices, I can't remember them perfectly but the one below is about wright.

xnew = ((x - 160) * sin(alpha)) + ((z- 100) * cos(alpha)) + 160

Using these type of formulae, how can I make the sides of say a cube for now solid.
Logged

eminiscing about trapezoids in conjunction with stratospherical parabolas:

No questions asked.

www.stickskate.com
Z!re
*/-\*
*****
Posts: 4599


« Reply #1 on: January 22, 2004, 10:53:34 AM »

A 3d Tutorial: http://www.sbdev.pwp.blueyonder.co.uk/intro.htm

I used a polygon filler, ie, i divided the box into triangle, a square made out by 2 triangles. Then filled each triangle.

But to get it good you must do Z-Order sorting, or some sort of other sorting, you don't want the back side of the cube to show up over the front do you  :wink:
Logged
andy
Senior Member
**
Posts: 175



WWW
« Reply #2 on: January 22, 2004, 06:43:01 PM »

Thanks, I have saved these files and I will read them soon
Logged

eminiscing about trapezoids in conjunction with stratospherical parabolas:

No questions asked.

www.stickskate.com
mark woods
New Member

Posts: 9


« Reply #3 on: January 25, 2004, 08:08:09 AM »

I had to do this a while back: I used the following "scan line algorithm"

To fill the polygon with a gradient of colour, first you must split the polygon into triangles.  You do this by drawing a horizontal line from the intercept of the adjacent and opposite, to the hypotonus

The reason you do this is because the following fill algorithm does not work with a triangle that hasn't got a horizontal side.

You then take both of the triangles in turn and sort the there points from highest to lowest.  

Then create a loop that goes from the top point of the triangle to the bottom point

e.g  
Y = TopPoint.Y
DO
REM fill code
Y = Y +1
LOOP UNTIL Y = BottomPoint.Y  

For each value of y you want to draw a line between the triangle edge on your left and the triangle edge on your right.  

If I remember correctly you then linear interpolate using (Difference between top Y and bottom Y) - Y as the parameter to find X.

If you do this for the left edge and the right edge you will find the X for the start and end pixel of the scan line.  You just fill in the gap between the two.



To fill with a gradient of colour

Each triangle vertex is assigned a colour.  You then go through each colour on the scan line.  To find what colour you need to plot the pixel you do a bi-linear interpolation on the colour of three vertices.

Filling with a Texture

Texturing is very similar to filling with colour. Istead of doing a bi-linear interpolation between three colour values you do it between three UV values that correspond to a texture.

Z-buffer or depth buffer

you use the same technique again.  Each has vertex has a Z co-ordinate.  You do another bi-linear interpolation between the three Z values so each pixel has a Z value.  You then check with the Z-buffer to see if a pixel has been plotted there. If it has and its Z value is closer to the camera, don't plot the pixel.  Otherwise plot it.


This is obviously a very rushed explanation.  The things you really need to understand to do this is are  linear and bi-linear interpolation.  

Hope this helps

Mark
Logged
relsoft
*/-\*
*****
Posts: 3927



WWW
« Reply #4 on: January 26, 2004, 03:37:18 AM »

Use PAINT and I'm not kidding.

Code:


'''SetvideoSeg by Plasma357
'''Rel.betterwebber.com


DECLARE SUB DrawModelHIDEFace (Model() AS ANY, Tri() AS ANY)
DECLARE SUB DrawModelFill (Model() AS ANY, Tri() AS ANY)
DECLARE SUB DrawModel (Model() AS ANY, Tri() AS ANY)
DECLARE SUB SetVideoSeg (Segment%)
DECLARE SUB RotateAndProject (Model() AS ANY, AngleX%, AngleY%, AngleZ%)
DECLARE SUB LoadCube (Model() AS ANY, Tri() AS ANY, Scale!)

DEFINT A-Z
REM $DYNAMIC



TYPE Point3d
        x       AS SINGLE                   'Normal 3d coords
        y       AS SINGLE
        z       AS SINGLE
        xr      AS SINGLE                   'Rotated  3d coords
        yr      AS SINGLE
        zr      AS SINGLE
        scrx    AS INTEGER                  'Translated and projected
        scry    AS INTEGER                  '2d Coords
END TYPE

TYPE PolyType
        p1      AS INTEGER                  'vertex 1
        p2      AS INTEGER
        p3      AS INTEGER
        clr     AS INTEGER                  'color
        idx     AS INTEGER                  'index for later use
END TYPE


CONST FALSE = 0, TRUE = NOT FALSE

CONST LENS = 256                            'Z
CONST XCENTER = 160                         '??
CONST YCENTER = 100                         '??

CONST PI = 3.14151693#

REDIM SHARED Vpage(32009)  AS INTEGER           'our Video buffer

'Polyhedra stuff
REDIM SHARED Model(1) AS Point3d               '3d  Coords
REDIM SHARED CubePoly(1) AS PolyType           '12 faces/Polys
DIM SHARED Thetax, Thetay, Thetaz              'Angle of rotation
DIM SHARED camx%, camy%, camz%                 'camera


CLS
SCREEN 0
WIDTH 80


'Initialize 3d model

LoadCube Model(), CubePoly(), 1

RendMode = 0

LOCATE 1, 1
PRINT "Choose Render Type:"
PRINT
PRINT "1. WireFrame"
PRINT "2. WireFrame + BackFace Culling"
PRINT "3. Filled"

K$ = INPUT$(1)
SELECT CASE ASC(K$)
        CASE 49
            RendMode = 0        'Wireframe
        CASE 50
            RendMode = 1        'Back face culled
        CASE 51
            RendMode = 2        'Filled
        CASE ELSE
            RendMode = 0
END SELECT

CLS
SCREEN 13
RANDOMIZE TIMER

camx% = 0
camy% = 0
camz% = 0

Thetax = INT(RND * 360)
Thetay = INT(RND * 360)
Thetaz = INT(RND * 360)

Vpage(6) = 2560                 'GET/PUT stuuff
Vpage(7) = 200
Layer = VARSEG(Vpage(0)) + 1    'Easy buffer reference
SetVideoSeg Layer               'Set Draw to buffer
Finished = 0

DO

     K$ = INKEY$
     SELECT CASE UCASE$(K$)             'Camera control
        CASE "A"
            camz% = camz% + 1
        CASE "Z"
            camz% = camz% - 1
        CASE "S"
            camy% = camy% + 1
        CASE "X"
            camy% = camy% - 1
        CASE "D"
            camx% = camx% + 1
        CASE "C"
            camx% = camx% - 1
    END SELECT
           

     Thetax = (Thetax + 1) MOD 360          'rotate our angles
     Thetay = (Thetay + 1) MOD 360
     Thetaz = (Thetaz + 1) MOD 360
     RotateAndProject Model(), Thetax, Thetay, Thetaz  '12 muls
     SetVideoSeg Layer              'set draw to Buffer
     LINE (0, 0)-(319, 199), 0, BF  'CLS
     SELECT CASE RendMode
        CASE 0
            DrawModel Model(), CubePoly()      'WireFrame
        CASE 1
            DrawModelHIDEFace Model(), CubePoly()      'Wire with BF culling
        CASE 2
            DrawModelFill Model(), CubePoly()      'Filled
        CASE ELSE
     END SELECT
     SetVideoSeg &HA000             'Set Draw to buffer
     WAIT &H3DA, 8                  'Vsynch
     PUT (0, 0), Vpage(6), PSET     'Blit

LOOP UNTIL K$ = CHR$(27)


CLS
SCREEN 0
WIDTH 80

END

'vertices of Cube
CUBEDATA:

DATA  50, 50, 50            : 'x,y,z
DATA -50, 50, 50
DATA -50,-50, 50
DATA  50,-50, 50
DATA  50, 50,-50
DATA -50, 50,-50
DATA -50,-50,-50
DATA  50,-50,-50

'Faces/Poly in 4 point form
CUBECONNECT:
DATA 0, 1, 2, 3
DATA 1, 5, 6, 2
DATA 5, 4, 7, 6
DATA 4, 0, 3, 7
DATA 4, 5, 1, 0
DATA 3, 2, 6, 7

REM $STATIC
SUB DrawModel (Model() AS Point3d, Tri() AS PolyType) STATIC

FOR I = 0 TO UBOUND(Tri)
    j = Tri(I).idx
    x1 = Model(Tri(j).p1).scrx       'Get triangles from "projected"
    x2 = Model(Tri(j).p2).scrx       'X and Y coords since Znormal
    X3 = Model(Tri(j).p3).scrx       'Does not require a Z coord
    y1 = Model(Tri(j).p1).scry       'V1= Point1 connected to V2 then
    y2 = Model(Tri(j).p2).scry       'V2 to V3 and so on...
    Y3 = Model(Tri(j).p3).scry

    LINE (x1, y1)-(x2, y2), Tri(j).clr
    LINE -(X3, Y3), Tri(j).clr
    LINE -(x1, y1), Tri(j).clr
NEXT I



END SUB

SUB DrawModelFill (Model() AS Point3d, Tri() AS PolyType) STATIC

''Draws our cube hiding the faces
FOR I = 0 TO UBOUND(Tri)
    j = Tri(I).idx
    x1 = Model(Tri(j).p1).scrx       'Get triangles from "projected"
    x2 = Model(Tri(j).p2).scrx       'X and Y coords since Znormal
    X3 = Model(Tri(j).p3).scrx       'Does not require a Z coord
    y1 = Model(Tri(j).p1).scry       'V1= Point1 connected to V2 then
    y2 = Model(Tri(j).p2).scry       'V2 to V3 and so on...
    Y3 = Model(Tri(j).p3).scry
    Znormal = (x2 - x1) * (y1 - Y3) - (y2 - y1) * (x1 - X3)
    IF (Znormal < -256) THEN              '<-256 so vector facing us
                                        'cuz our z component is not
                                        'normalized and paint would sometimes
                                        'fail ;*)
        LINE (x1, y1)-(x2, y2), Tri(j).clr
        LINE -(X3, Y3), Tri(j).clr
        LINE -(x1, y1), Tri(j).clr
        xcen = (x1 + x2 + X3) \ 3
        ycen = (y1 + y2 + Y3) \ 3
        PAINT (xcen, ycen), Tri(j).clr
    END IF
NEXT I



END SUB

SUB DrawModelHIDEFace (Model() AS Point3d, Tri() AS PolyType) STATIC
''Draws our cube hiding the faces
FOR I = 0 TO UBOUND(Tri)
    j = Tri(I).idx
    x1 = Model(Tri(j).p1).scrx       'Get triangles from "projected"
    x2 = Model(Tri(j).p2).scrx       'X and Y coords since Znormal
    X3 = Model(Tri(j).p3).scrx       'Does not require a Z coord
    y1 = Model(Tri(j).p1).scry       'V1= Point1 connected to V2 then
    y2 = Model(Tri(j).p2).scry       'V2 to V3 and so on...
    Y3 = Model(Tri(j).p3).scry
    Znormal = (x2 - x1) * (y1 - Y3) - (y2 - y1) * (x1 - X3)
    IF (Znormal < 0) THEN               '<0 so vector facing us
        LINE (x1, y1)-(x2, y2), Tri(j).clr
        LINE -(X3, Y3), Tri(j).clr
        LINE -(x1, y1), Tri(j).clr
    END IF
NEXT I




END SUB

SUB LoadCube (Model() AS Point3d, Tri() AS PolyType, Scale!)
REDIM Model(7) AS Point3d   '8 vertices
RESTORE CUBEDATA
FOR I = 0 TO 7
    READ x, y, z
    Model(I).x = x * Scale!     'scale it according to
    Model(I).y = y * Scale!     'the parameter
    Model(I).z = z * Scale!
NEXT I

REDIM Tri(11) AS PolyType
j = 0
FOR I = 0 TO 5
    READ p1, p2, p3, p4
    Tri(j).p1 = p4
    Tri(j).p2 = p2
    Tri(j).p3 = p1
    Tri(j).idx = j
    Tri(j).clr = 20 + INT(RND * 128)
    j = j + 1
    Tri(j).p1 = p4
    Tri(j).p2 = p3
    Tri(j).p3 = p2
    Tri(j).idx = j
    Tri(j).clr = 20 + INT(RND * 128)
    j = j + 1
NEXT I

END SUB

SUB RotateAndProject (Model() AS Point3d, AngleX, AngleY, AngleZ) STATIC
''Right handed system
''when camera components increase:
''x=goes left
''y=goes down
''z=goes into the screen

' so when increased:
'x =right
'y=up
'z=into you

'          y
'         |
'         |
'         |
'         0-- -- -- 
'        /        x
'      /
'    /  z
'  \/

'''rotation: counter-clockwise of each axis
''ei.  make yourself perpenicular to the axis
''wave your hand from the center of your body to the left.
''That's how it rotates. ;*)


'convert degrees to radians
ax! = AngleX * PI / 180
ay! = AngleY * PI / 180
az! = AngleZ * PI / 180

'Precalculate the SIN and COS of each angle
cx! = COS(ax!)
sx! = SIN(ax!)
cy! = COS(ay!)
sy! = SIN(ay!)
cz! = COS(az!)
sz! = SIN(az!)

'''After2 hours of work, I was able to weed out the constants from
'''Rotate and project N to reduce my muls to 9 instead of 12. woot!!!!

xx! = cy! * cz!
xy! = sx! * sy! * cz! - cx! * sz!
xz! = cx! * sy! * cz! + sx! * sz!

yx! = cy! * sz!
yy! = cx! * cz! + sx! * sy! * sz!
yz! = -sx! * cz! + cx! * sy! * sz!

zx! = -sy!
zy! = sx! * cy!
zz! = cx! * cy!

FOR I = 0 TO UBOUND(Model)

        x! = Model(I).x
        y! = Model(I).y
        z! = Model(I).z

        RotX! = (x! * xx! + y! * xy! + z! * xz!) - camx%
        RotY! = (x! * yx! + y! * yy! + z! * yz!) - camy%
        RotZ! = (x! * zx! + y! * zy! + z! * zz!) - camz%

        Model(I).xr = RotX!
        Model(I).yr = RotY!
        Model(I).zr = RotZ!

        'Project
        Distance% = (LENS - RotZ!)
        IF Distance% > 0 THEN
            Model(I).scrx = (LENS * RotX! / Distance%) + XCENTER
            Model(I).scry = -(LENS * RotY! / Distance%) + YCENTER
        ELSE
        END IF
NEXT I

END SUB

SUB SetVideoSeg (Segment) STATIC
'By Plasma 357 (Jon Petrosky)

DEF SEG

IF VideoAddrOff& = 0 THEN ' First time the sub is called

' We need to find the location of b$AddrC, which holds the graphics
' offset (b$OffC) and segment (b$SegC). Since b$AddrC is in the default
' segment, we can find it by setting it to a certain value, and then
' searching for that value.

SCREEN 13 ' Set b$SegC to A000 (00A0 in memory)
PSET (160, 100), 0 ' Set b$OffC to 7DA0 (not needed in the IDE)

FOR Offset& = 0 TO 32764 ' Search for b$AddrC, which is
IF PEEK(Offset&) = &HA0 THEN ' in the default segment and
IF PEEK(Offset& + 1) = &H7D THEN ' should have a value of
IF PEEK(Offset& + 2) = &H0 THEN ' A0 7D 00 A0.
IF PEEK(Offset& + 3) = &HA0 THEN
VideoAddrOff& = Offset& + 2 ' If we found it, record the
EXIT FOR ' offset of b$SegC and quit
END IF ' looking. (Oddly, changing
END IF ' the b$OffC doesn't seem to
END IF ' do anything, so this is why
END IF ' this sub only changes b$SegC)
NEXT

END IF

' Change b$SegC to the specified Segment

POKE VideoAddrOff&, Segment AND &HFF
POKE VideoAddrOff& + 1, (Segment AND &HFF00&) \ &H100



END SUB




Hey, just a teaser for you.  Read QBCM monthly from next month.  I'll be starting a 3d series. :*)
 Cheesy
Logged

y smiley is 24 bit.


Genso's Junkyard:
http://rel.betterwebber.com/
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!