3d animated tunnel in pure FB

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

3d animated tunnel in pure FB

Post by angros47 »

Textured tunnels were widely used in demoscenes in '90s, to show that even on a simple VGA 3d effects were possible. Later, when even cheapest computers had a 3d accelerator, tunnels lose popularity in demo competitions (everyone could build one with a 3d cylinder, so it become trivial).

But doing a tunnel in old-school way is still funny:

Code: Select all

screenres 800,600,24

dim shared as unsigned integer LookUpTable (800,600,2)

Dim texture As unsigned integer Ptr = ImageCreate( 247, 247,24 )
BLoad "IvyTexture.bmp", texture


dim as integer x,y

for x=0 to 800
	for y=0 to 600

		if y=300 then
			if x<400 then LookUpTable(x,y,1)=0 else LookUpTable(x,y,1)=1024
		else
			LookUpTable(x,y,1)=1024*(.5+atn((x-400)/(y-300))/3.1415926)
			if y<300 then LookUpTable(x,y,1)+=1024
		end if
		LookUpTable(x,y,2)= 8388608/((x-400)^2+(y-300)^2)

	next
next



dim as unsigned integer t=0

dim as unsigned integer u,v


texture +=8 ' Skip header data

do

	dim as unsigned integer ptr target=screenptr

	screenlock
	for y=1 to 600
		for x=1 to 800
			u=(LookUpTable(x,y,1) + t) mod 247
			v=(LookUpTable(x,y,2) + t) mod 247
			*target=*(texture +u*248+v)     'point(u , v , texture)
			target+=1
		next
	next
	screenunlock
	sleep 1

	t+=1

loop until inkey<>""

end
you need this texture:
http://www.math.ucsd.edu/~sbuss/MathCG/ ... exture.bmp

Note: the above code works in DOS, too (you might have to trim the file name of the texture, if LFN aren't supported)

It's just a port of this tutorial:

http://benryves.com/tutorials/tunnel/1

It's not the first example of that in FreeBasic (relsoft made something similar years ago), but this one is made in pure FB, with no external libraries, and it's about 35 lines of code!
Tyr_Anassazi
Posts: 28
Joined: Jul 01, 2013 15:01
Location: Russia, Novosibirsk
Contact:

Re: 3d animated tunnel in pure FB

Post by Tyr_Anassazi »

Hi, angros47.
Cool effect, and it is made by means of 2d. Thanks.
It is a pseudo 3d, but looks like real 3d.
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Re: 3d animated tunnel in pure FB

Post by anonymous1337 »

This is AWESOME!

And so simple. I understand very basic 2D/3D math, but it never hit me how to get "all" of the pixels on the screen using polar coordinates. I see now, thanks to the simplicity of this demo, that polar values for each x/y coordinate can simply be calculated instead.

That makes so much more sense to me than the other things I tried. Sheesh. Now, I actually feel dumb for having never thought of it :)

Great job!
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Re: 3d animated tunnel in pure FB

Post by relsoft »

Yo angros47! Nice effect!


Was it this?

Code: Select all

'' Twisted Tunnel

const BUFF_XMAX = 400 
const BUFF_YMAX = 350 


const XMID = BUFF_XMAX \ 2 
const YMID = BUFF_YMAX \ 2 
const PI = 3.141593                     'PI for rotation 
const TWOPI = (2 * PI) 
const BUFF_SIZE = BUFF_XMAX * BUFF_YMAX
const MAXPOINTS = 32 
const TUNNEL_TEXT_XMAX = 256 
const TUNNEL_TEXT_YMAX = 256 


declare sub draw_tunnel( Texture() as integer,_                        
                       byval addx as integer, byval addy as integer) 
declare sub tunnel_init_texture() 
declare function dist (byval x as single,byval  y as single,_ 
                   xc() as single, yc() as single,_ 
                  byref nearest_dist as single   ) as single 


dim texture as unsigned integer Ptr = ImageCreate(  BUFF_XMAX,  BUFF_YMAX, 32 )    

dim shared tunnel_texture( 255, 255) as integer 
dim shared distbuffer( 255, 255) as single 
dim shared xcoords(MAXPOINTS) as single 
dim shared ycoords(MAXPOINTS) as single     
dim shared sqrt(-(XMID^2 + YMID^2)*2 to (XMID^2 + YMID^2)*2) as single
dim shared atan(-YMID*2 to YMID*2, -XMID*2 to XMID*2) as single

