3d animated tunnel in pure FB

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

3d animated tunnel in pure FB

Postby angros47 » Sep 22, 2014 17:37

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/OpenGLsoft/FourTextures/IvyTexture.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: 26
Joined: Jul 01, 2013 15:01
Location: Russia, Novosibirsk
Contact:

Re: 3d animated tunnel in pure FB

Postby Tyr_Anassazi » Sep 22, 2014 18:04

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

Re: 3d animated tunnel in pure FB

Postby Pritchard » Sep 22, 2014 19:00

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

Postby relsoft » Sep 23, 2014 10:02

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: 1539
Joined: Jun 21, 2005 19:04

Re: 3d animated tunnel in pure FB

Postby angros47 » Sep 23, 2014 10:47

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: 7
Joined: Apr 26, 2017 8:57
Contact:

Re: 3d animated tunnel in pure FB

Postby hurtado » Apr 17, 2019 21:59

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: 1262
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: 3d animated tunnel in pure FB

Postby jj2007 » Apr 18, 2019 3:16

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: 6013
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: 3d animated tunnel in pure FB

Postby dodicat » Apr 18, 2019 9:06

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: 7
Joined: Apr 26, 2017 8:57
Contact:

Re: 3d animated tunnel in pure FB

Postby hurtado » Apr 18, 2019 10:17

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: 6013
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: 3d animated tunnel in pure FB

Postby dodicat » Apr 18, 2019 11:06

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: 338
Joined: May 05, 2017 19:59
Location: Germany

Re: 3d animated tunnel in pure FB

Postby UEZ » Apr 18, 2019 11:11

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

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

Re: 3d animated tunnel in pure FB

Postby paul doe » Apr 18, 2019 11:21

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: 7
Joined: Apr 26, 2017 8:57
Contact:

Re: 3d animated tunnel in pure FB

Postby hurtado » Apr 18, 2019 13:03

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

Re: 3d animated tunnel in pure FB

Postby hurtado » Apr 18, 2019 13:39

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: 6013
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: 3d animated tunnel in pure FB

Postby dodicat » Apr 18, 2019 14:47

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.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest