Dark Bit Factory & Gravity

PROGRAMMING => Freebasic => Topic started by: Shockwave on August 17, 2006

Title: Use your imagination here..
Post by: Shockwave on August 17, 2006
Here is a technique which is quite cool. Here's how it works.
Let's say that you have four corners of a square..

;D :) :) :) ;D
:) :) :) :) :)
:) :) :) :) :)
:) :) :) :) :)
;D :) :) :) ;D

And you wanted to make it more detailed I figured that you could just divide the opposite corners like;

centrex = (x1+x2) / 2
centrey = (y1+y2) / 2

And easily get this;

;D :) ;D :) ;D
:) :) :) :) :)
;D :) :) :) ;D
:) :) :) :) :)
;D :) ;D :) ;D

From the four original points. I figured that this technique would be quite useful for making low overhead dot cubes, it would be possible to make a cube out of the 8 corner points and recursively subdivide the points to make the cube as detailed as you wanted but only ever having to rotate the original 8 corner points.

Then I thought that wasn't even the best way of doing it so I decided to interpolate, almost as if I was writing a texture mapping routine and I've got the listing below so far.. I am going to apply it to some 3D models in my next intro and do some transformations and other stuff to them.

First and unoptimised test;


'
' This technique is going to form the basis for a demo effect.
' Basically it uses an interpolation technique to subdivide the 4 corners
' Of a cube,this will make it possible to do relly complex dot cubes and make transformations
' a simple matter and also save the overheads of rotating all those points as only the corners
' will ever need to be rotated.
'
' Coded by Shockwave / DBF
' Do not rip without credit :-)
'
' See you in the finished intro..
'
'---------------------------------------------------------------------------


        OPTION STATIC
        OPTION EXPLICIT

'-------------------------------------------------------------------------
' Includes.
'-------------------------------------------------------------------------

        '#define PTC_WIN
        #Include Once "tinyptc.bi"

   
    Const XRES=640 'Screen Width
    Const YRES=480 'Screen Height
   
    const SUBDIVISIONS = 20 '            How many dots per line?

   
DECLARE SUB DRAW_DOT_FACE(BYVAL X1 AS DOUBLE , BYVAL Y1 AS DOUBLE,BYVAL X2 AS DOUBLE , BYVAL Y2 AS DOUBLE , BYVAL X3 AS DOUBLE , BYVAL Y3 AS DOUBLE , BYVAL X4 AS DOUBLE , BYVAL Y4 AS DOUBLE)
DIM SHARED AS INTEGER BUFFER ( XRES * YRES )     

        If( ptc_open( "DBF SCREEN", XRES, YRES ) = 0 ) Then
        End -1
        End If
   
DIM XA,XB,XC,XD,YA,YB,YC,YD
DIM SHARED GADD,GADD2 AS DOUBLE
DO
    GADD=GADD+.004
    GADD2=GADD2+.005

XA = 320+(200*SIN(GADD ))
XB = 320+(200*SIN(GADD + 90))
XC = 320+(200*SIN(GADD2 + 180))
XD = 320+(200*SIN(GADD2 + 270))

YA = 240+(200*COS(GADD2))
YB = 240+(200*COS(GADD2 + 90))
YC = 240+(200*COS(GADD + 70))
YD = 240+(200*COS(GADD + 40))


    DRAW_DOT_FACE(XA,YA, XB,YB,  XC,YC, XD,YD )
    PTC_UPDATE@BUFFER(0)
    ERASE BUFFER
    SLEEP 1
LOOP UNTIL INKEY$=CHR$(27)

