Possible line bug?

General FreeBASIC programming questions.
Post Reply
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Possible line bug?

Post by relsoft »

Are you seeing pixels on the lines? I made this for a guy who requested via email and found out that somehow the lines have pixels in between them. Use the arrow keys to rotate. :*)


Code: Select all

'rotation demo
'use FreeBASIC
'FreeBASIC.net

DEFINT A-Z
REM $DYNAMIC

TYPE Point3D
        X       AS SINGLE                   'Normal 3d coords
        Y       AS SINGLE
        Z       AS SINGLE
        Xr      AS SINGLE
        Yr      AS SINGLE
        Zr      AS SINGLE
        ScrX    AS INTEGER                  'Translated and projected
        ScrY    AS INTEGER                  '2d Coords
END TYPE

TYPE VectorType
        V1      AS INTEGER
        V2      AS INTEGER
        V3      AS INTEGER
        Clr     AS INTEGER
END TYPE

DECLARE SUB LoadCube (Model() AS Point3D, Vector() AS VectorType)
DECLARE SUB RotateAndProject (Model() AS Point3D, AngleX%, AngleY%, AngleZ%)
DECLARE SUB DrawCube (Model() AS Point3D, Vector() AS VectorType) 


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


CONST PI = 3.14151693#

REDIM SHARED CubeModel(1) AS Point3D
REDIM SHARED CubeVector(1) AS VectorType
DIM SHARED MaxVertex, MaxVector
DIM SHARED ThetaX, ThetaY, ThetaZ
DIM SHARED Zcenter, CamX, CamY


LoadCube CubeModel(), CubeVector()

CLS
SCREEN 13,8,2
RANDOMIZE TIMER

ThetaX = 0
ThetaY = 0
ThetaZ = 0
Zcenter = LENS
CamX = 0
CamY = 0
Camdir = -4


DO

     SCREENSET 1, 0
     CLS
     'ThetaX = (ThetaX + 1) MOD 360
     'ThetaY = (ThetaY + 1) MOD 360
     'ThetaZ = (ThetaZ + 1) MOD 360
     if MULTIKEY(&h4B) then ThetaY = (ThetaY - 1)
     if MULTIKEY(&h4D) then ThetaY = (ThetaY + 1)

     if MULTIKEY(&h48) then ThetaX = (ThetaX - 1)
     if MULTIKEY(&h50) then ThetaX = (ThetaX + 1)

     RotateAndProject CubeModel(), ThetaX, ThetaY, ThetaZ

     DrawCube CubeModel(), CubeVector()
     sleep 1
     screensync
     SCREENCOPY
     
LOOP WHILE NOT MULTIKEY(&h1)



END

'numPoints
NumPoints:
DATA 8


'vertices of Cube
VertexData:
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
DATA -50, 50, 50
     
NumVector:
DATA 12
'Vector Connect data
ConnectData:
DATA 5,1,8
DATA 1,4,8
DATA 6,5,7
DATA 5,8,7
DATA 2,6,3
DATA 6,7,3
DATA 1,2,4
DATA 2,3,4
DATA 4,3,8
DATA 3,7,8
DATA 5,6,1
DATA 6,2,1

REM $STATIC
SUB DrawCube (Model() AS Point3D, Vector() AS VectorType) STATIC

    REDIM RotPoints(1 TO MaxVertex, 1 TO 3)
    REDIM ConPoints(1 TO MaxVector, 1 TO 3)
    
    FOR I = 1 TO MaxVertex
        RotPoints(I, 1) = Model(I).ScrX
        RotPoints(I, 2) = Model(I).ScrY
        RotPoints(I, 3) = Model(I).Zr
    NEXT I
    
    FOR I = 1 TO MaxVector
        ConPoints(I, 1) = Vector(I).V1
        ConPoints(I, 2) = Vector(I).V2
        ConPoints(I, 3) = Vector(I).V3
    NEXT I
    
    FOR I = 1 TO MaxVector
        x1 = RotPoints(Vector(I).V1, 1)
        x2 = RotPoints(Vector(I).V2, 1)
        x3 = RotPoints(Vector(I).V3, 1)
        y1 = RotPoints(Vector(I).V1, 2)
        y2 = RotPoints(Vector(I).V2, 2)
        y3 = RotPoints(Vector(I).V3, 2)
        Z1 = RotPoints(Vector(I).V1, 3)
        Z2 = RotPoints(Vector(I).V2, 3)
        Z3 = RotPoints(Vector(I).V3, 3)
    
        Visible = (x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1)
                  
        'IF Visible < 0 THEN                     ' To see the INSIDE, do "Visible > 256" :)
                LINE (x1, y1)-(x2, y2), Vector(I).Clr
                LINE (x2, y2)-(x3, y3), Vector(I).Clr
                LINE (x3, y3)-(x1, y1), Vector(I).Clr
        'END IF
    
    NEXT I
    
    