randomize timer 


dim as integer x,y 

for x = -XMID*2 to XMID*2
   for y = -YMID*2 to YMID*2
       atan(y,x) = atan2(y,x)
   next y
next x

for x = -(XMID^2 + YMID^2)*2 to (XMID^2 + YMID^2)*2
   sqrt(x) = sqr(x)
next x
    

dim fold_off as single
dim fold_num as single
dim fold_scale as single


fold_off = 0.02
fold_scale = 0.05
fold_num = 16

tunnel_init_texture() 
dim shared demotime as integer
dim shared t as single

screenres BUFF_XMAX,BUFF_YMAX,32
do 

    t = timer 
    demotime = t * 500
    
    screenlock
    draw_tunnel( tunnel_texture(), (BUFF_XMAX shr 1)* sin(t * .5),_ 
               (t *.8)* (BUFF_YMAX shr 1) ) 
               
    fold_off = fold_off +  sin(demotime/500) * 0.25                   

    
    fold_scale =   0.5 + sin(demotime/500) * 0.20                   

 	screenunlock
    sleep 1
    screensync
loop until Inkey$ <>"" 


end 





sub draw_tunnel( tunnel_texture() as integer,_                        
                 byval addx as integer, byval addy as integer) 
   
    dim as integer x, y, tx, ty   
    
    static as integer cx = XMID, cy = YMID 
    dim xdist as single 
    dim as integer cxmx, cymy, diamxscale 
    static frame as short 
    static  as single fold_off = 0.02 
    static  as single squig_off = 0.02 
    static  as single fold_scale = 0.07' * sin(timer / 512.0) 
    static  as single fold_num = 5 
    static  as single rad_factor = 0 
    dim as integer diameter 
    static  as integer old_scale_sign = 0
    frame +=1 
    diameter = 128 
    diamxscale = 64 * diameter 
    cx = (XMID)+ sin(addx/80)*50 
    cy = (YMID)+ sin(addy/90)*50 
    dim temp as short 
    temp = 512/PI 
    dim angle as single 
    fold_off += 0.2    
    fold_scale = 0.5 * sin(frame / 40)    
    dim as integer light 
    dim as single inv_180 = 1/180
    dim as integer adder = BUFF_XMAX 
    
    if sgn(fold_scale)<>0 then 
    if sgn(fold_scale)<> old_scale_sign then 
        fold_num = (fold_num+1) mod 6
        old_scale_sign = sgn(fold_scale)
    end if
    end if
   dim as unsigned integer ptr p = screenptr
   for y = 0 to BUFF_YMAX - 1 
        cymy = cy - y 
      for x = 0 to BUFF_XMAX - 1 
            cxmx = cx -x                                                  
            xdist = sqrt((cxmx*cxmx) + (cymy*cymy)) 
            angle = atan(cymy,cxmx) + (((sin((fold_off) +  (fold_num-3) * xdist*inv_180)) * fold_scale)+1)             
            tx = int(angle * temp) + addx
            xdist = xdist * ((sin(fold_off + fold_num * angle) * fold_scale)+1)            
            light = xdist * 5 
            if light > 255 then light = 255 
            light = 255 - light 
            ty =  (diamxscale / xdist) + addy                        
            tx = (tx) and 255 
            ty = (ty) and 255                     
         *p  = tunnel_texture(tx, ty) or (light shl 16 or light shl 8 or light) 
         p += 1
      next x         
   next y 


end sub 

function dist ( byval x as single,byval  y as single,_ 
                xc() as single, yc() as single,_ 
            byref nearest_dist as single   ) as single 

    dim mindist as single 
    dim max as integer 
    dim d as single 
    dim dx as single, dy as single 
    dim diff as single 
    dim i as integer 
    mindist = 1D+32 
    max = ubound(xc) 
    for i = 0 to max 
        dx = abs(xc(i) - x) 
        dy = abs(yc(i) - y) 
        if dx > TUNNEL_TEXT_XMAX/2.0 then dx = TUNNEL_TEXT_XMAX-dx 
       if dy > TUNNEL_TEXT_YMAX/2.0 then dy = TUNNEL_TEXT_YMAX-dy 
       d = sqr( dx*dx + dy*dy ) 
        if d < mindist then 
           nearest_dist = mindist 
         mindist = d 
      end if 
    next i 
    dist = mindist 