SUB DRAW_DOT_FACE(BYVAL X1 AS DOUBLE , BYVAL Y1 AS DOUBLE,BYVAL X2 AS DOUBLE , BYVAL Y2 AS DOUBLE , BYVAL X3 AS DOUBLE , BYVAL Y3 AS DOUBLE , BYVAL X4 AS DOUBLE , BYVAL Y4 AS DOUBLE)
   
    DIM AS INTEGER SA,SB
    DIM AS DOUBLE INTERX,INTERY , XXP , YYP
   
    DIM  AS DOUBLE TOPX (SUBDIVISIONS)
    DIM  AS DOUBLE TOPY (SUBDIVISIONS)
    DIM  AS DOUBLE BOTX (SUBDIVISIONS)
    DIM  AS DOUBLE BOTY (SUBDIVISIONS)

'
'   CALCULATE TOP LINE.
'

INTERX = (X1-X2) / SUBDIVISIONS
INTERY = (Y1-Y2) / SUBDIVISIONS

XXP = X1
YYP = Y1

FOR SA = 1 TO SUBDIVISIONS   
    TOPX(SA) = INT(XXP)
    TOPY(SA) = INT(YYP)
    XXP=XXP-INTERX       
    YYP=YYP-INTERY
    BUFFER(TOPX(SA)+(TOPY(SA) * XRES)) = &HFFFFFF
    BUFFER(TOPX(SA)+((TOPY(SA)-1) * XRES)) = &HFFFFF
    BUFFER(TOPX(SA)+((TOPY(SA)+1) * XRES)) = &HFFFFFF
    BUFFER((TOPX(SA)-1)+(TOPY(SA) * XRES)) = &HFFFFFF
    BUFFER((TOPX(SA)+1)+(TOPY(SA) * XRES)) = &HFFFFFF
NEXT

'
'   CALCULATE BOTTOM LINE.
'

INTERX = (X3-X4) / SUBDIVISIONS
INTERY = (Y3-Y4) / SUBDIVISIONS

XXP = X3
YYP = Y3
FOR SA = 1 TO SUBDIVISIONS   
   
    BOTX(SA) = INT(XXP)
    BOTY(SA) = INT(YYP)
   
    XXP=XXP-INTERX       
    YYP=YYP-INTERY
    BUFFER(BOTX(SA)+(BOTY(SA) * XRES)) = &HFFFFFF
    BUFFER(BOTX(SA)+((BOTY(SA)+1) * XRES)) = &HFFFFFF
    BUFFER(BOTX(SA)+((BOTY(SA)-1) * XRES)) = &HFFFFFF
    BUFFER((BOTX(SA)-1)+(BOTY(SA) * XRES)) = &HFFFFFF
    BUFFER((BOTX(SA)+1)+(BOTY(SA) * XRES)) = &HFFFFFF
NEXT

'
'   CALCULATE MIDDLES;
'
FOR SB=1 TO SUBDIVISIONS

INTERX = (TOPX(SB)-BOTX(SB)) / SUBDIVISIONS
INTERY = (TOPY(SB)-BOTY(SB)) / SUBDIVISIONS

XXP = TOPX(SB)
YYP = TOPY(SB)

FOR SA = 1 TO SUBDIVISIONS-1
    XXP=XXP-INTERX       
    YYP=YYP-INTERY
    BUFFER(INT(XXP)+(INT(YYP) * XRES)) = &HFFFFFF
    BUFFER(INT(XXP-1)+(INT(YYP) * XRES)) = &HFFFFFF
    BUFFER(INT(XXP+1)+(INT(YYP) * XRES)) = &HFFFFFF
    BUFFER(INT(XXP)+(INT(YYP-1) * XRES)) = &HFFFFFF
    BUFFER(INT(XXP)+(INT(YYP+1) * XRES)) = &HFFFFFF
NEXT

NEXT

END SUB



Title: Re: Use your imagination here..
Post by: Shockwave on August 17, 2006
To give you an example of how powerful this is, check this 200 * 200 Dot poly square or 40,000 dots in other words! Imaging how slow it would be to rotate 40,000 vertices, this could be drawn at this speed (faster when I've removed the fpu math) from just rotating 4 corners..


'
' This technique is going to form the basis for a demo effect.
' Basically it uses an interpolation technique to subdivide the 4 corners
' Of a cube,this will make it possible to do relly complex dot cubes and make transformations
' a simple matter and also save the overheads of rotating all those points as only the corners
' will ever need to be rotated.
'
' Coded by Shockwave / DBF
' Do not rip without credit :-)
'
' See you in the finished intro..
'
'---------------------------------------------------------------------------


        OPTION STATIC
        OPTION EXPLICIT

'-------------------------------------------------------------------------
' Includes.
'-------------------------------------------------------------------------

        '#define PTC_WIN
        #Include Once "tinyptc.bi"

   
    Const XRES=640 'Screen Width
    Const YRES=480 'Screen Height
   
    const SUBDIVISIONS = 200 '            How many dots per line?

   
DECLARE SUB DRAW_DOT_FACE(BYVAL X1 AS DOUBLE , BYVAL Y1 AS DOUBLE,BYVAL X2 AS DOUBLE , BYVAL Y2 AS DOUBLE , BYVAL X3 AS DOUBLE , BYVAL Y3 AS DOUBLE , BYVAL X4 AS DOUBLE , BYVAL Y4 AS DOUBLE)
DIM SHARED AS INTEGER BUFFER ( XRES * YRES )     

        If( ptc_open( "DBF SCREEN", XRES, YRES ) = 0 ) Then
        End -1
        End If
   
DIM XA,XB,XC,XD,YA,YB,YC,YD
DIM SHARED AS DOUBLE GADD,GADD2, GADD3,GADD4, GADD5
DO
    GADD=GADD+.004
    GADD2=GADD2+.008
    GADD3=GADD3+.007
    GADD4=GADD4+.005
    GADD5=GADD5+.01

XA = 320+(300*SIN(GADD5))
XB = 320+(300*SIN(GADD4))
XC = 320+(300*SIN(GADD3))
XD = 320+(300*SIN(GADD))

YA = 240+(238*COS(GADD2 ))
YB = 240+(238*COS(GADD3 ))
YC = 240+(238*COS(GADD4 ))
YD = 240+(238*COS(GADD5 ))


    DRAW_DOT_FACE(XA,YA, XB,YB,  XC,YC, XD,YD )
    PTC_UPDATE@BUFFER(0)
    ERASE BUFFER   
LOOP UNTIL INKEY$=CHR$(27)

SUB DRAW_DOT_FACE(BYVAL X1 AS DOUBLE , BYVAL Y1 AS DOUBLE,BYVAL X2 AS DOUBLE , BYVAL Y2 AS DOUBLE , BYVAL X3 AS DOUBLE , BYVAL Y3 AS DOUBLE , BYVAL X4 AS DOUBLE , BYVAL Y4 AS DOUBLE)
   
    DIM AS INTEGER SA,SB
    DIM AS DOUBLE INTERX,INTERY , XXP , YYP
   
    DIM  AS DOUBLE TOPX (SUBDIVISIONS)
    DIM  AS DOUBLE TOPY (SUBDIVISIONS)
    DIM  AS DOUBLE BOTX (SUBDIVISIONS)
    DIM  AS DOUBLE BOTY (SUBDIVISIONS)

'
'   CALCULATE TOP LINE.
'

INTERX = (X1-X2) / SUBDIVISIONS
INTERY = (Y1-Y2) / SUBDIVISIONS

XXP = X1
YYP = Y1

FOR SA = 1 TO SUBDIVISIONS   
    TOPX(SA) = INT(XXP)
    TOPY(SA) = INT(YYP)
    XXP=XXP-INTERX       
    YYP=YYP-INTERY
    BUFFER(TOPX(SA)+(TOPY(SA) * XRES)) = &HFFFFFF

NEXT

'
'   CALCULATE BOTTOM LINE.
'

INTERX = (X3-X4) / SUBDIVISIONS
INTERY = (Y3-Y4) / SUBDIVISIONS

XXP = X3
YYP = Y3
FOR SA = 1 TO SUBDIVISIONS   
   
    BOTX(SA) = INT(XXP)
    BOTY(SA) = INT(YYP)
   
    XXP=XXP-INTERX       
    YYP=YYP-INTERY
    BUFFER(BOTX(SA)+(BOTY(SA) * XRES)) = &HFFFFFF
NEXT

'
'   CALCULATE MIDDLES;
'
FOR SB=1 TO SUBDIVISIONS

INTERX = (TOPX(SB)-BOTX(SB)) / SUBDIVISIONS
INTERY = (TOPY(SB)-BOTY(SB)) / SUBDIVISIONS

XXP = TOPX(SB)
YYP = TOPY(SB)

FOR SA = 1 TO SUBDIVISIONS-1
    XXP=XXP-INTERX       
    YYP=YYP-INTERY
    BUFFER(INT(XXP)+(INT(YYP) * XRES)) = &HFFFFFF
NEXT

NEXT

END SUB
Title: Re: Use your imagination here..
Post by: MrP on August 17, 2006
Sweet little idea. Look forward to seeing the finished version....
Title: Re: Use your imagination here..
Post by: Dad1916 on August 17, 2006
Can you post the .exe examples if you get a chance. thanks. O0 O0
Title: Re: Use your imagination here..
Post by: Shockwave on August 17, 2006
Yep, no problem, I'll get a dotcube working with it and post it later :)
Title: Re: Use your imagination here..
Post by: Shockwave on August 17, 2006
Ok, well it works with a cube no problem, I have attached an exe to this post :)
Title: Re: Use your imagination here..
Post by: Clyde on August 17, 2006
Welldone and all, that dot cube looks amazing dude. :)

Cheers,
Clyde.
Title: Re: Use your imagination here..
Post by: Jim on August 18, 2006
Now, think about ANY point inside your cube.  You can get to it by adding only!  Just rotate 3 points x=(0,0,1), y=(0,1,0), z=(1,0,0) and then multiply x, y and z by the scale factors of the points you're interested in and you can get any point inside the cube (right now you've only used 1/2).  And then see that those x,y and z scale factors are actually just the x,y and z positions of the points inside the object.

I think you've just had an epiphany.

Jim
Title: Re: Use your imagination here..
Post by: DrewPee on August 18, 2006
Wow! Thats stunning - how the hell did you come up with that? My head hurts (although I do understand how its done!).
Looks wicked . . . what about setting fire to that now? lol?

Drew
Title: Re: Use your imagination here..
Post by: Shockwave on August 18, 2006
Quote from: Jim on August 18, 2006
Now, think about ANY point inside your cube. You can get to it by adding only! Just rotate 3 points x=(0,0,1), y=(0,1,0), z=(1,0,0) and then multiply x, y and z by the scale factors of the points you're interested in and you can get any point inside the cube (right now you've only used 1/2). And then see that those x,y and z scale factors are actually just the x,y and z positions of the points inside the object.

I think you've just had an epiphany.

Jim

Shit, that's so simple that it's sick :) I am going to have to re-write most of my 3D code to take advantage of this now. Cheers Jim.

Quote from: DrewPee on August 18, 2006
Wow! Thats stunning - how the hell did you come up with that? My head hurts (although I do understand how its done!).
Looks wicked . . . what about setting fire to that now? lol?

Drew

Burning it would be pretty easy, I'll add an example of it after I have finished doing the cracktro I am working on.

As far as working out how to do this I was just thinking about how it must be possible to calculate a cube from the corners if it was possible to calculate a texture from the same data so it just clicked.

I think I've been waiting to have an idea lately to be Honest Drew :)
Title: Re: Use your imagination here..
Post by: Shockwave on August 18, 2006
Transformations are in :)
Title: Re: Use your imagination here..
Post by: Stonemonkey on August 18, 2006
Nice one :)
Title: Re: Use your imagination here..
Post by: ninogenio on August 18, 2006
holy shit that is good!