END SUB

SUB LoadCube (Model() AS Point3D, Vector() AS VectorType) STATIC

    RESTORE NumPoints
    READ MaxVertex
    REDIM Model(1 TO MaxVertex) AS Point3D
    
    
    RESTORE VertexData
    FOR V = 1 TO MaxVertex
        READ Xt, Yt, Zt
        Model(V).X = Xt
        Model(V).Y = Yt
        Model(V).Z = Zt
    NEXT V
    
    RESTORE NumVector
    READ MaxVector
    REDIM Vector(MaxVector) AS VectorType
    
    RESTORE ConnectData
    
    FOR V = 1 TO MaxVector
            READ VT1, VT2, VT3
            Vector(V).V1 = VT1
            Vector(V).V2 = VT2
            Vector(V).V3 = VT3
            Vector(V).Clr = 50 + INT(RND * 100)
    NEXT V
    



END SUB

SUB RotateAndProject (Model() AS Point3D, AngleX, AngleY, AngleZ) STATIC

    
    
    dim as single angx, angy, angz
    'convert degrees to radians
    angx = anglex * PI/180
    angy = angley * PI/180
    angz = anglez * PI/180
    
    CX! = COS(AngX)
    SX! = SIN(AngX)
    CY! = COS(AngY)
    SY! = SIN(AngY)
    CZ! = COS(AngZ)
    SZ! = SIN(AngZ)
    
    'Transformation matrix formula
    'This is actually 16(or 12) equations but I pared it down to 9
    'since TX4=0,TY4=0,TZ4=0,13 to 16th =0,0,0,1 (yes Doom!!!)
    
    TX1! = CY! * CZ!
    TX2! = CY! * SZ!
    TX3! = -SY!
    TY1! = CX! * -SZ! + SX! * SY! * CZ!
    TY2! = CX! * CZ! + SX! * SY! * SZ!
    TY3! = SX! * CY!
    TZ1! = -SX! * -SZ! + CX! * SY! * CZ!
    TZ2! = -SX! * CZ! + CZ! * SY! * SZ!
    TZ3! = CX! * CY!
    
    
    FOR I = 1 TO UBOUND(Model)
    
            X! = Model(I).X       'Load Original model
            Y! = Model(I).Y
            Z! = Model(I).Z
    
            RotX! = (X! * TX1! + Y! * TY1! + Z! * TZ1!)
            RotY! = (X! * TX2! + Y! * TY2! + Z! * TZ2!)
            RotZ! = (X! * TX3! + Y! * TY3! + Z! * TZ3!)
    
            Model(I).Xr = RotX!
            Model(I).Yr = RotY!
            Model(I).Zr = RotZ!
    
    
            'Project
            Distance% = (LENS - RotZ!)
            IF Distance% THEN
                Model(I).ScrX = (Zcenter * RotX! / Distance%) + XCENTER + CamX
                Model(I).ScrY = -(Zcenter * RotY! / Distance%) + YCENTER + CamY
            ELSE
            END IF
    NEXT I

END SUB
voodooattack
Posts: 605
Joined: Feb 18, 2006 13:30
Location: Alexandria / Egypt
Contact:

Post by voodooattack »

hmm yeah.. i can see weird pixel distortion along the lines.. strange...

however if you leave a single LINE statement from the code below and comment the rest, it simply disappears..