end function 


sub tunnel_init_Texture() 

   dim i as integer 
   dim frame as integer 

    for i = 0 to MAXPOINTS 
        xcoords(i) = rnd * (TUNNEL_TEXT_XMAX + 1) 
        ycoords(i) = rnd * (TUNNEL_TEXT_YMAX + 1) 
    next i 

    frame = 0 

   dim mindist as single 
   dim maxdist as single 

          mindist = 1D+32 
          maxdist = 0 

        dim tx as single 
        dim ty as single 
        dim x as integer 
        dim y as integer 
        dim distance as single 
        dim distance2 as single 
        dim nearest_dist as single 
          for y = 0 to TUNNEL_TEXT_YMAX - 1 
          for x = 0 to TUNNEL_TEXT_XMAX  - 1 
              tx = x 
              ty = y 
              distance = dist(tx, ty, xcoords(), ycoords(), nearest_dist) 
              distbuffer(x, y) = distance 
              if distance < mindist then mindist = distance 
              if distance > maxdist then maxdist = distance 
          next x 
          next y 

        dim c as single 
        dim as ubyte r,g, b 
          for y = 0 to TUNNEL_TEXT_YMAX - 1 
          for x = 0 to TUNNEL_TEXT_XMAX - 1 
              c = (distbuffer(x, y) - mindist) / ((maxdist - mindist)) 
              r = 255 - (c * 255) 
              g = (c * 255) 
              b = r 
              tunnel_texture(x , y) = r shl 24 or g shl 16 or b shl 8 or 255
          next x 
          next y 

end sub


angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: 3d animated tunnel in pure FB

Post by angros47 »

Actually, I was talking about this one:

Image

and about this source:

http://www.freebasic.net/forum/viewtopic.php?t=3647

(I haven't tested, because I haven't tinyptc installed)

Anyway, your effect is nice, too.
hurtado
Posts: 47
Joined: Apr 26, 2017 8:57
Contact:

Re: 3d animated tunnel in pure FB

Post by hurtado »

Hello, just as curiosity, this a translated code from Relsoft of his tunnel effect to tinyc. 9kb compiled code and almost no wasting processor. Save the file as "tunnel.c" and compile with "tcc tunnel.c". All the merit for Relsoft.
If it is not allowed to posted c source code, you can delete the post.

Code: Select all

#include <windows.h>
#include <math.h>

#define cdXPos          CW_USEDEFAULT
#define cdYPos          CW_USEDEFAULT
#define cdXSize         320 //cdYSize*1.6
#define cdYSize         200
#define cdColFondo      0
#define MAIN_ICON       100    //  IDI_APPLICATION
#define cdVCursor       IDC_ARROW
#define cdVBarTipo      0
#define cdVBtnTipo      WS_OVERLAPPEDWINDOW
#define cdIdTimer       1
#define DIB_RGB_COLORS  0
#define cdimTeja        128
#define cdimTile        (cdimTeja*2)
#define deg2rad         0.01745329251994   // pi/180
#define cdPI            3.1415926535897932384626433832795
#define cd2PI           6.283185307179586476925286766559
#define maxpoints       32

// Prototipos de funciones
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

// Variables globales
int               *pMainDIB    = NULL;
int                vdxClient, vdyClient;
BITMAPINFOHEADER   bi = {sizeof(BITMAPINFOHEADER),cdXSize,-cdYSize,1,32,0,0,0,0,0,0};
int                Buffer[cdXSize*cdYSize];
int                Tangle[cdXSize][cdYSize], Tdepth[cdXSize][cdYSize];
int                Texture[256][256], Distbuffer[256][256];
double             xcoords[maxpoints], ycoords[maxpoints];
double             tmp = 0;

void DrawTunnel (int addx, int addy) {
  int x, y, tx, ty, k = 0;
  for (y = 0; y < cdYSize; y++) {
    for (x = 0; x < cdXSize; x++, k++) {
      tx = (Tangle[x][y] + addx) & 255;
      ty = (Tdepth[x][y] + addy) & 255;
      *(pMainDIB + k) = Texture[tx][ty];
    }  
  }  
}  

double dist (double x, double y, double xc[], double yc[]) {
  double mindist = 1E+16, a, b, d;
  int i;
  for (i = 0; i < maxpoints; i++) {
    a = (xc[i] - x) * (xc[i] - x) ;
    b = (yc[i] - y) * (yc[i] - y);
    d = sqrt(a + b);
    if (d < mindist) mindist = d;
  }
  return(mindist);
}  

void doPrecalc (void) {
  int x, y, i, r, g, b, cx, cy, diameter = 64;
  double mindist, maxdist, distance, c, tx, ty;
  for (i = 0; i < maxpoints; i++) {
    xcoords[i] = rand() % cdXSize;
    ycoords[i] = rand() % cdYSize;
  }
  mindist = 1E+16;
  maxdist = 0;
  for (y = 0; y < 256; y++) {
    for (x = 0; x < 256; x++) {
      tx = abs(x-128); ty = abs(y - 128);
      distance = dist (tx, ty, xcoords, ycoords) ;
      Distbuffer [x][y] = distance;
      if (distance < mindist) mindist = distance;
      if (distance > maxdist) maxdist = distance;
    }  
  }  
  for (y = 0; y < 256; y++) {
    for (x = 0; x < 256; x++) {
      c =(Distbuffer [x][y] - mindist) / (maxdist - mindist);
      r = (int)(c * 55.);
      g = (int)(c * 155.);
      b = (int)(c * 255.);
      Texture[x][y] = (r << 16) | (g << 8) | b;
    }  
  }
  cx = cdXSize/2; cy = cdYSize/2;
  for (x = 0; x < cdXSize; x++) {
    for (y = 0; y < cdYSize; y++) {
      Tangle[x][y] = (int)(atan2(cy - y, cx - x) * 256. / M_PI );
      distance = (sqrt((x-cx)*(x-cx) + (y-cy)*(y-cy)));
      Tdepth[x][y] =  256. * diameter / distance;
    }  
  }  
}  

void PintaObjeto (void) {
  DrawTunnel ((cdXSize/2)* sin(tmp * .5), (tmp *.8)* (cdYSize/2));
  tmp += .05;
}

void Inicio (void) {
  doPrecalc ();
}

LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static   HDC               bufDIBDC;
     static   HBITMAP           hMainDIB;
              HDC               hdc ;
              PAINTSTRUCT       ps ;
     static   HGDIOBJ           hOldDIB=0, hGDITmp;
              int               bResult;

     switch (message)
     {
     case WM_CHAR :
          if (wParam == VK_ESCAPE) {
            goto     wmDestruimos;
          }
          return 0 ;

     case WM_CREATE:
          hdc = GetDC(hWnd);
          
          // Crea un búfer dib para PintaObjeto. pMainDIB es un puntero a él
          bufDIBDC = CreateCompatibleDC (hdc);
          hMainDIB = CreateDIBSection(hdc, (BITMAPINFO *) &bi, DIB_RGB_COLORS, (void **) &pMainDIB, NULL, 0);
          hOldDIB  = SelectObject (bufDIBDC, hMainDIB);
        
          ReleaseDC (hWnd, hdc);   // Libera device context
          
          Inicio ();
          SetTimer (hWnd, cdIdTimer, 20, NULL) ;
          return 0 ;

     case WM_TIMER :
          InvalidateRect (hWnd, NULL, FALSE) ;
          return 0 ;

     case WM_SIZE :
          vdxClient = lParam & 0xFFFF;
          vdyClient = lParam >> 0x10;
          return 0 ;

     case WM_PAINT :
          hdc = BeginPaint(hWnd, &ps);
          PintaObjeto ();
          // bResult = BitBlt(hdc, 0, 0, cdXSize, cdYSize, bufDIBDC, 0, 0, SRCCOPY);
          bResult = StretchBlt (hdc, 0, 0, vdxClient, vdyClient, bufDIBDC, 0, 0, cdXSize, cdYSize, SRCCOPY);
          EndPaint(hWnd, &ps);
          return 0 ;

     case WM_DESTROY :
          wmDestruimos:
          KillTimer (hWnd, cdIdTimer) ;
          hGDITmp = SelectObject (bufDIBDC, hOldDIB);
          bResult = DeleteDC (bufDIBDC);
          bResult = DeleteObject (hMainDIB);
          bResult = DestroyWindow (hWnd);
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hWnd, message, wParam, lParam) ;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     RECT   WRect;
     static TCHAR szAppName[] = TEXT ("SWGPTG") ;
     HWND         hWnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hbrBackground = cdColFondo ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     wndclass.hInstance     = GetModuleHandle (NULL) ;
     wndclass.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(MAIN_ICON)) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;

     if (!RegisterClass (&wndclass)) {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      TEXT ("Error"), MB_ICONERROR) ;
          return 0 ;
     }

     SetRect (&WRect, 0, 0, cdXSize, cdYSize);
     AdjustWindowRectEx (&WRect, cdVBtnTipo, 0, cdVBarTipo);
     WRect.bottom -= WRect.top;
     WRect.right  -= WRect.left;
     WRect.left    = (GetSystemMetrics (SM_CXSCREEN) - WRect.right)/2;
     WRect.top     = (GetSystemMetrics (SM_CYSCREEN) - WRect.bottom) / 3;
     
     hWnd = CreateWindow (szAppName, TEXT ("Tunnel - from Relsoft"),
                          cdVBtnTipo,//WS_OVERLAPPEDWINDOW,
                          WRect.left,WRect.top,WRect.right,WRect.bottom,
                          NULL, NULL, hInstance, NULL) ;

     ShowWindow (hWnd, iCmdShow) ;
     UpdateWindow (hWnd) ;

     while (GetMessage (&msg, NULL, 0, 0)) {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: 3d animated tunnel in pure FB

Post by jj2007 »

Looks interesting, but I don't have TinyC installed. So I tried Visual C, Gcc and PellesC. All three fail with this code, with very different error messages, of course. It would be nice if C was compatible to something ;-)
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: 3d animated tunnel in pure FB

Post by dodicat »

In tiny c, MP_I isn't declared, so a fail.
I made MP_I as 1, just to get a runner, compiled fine, but Avira antivirus stopped the .exe from running and ditched it into the quarantine.

fb 1.06 is no longer compatible with much of the old fb forum code due to
...
Suffixes are only valid in -lang fb or deprecated or fblite
...

I don't know the reason for doing this, suffixes are part of most basic dialects.

luckily relsoft's code only required one suffix to be expunged.
hurtado
Posts: 47
Joined: Apr 26, 2017 8:57
Contact:

Re: 3d animated tunnel in pure FB

Post by hurtado »

Tiny C is ANSI compatible. This code may be compiled with any of your three c compilers with a tiny effort. You need a tiny effort because each compiler has its own specifications. Luckily, to install tiny c you just need to unzip the package.

Tiny c does not usually get along with antivirus, beeing common false positives. Lately I've seen that Avast goes pretty well with Tiny C. Not long ago It also gave many false positives, but I sent them the code and, curiously, it seems that they have taken it into account, because now it works quite well. Avira, on the other hand, is still quite strict with tinyc.

I guess I do not have the possibility to attach files, so I can not upload any snap shot.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: 3d animated tunnel in pure FB

Post by dodicat »

Thanks hurtado.
Perhaps my tiny c is a bit old.
If I strip the .exe before I run it, the false positive is gone.
It strips to 10 kb, and runs fine.
This is probably why the .exe files produced by freebasic -gen gcc don't give avira problems, because compiled .exe by gcc (Dev-C++, or mingw) often give false positives when using Win api functions.



For curiosiuty, where is the MP_1 defined or declared?
Maybe I should get an updated tcc .zip
UEZ
Posts: 972
Joined: May 05, 2017 19:59
Location: Germany

Re: 3d animated tunnel in pure FB

Post by UEZ »

Here another Tunnel flight: Tunnel Flight v2.5.2 (too long to post it here directly)

Image
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: 3d animated tunnel in pure FB

Post by paul doe »

hurtado wrote:...
I guess I do not have the possibility to attach files, so I can not upload any snap shot.
Nobody here does. You need to use an external host for your images like imgbox.
hurtado
Posts: 47
Joined: Apr 26, 2017 8:57
Contact:

Re: 3d animated tunnel in pure FB

Post by hurtado »

What is MP_1? I have never seen it
hurtado
Posts: 47
Joined: Apr 26, 2017 8:57
Contact:

Re: 3d animated tunnel in pure FB

Post by hurtado »

Here it is another enhanced version of the tunnel. Compiled in 10Kb with tiny c, almost no wasting cpu.

Image

Code: Select all

#define cdXPos          CW_USEDEFAULT
#define cdYPos          CW_USEDEFAULT
#define cdXSize         320 //cdYSize*1.6
#define cdYSize         200
#define cdColFondo      0
#define MAIN_ICON       100    //  IDI_APPLICATION
#define cdVCursor       IDC_ARROW
#define cdVBarTipo      0
#define cdVBtnTipo      WS_OVERLAPPEDWINDOW
#define cdIdTimer       1
#define DIB_RGB_COLORS  0
#define deg2rad         0.01745329251994   // pi/180
#define cdPI            3.1415926535897932384626433832795
#define cd2PI           6.283185307179586476925286766559
#define maxpoints       32

// Prototipos de funciones
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

// Variables globales
int               *pMainDIB    = NULL;
int                vdxClient, vdyClient;
BITMAPINFOHEADER   bi = {sizeof(BITMAPINFOHEADER),cdXSize,-cdYSize,1,32,0,0,0,0,0,0};
int                Tangle[cdXSize*2][cdYSize*2], Tdepth[cdXSize*2][cdYSize*2];
int                Texture[256][256], Distbuffer[256][256];
double             xcoords[maxpoints], ycoords[maxpoints];
double             tmp = 0;

double dist (double x, double y, double xc[], double yc[]) {
  double mindist = 1E+16, a, b, d;
  int i;
  for (i = 0; i < maxpoints; i++) {
    a = (xc[i] - x) * (xc[i] - x) ;
    b = (yc[i] - y) * (yc[i] - y);
    d = sqrt(a + b);
    if (d < mindist) mindist = d;
  }
  return(mindist);
}  

void doPrecalc (void) {
  int x, y, i, r, g, b, cx, cy, diameter = 64;
  double mindist, maxdist, distance, c, tx, ty;
  for (i = 0; i < maxpoints; i++) {
    xcoords[i] = rand() % cdXSize;
    ycoords[i] = rand() % cdYSize;
  }
  mindist = 1E+16;
  maxdist = 0;
  for (y = 0; y < 256; y++) {
    for (x = 0; x < 256; x++) {
      tx = abs(x-128); ty = abs(y - 128);
      distance = dist (tx, ty, xcoords, ycoords) ;
      Distbuffer [x][y] = distance;
      if (distance < mindist) mindist = distance;
      if (distance > maxdist) maxdist = distance;
    }  
  }  
  for (y = 0; y < 256; y++) {
    for (x = 0; x < 256; x++) {
      c =(Distbuffer [x][y] - mindist) / (maxdist - mindist);
      r = (int)(c * 55.);
      g = (int)(c * 155.);
      b = (int)(c * 255.);
      Texture[x][y] = (r << 16) | (g << 8) | b;
    }  
  }
  cx = cdXSize; cy = cdYSize;
  for (x = 0; x < cdXSize*2; x++) {
    for (y = 0; y < cdYSize*2; y++) {
      Tangle[x][y] = (int)(atan2(cy - y, cx - x) * 256. / M_PI );
      distance = (sqrt((x-cx)*(x-cx) + (y-cy)*(y-cy)));
      Tdepth[x][y] =  256. * diameter / distance;
    }  
  }  
}  

void PintaObjeto (void) {
  int x, y, tx, ty;
  static double currtime = 0.0;
  int sx, sy, slx, sly, k = 0, r, g, b, c;
  double    d;

  currtime += 0.00913;

  sx = (int)(256 * 1.0 * currtime);
  sy = (int)(256 * 0.25 * currtime);

  //Calculate the movement
  slx = cdXSize / 2 + (int)(cdXSize / 2 * cos(currtime));
  sly = cdYSize / 2 + (int)(cdYSize / 2 * sin(currtime * 3.3));
  
  for (y = 0; y < cdYSize; y++) {
    for (x = 0; x < cdXSize; x++, k++) {
      tx = (unsigned int)(Tdepth[x + slx][y + sly] + sx) & 255;
      ty = (unsigned int)2*(Tangle[x + slx][y + sly] + sy) & 255;
      d = (54./Tdepth[x + slx][y + sly]);
      c = Texture[tx][ty];
      r = (c & (0xFF0000))>>16; g = (c & (0xFF00))>>8; b = c & 0xFF;
      r = (int) ((double)r * d); g = (int)((double)g * d); b = (int)((double)b * d);
      if (r & 0x1F00) r = 255; if (g & 0x1F00) g = 255; if (b & 0x1F00) b = 255;
      *(pMainDIB + k) = b|(g<<8)|(r<<16);
    }  
  }  
}

void Inicio (void) {
  doPrecalc ();
}

LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static   HDC               bufDIBDC;
     static   HBITMAP           hMainDIB;
              HDC               hdc ;
              PAINTSTRUCT       ps ;
     static   HGDIOBJ           hOldDIB=0, hGDITmp;
              int               bResult;

     switch (message)
     {
     case WM_CHAR :
          if (wParam == VK_ESCAPE) {
            goto     wmDestruimos;
          }
          return 0 ;

     case WM_CREATE:
          hdc = GetDC(hWnd);
          
          // Crea un búfer dib para PintaObjeto. pMainDIB es un puntero a él
          bufDIBDC = CreateCompatibleDC (hdc);
          hMainDIB = CreateDIBSection(hdc, (BITMAPINFO *) &bi, DIB_RGB_COLORS, (void **) &pMainDIB, NULL, 0);
          hOldDIB  = SelectObject (bufDIBDC, hMainDIB);
        
          ReleaseDC (hWnd, hdc);   // Libera device context
          
          Inicio ();
          SetTimer (hWnd, cdIdTimer, 20, NULL) ;
          return 0 ;

     case WM_TIMER :
          InvalidateRect (hWnd, NULL, FALSE) ;
          return 0 ;

     case WM_SIZE :
          vdxClient = lParam & 0xFFFF;
          vdyClient = lParam >> 0x10;
          return 0 ;

     case WM_PAINT :
          hdc = BeginPaint(hWnd, &ps);
          PintaObjeto ();
          // bResult = BitBlt(hdc, 0, 0, cdXSize, cdYSize, bufDIBDC, 0, 0, SRCCOPY);
          bResult = StretchBlt (hdc, 0, 0, vdxClient, vdyClient, bufDIBDC, 0, 0, cdXSize, cdYSize, SRCCOPY);
          EndPaint(hWnd, &ps);
          return 0 ;

     case WM_DESTROY :
          wmDestruimos:
          KillTimer (hWnd, cdIdTimer) ;
          hGDITmp = SelectObject (bufDIBDC, hOldDIB);
          bResult = DeleteDC (bufDIBDC);
          bResult = DeleteObject (hMainDIB);
          bResult = DestroyWindow (hWnd);
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hWnd, message, wParam, lParam) ;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     RECT   WRect;
     static TCHAR szAppName[] = TEXT ("SWGPTG") ;
     HWND         hWnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hbrBackground = cdColFondo ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     wndclass.hInstance     = GetModuleHandle (NULL) ;
     wndclass.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(MAIN_ICON)) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;

     if (!RegisterClass (&wndclass)) {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      TEXT ("Error"), MB_ICONERROR) ;
          return 0 ;
     }

     SetRect (&WRect, 0, 0, cdXSize, cdYSize);
     AdjustWindowRectEx (&WRect, cdVBtnTipo, 0, cdVBarTipo);
     WRect.bottom -= WRect.top;
     WRect.right  -= WRect.left;
     WRect.left    = (GetSystemMetrics (SM_CXSCREEN) - WRect.right)/2;
     WRect.top     = (GetSystemMetrics (SM_CYSCREEN) - WRect.bottom) / 3;
     
     hWnd = CreateWindow (szAppName, TEXT ("Tunnel - from Relsoft"),
                          cdVBtnTipo,//WS_OVERLAPPEDWINDOW,
                          WRect.left,WRect.top,WRect.right,WRect.bottom,
                          NULL, NULL, hInstance, NULL) ;

     ShowWindow (hWnd, iCmdShow) ;
     UpdateWindow (hWnd) ;

     while (GetMessage (&msg, NULL, 0, 0)) {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: 3d animated tunnel in pure FB

Post by dodicat »

hurtado wrote:What is MP_1? I have never seen it
Tangle[x][y] = (int)(atan2(cy - y, cx - x) * 256. / M_PI ); // line 88

sorry, M_PI I meant to write.
Post Reply