i was gonna try one of these but i had it down a totally diffrent way, whats better is i understand it too.
Title: Re: Use your imagination here..
Post by: Shockwave on August 18, 2006
Yeah, I am really happy with the way this worked out and the extra understanding of how this may be applied to a 3D engine (thanks Jim, Thanks Stonemonkey). Glad that you like it guys, I'll surely do something cute with this technique soon.
Title: Re: Use your imagination here..
Post by: Rbz on August 18, 2006
Very smart  :)

Can you make a jelly cube effect  ?  Would be nice too
Title: Re: Use your imagination here..
Post by: Jim on August 18, 2006
Let's see if I can drive the nail in a little further...

When you multiply (0,0,1)  (0,1,0) and (1,0,0) by your matrix to get the vectors you need to add together in your new technique, all you are really doing is extracting rows from the matrix.
So

(x,y,z) * (a b c)
         (d e f)
         (g h i)
=(xa+yd+zg, xb+ye+ zh, xc+yf+zi)

But if x=0, y=0, z=1 that's just

(0a+0d+1g, 0b+0e+1h, 0c+0f+1i)=(g,h,i)

which is exactly the bottom row of the matrix.  x is the top row (a,b,c) and y is the middle row (d,e,f).

That tells you that the rows of the matrix are just 3 vectors.  vectors which point along the bottom edges of your cube.

All you are doing when you rotate a vector by a matrix is applying an x,y,z scale to the 3 vectors that point along the bottom edges of your cube.

In the immortal words of Paul Daniels "Now that's magic!"

Jim

Title: Re: Use your imagination here..
Post by: Clyde on August 19, 2006
I still need to inspect and see whats occuring.
Goes without saying though, Very cool and impressive transformers Shockwave.
Title: Re: Use your imagination here..
Post by: Shockwave on August 19, 2006
Good old small daniels :) And thanks Jim, this has been a revelation to me, I'm glad I shared this code now.

It is also having another completely seperate side effect too. In the Flame intro I used Delta timing for the text writer because I wanted to make sure that it was in synch to the music, I am applying delta timing to this routine and it still looks smooth right down to about 30fps, I'm hoping that I will be able to use this to make something really oldschool without the glitches I've come to accept as part of tinyptc.
Title: Re: Use your imagination here..
Post by: MrP on August 21, 2006
Yep looks real good...... must study that a bit my maths is pants....
Title: Re: Use your imagination here..
Post by: Dad1916 on August 21, 2006
Quote from: Shockwave on August 17, 2006
Ok, well it works with a cube no problem, I have attached an exe to this post :)
Very nice indeed. Now the hard part, I must examine the code and learn! O0 O0
Title: Re: Use your imagination here..
Post by: Shockwave on August 21, 2006
The routine was quite easy to code for me, but that is because I already had something to base it upon. It's not unlike coding an affine texture map. Don't be scared, it's pretty easy.

First of all you need to look at the information you have on the face you are about to draw.
All you know are where the 4 corners are, so you have 4 pairs of X+Y co-ordinates.

To make it very simple, class two of them as the top and two as the bottom.
From these we can calculate the top and bottom edges.
In the program a constant is set for the amount of subdivisions, it works something like this.

This pseudo code would calculate one of the edges;

x_top = X1
y_top = X1

Reciprocal_ X        = (X1 - X2 ) / Subdivisions
Reciprocal_ Y        = (Y1 -Y2 ) / Subdivisions

for loop = 1 to subdivisions
TOP_X_EDGE_STORE (LOOP) = x_top
TOP_Y_EDGE_STORE (LOOP) = y_top
  ytop = ytop+Reciprocal_Y
  xtop = ytop+Reciprocal_X >:D
next


Do the same for the bottom, these are the only points we need to physically store for the face, they can be plotted while they are being calculated.
Then another process to interpolate between the edges happens to draw the middle of the face and voila.
See it's not too bad.