Code: Select all

                'LINE (x1, y1)-(x2, y2), Vector(I).Clr
                'LINE (x2, y2)-(x3, y3), Vector(I).Clr
                LINE (x3, y3)-(x1, y1), Vector(I).Clr
redcrab
Posts: 623
Joined: Feb 07, 2006 15:29
Location: France / Luxemburg
Contact:

Post by redcrab »

It's not a bug from line
if you modify your code as

Code: Select all

                LINE (x1, y1)-(x2, y2),10 ' Vector(I).Clr
                LINE (x2, y2)-(x3, y3),10 'Vector(I).Clr
                LINE (x3, y3)-(x1, y1),10 'Vector(I).Clr
then no bad dots appear

You currently using triangles ...
all cube edge are drawned twice in different color ...
if you have (P1,P2) a line
you draw it as from p1 to P2 and P2 to P1 in different color.
Bresenham algo make different "scale" if you draw line between P1 to P2 and P2 to P1 (the scale do not use always the same pixels between "go" and "return" drawing)

so it's normal !

resolve it by 2 ways :
1) make line between P1 to P2 never P2 to P1 whatever the triangle is
or
2) never draw a line twice !

Have fun !
Last edited by redcrab on May 04, 2006 14:22, edited 1 time in total.
redcrab
Posts: 623
Joined: Feb 07, 2006 15:29
Location: France / Luxemburg
Contact:

Post by redcrab »

Here a example to show the effects

Code: Select all

screen 13,8,1
cls
randomize timer
for i = 1 to 100
    x1 = int(rnd*320)
    y1 = int(rnd*200)
    x2 = int(rnd*320)
    y2 = int (rnd*200)

' GO LINE in RED 
' LINE from P1 to P2
    line (x1,y1)-(x2,y2),12

'RETURN LINE in GREEN
' LINE FROM P2 to P1
    line (x2,y2)-(x1,y1),10
next i
sleep
You can see that some red dots still there...

there is no error....

it's a math stuff when you do egyptian division (used in bresenham algo)
so it's normal

BTW: did you already seen these kind of error in Opengl ... the frontier between two independant surface are sometime broken due to Go/return bresenham effect ...
I already saw some of these in some proggies


Have fun !
redcrab
Posts: 623
Joined: Feb 07, 2006 15:29
Location: France / Luxemburg
Contact:

Post by redcrab »

here a proposal fix ! It's work !

replace the 3 LINE statements with the following code

this solution use my first proposition :
when drawing line from P1 to P2 never draw P2 to P1

Code: Select all

            if x1 < x2 then
                LINE (x1, y1)-(x2, y2), Vector(I).Clr
            else
                LINE (x2, y2)-(x1, y1), Vector(I).Clr
            end if
            if x2 < x3 then
                LINE (x2, y2)-(x3, y3), Vector(I).Clr
            else
                LINE (x3, y3)-(x2, y2), Vector(I).Clr
            end if
            if x3 < x1 then
                LINE (x3, y3)-(x1, y1), Vector(I).Clr
            else
                LINE (x1, y1)-(x3, y3), Vector(I).Clr
            end if

Have fun !
Last edited by redcrab on May 04, 2006 14:55, edited 1 time in total.
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Post by relsoft »

Ic. I just whipped that code out for a guy needing some rotation explanations.

Thanks!
cha0s
Site Admin
Posts: 5319
Joined: May 27, 2005 6:42
Location: USA
Contact:

Post by cha0s »

Rel please. Don't whip it out in public.
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Post by relsoft »

cha0s wrote:Rel please. Don't whip it out in public.
Well. It's not you. But if you want to get whipped... ;*)

*takes whip....

whap!!!!
redcrab
Posts: 623
Joined: Feb 07, 2006 15:29
Location: France / Luxemburg
Contact:

Post by redcrab »

relsoft wrote:
cha0s wrote:Rel please. Don't whip it out in public.
Well. It's not you. But if you want to get whipped... ;*)

*takes whip....

whap!!!!

tss tss tss tss ... please move to off-topic please ;D
anyway whipped code never hurt =8D

Have fun !
Post Reply