BMP save ?

Status
Niet open voor verdere reacties.

blua tigro

Gebruiker
Lid geworden
21 apr 2009
Berichten
48
ik wil n raytracer schijven
daarbij heb ik n saveBMP functie nodig
hoe do ik dat ?
Code:
#include <iostream>

typedef struct tagBITMAPFILEHEADER {
  WORD  bfType ;
  DWORD bfSize ;
  WORD  bfReserved1 ;
  WORD  bfReserved2 ;
  DWORD bfOffBits ;
} BITMAPFILEHEADER , *PBITMAPFILEHEADER ;

typedef struct tagBITMAPINFOHEADER {
  DWORD biSize ;
  LONG  biWidth ;
  LONG  biHeight ;
  WORD  biPlanes ;
  WORD  biBitCount ;
  DWORD biCompression ;
  DWORD biSizeImage ;
  LONG  biXPelsPerMeter ;
  LONG  biYPelsPerMeter ;
  DWORD biClrUsed ;
  DWORD biClrImportant ;
} BITMAPINFOHEADER , *PBITMAPINFOHEADER ;

typedef struct PIXEL {
  unsigned char r , g , b ;
} ;

const int screenx = 800 ;
const int screeny = 600 ;

PIXEL pixel[ screenx ][ screeny ] ;

void saveBMP()
{
//todo :
//fill bitmapfileheader
//fill bitmapinfoheader
//open file
//  write bitmapfileheader
//  write bitmapinfoheader
//  write pixel data
//close file
}

int main()
{
  int x , y ;
  for ( x = 0 ; x < screenx ; x++ )
  {
    for ( y = 0 ; y < screeny ; y++ )
    {
      pixel[ x ][ y ].r = 255 ;
      pixel[ x ][ y ].g = 127 ;
      pixel[ x ][ y ].b = 0 ;
    }
  }
  saveBMP() ;
}
 
raytrecer

update : windows versie 0.1
ik heb windows toegevoegd
dan heb ik GDI bmp file
en zie ik het plaatje

ik kreeg wat hulp op n ander forum
ik denk niet dat ik alles heb

ik heb nu :
Code:
// bluatigro 1 okt 2017
// windows raytracer 0.1

#include <windows.h>
#include <string>

const int winx = 800 ;
const int winy = 600 ;

typedef struct PIXEL {
	char r , g , b , a ;
} ;

void saveBMP( string filename , PIXEL[][] pixel
, int w , int h )
{
unsigned nWidthBytes = ((w * 24 + 31) & ~31) / 8;
// EDIT: Corrected
//unsigned nExtra = 8 * ((screenx * 24) % 32);
unsigned nExtra = nWidthBytes - 3 * w ;
unsigned nPixelSize = nWidthBytes * h ;
BITMAPFILEHEADER FileHdr ;
// File header
FileHdr.bfType = 0x4D42; // "BM"
FileHdr.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD) + nPixelSize;
FileHdr.bfReserved1 = pBmHdr.bfReserved2 = 0;
// EDIT: Corrected
//FileHdr.bfOffBits = sizeof(BITMAPFILEHEADER);
FileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
BITMAPINFOHEADER InfoHdr ;
// Info header for 24-bit RGB
InfoHdr.biSize = sizeof(BITMAPINFOHEADER);
InfoHdr.biWidth = screenx;
InfoHdr.biHeight = screeny;
InfoHdr.biPlanes = 1;
InfoHdr.biBitCount = 24;
InfoHdr.biCompression = BI_BITFIELDS;
InfoHdr.biSizeImage = nPixelSize;
InfoHdr.biXPelsPerMeter = 0;
InfoHdr.biYPelsPerMeter = 0;
InfoHdr.biClrUsed = 0;
InfoHdr.biClrImportant = 0;
*
// Color table (bit masks for the three colours) with BI_BITFIELDS
// NOTE: I'm actually not sure if these must be reversed!
DWORD clrTable[3] = { 0xff, 0xff00, 0xff0000 };
*
fwrite(&FileHdr, 1, sizeof(BITMATFILEHEADER), file);
fwrite(&InfoHdr, 1, sizeof(BITMATINFOHEADER), file);
fwrite(clrTable, 1, sizeof(clrTable), file);
for (int y = 0 ; y &lt ; h ; y++ )
{
    // EDIT: Corrected
    //fwrite(pixel[y], 3, nWidthBytes, file);
    fwrite( pixel[y] , 3 , w , file ) ;
    if ( nExtra )
    {
        DWORD dummy = 0;
        fwrite( &dummy , 1 , nExtra , file ) ;
    }
}  
}

/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {

  HDC hdc ;
	PAINTSTRUCKT ps ;
	
	switch( Message ) 
	{
		
		case WM_PAINT :
			int x , y ;
			PIXEL pixel[ winy ][ winx ] ;
			unsigned long color ; 
			hdc = BeginPaint( hwnd , & ps ) ;
      for ( x = 0 ; x < winx ; x++ )
      {
        for ( y = 0 ; y < winy ; y++ }
        {
      	if ( x > 100 && x < winx - 100
				&& y > 100 && y < winy - 100 )
      	  color = 0xff007fff ; //orange
      	else
      	  color = 0xff000000 ; //black
      	pixel[y][x].r = color & 255 ;
      	pixel[y][x].g = ( color >> 8 ) & 255 ;
      	pixel[y][x].b = ( color >> 16 ) & 255 ;
      	pixel[y][x].a = 255 ;
      	SetPixel( hdc , x , y , color ) ;
			}
	}
		saveBMP( "orange-rect.bmp" 
			, pixel , winx , winy ) ;
			
			EndPaint( hwnd , & ps ) ;			
		break ;

		/* Upon destruction, tell the main thread to stop */
		case WM_DESTROY: {
			PostQuitMessage(0);
			break;
		}
		
		/* All other messages (a lot of them) are processed using default procedures */
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);
	}
	return 0;
}

/* The 'main' function of Win32 GUI programs: this is where execution starts */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc; /* A properties struct of our window */
	HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */
	MSG msg; /* A temporary location for all messages */

	/* zero out the struct and set the stuff we want to modify */
	memset(&wc,0,sizeof(wc));
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.lpfnWndProc	 = WndProc; /* This is where we will send messages to */
	wc.hInstance	 = hInstance;
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	
	/* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszClassName = "WindowClass";
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION); /* Load a standard icon */
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION); /* use the name "A" to use the project icon */

	if(!RegisterClassEx(&wc)) {
		MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, /* x */
		CW_USEDEFAULT, /* y */
		winx, /* width */
		winy, /* height */
		NULL,NULL,hInstance,NULL);

	if(hwnd == NULL) {
		MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	/*
		This is the heart of our program where all input is processed and 
		sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
		this loop will not produce unreasonably high CPU usage
	*/
	while(GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
		TranslateMessage(&msg); /* Translate key codes to chars if present */
		DispatchMessage(&msg); /* Send it to WndProc */
	}
	return msg.wParam;
}
 
raytracer

update :
ik heb n scene toegevoegd

Code:
// bluatigro 1 okt 2017
// windows raytracer 0.2

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

const int winx = 800 ;
const int winy = 600 ;

typedef struct PIXEL {
	char r , g , b , a ;
} ;

class d3d
{
public :
	double x , y , z ;
	d3d()
	{
		x = 0.0 ;
		y = 0.0 ;
		z = 0.0 ;
	}
	d3d( double X , double Y , double Z )
	{
		x = X ;
		y = Y ;
		z = Z ;
	}
	void fill( double X , double Y , double Z )
	{
		x = X ;
		y = Y ;
		z = Z ;
	}
	unsigned long toColor()
  {
  	return (unsigned long)
		( floor( x * 255 ) + 
		  floor( y * 255 ) * 256 +
			floor( z * 255 ) * 256 * 256 ) ;
	}
} ;
d3d operator + ( d3d a , d3d b )
{
	return d3d( a.x + b.x ,
	            a.y + b.y , 
							a.z + b.z ) ;
}
d3d operator - ( d3d a , d3d b )
{
	return d3d( a.x - b.x ,
	            a.y - b.y , 
							a.z - b.z ) ;
}
d3d operator / ( d3d a , double b )
{
	return d3d( a.x / b ,
	            a.y / b , 
							a.z / b ) ;
}
d3d operator * ( d3d a , d3d b )
{
	return d3d( a.x * b ,
	            a.y * b , 
							a.z * b ) ;
}
double dot( d3d a , d3d b )
{
	return a.x * b.x
	     + a.y * b.y 
	     + a.z * b.z ;
}
double length( d3d a )
{
	return sqrt( dot( a , a ) ) ;
}
d3d normalize( d3d a )
{
	return a / length( a ) ;
}
double getAngle( d3d a , d3d b )
{
	double d , la , lb ;
	d = dot( a , b ) ;
	la = length( a ) ;
	lb = length( b ) ;
	return acos( d / ( la * lb ) ) ;
}
d3d cross( d3d a , d3d b )
{
	return d3d( a.y * b.z - a.z * b.y ,
	            a.z * b.x - a.x * b.z ,
							a.x * b.y - a.y * b.x ) ;
}

struct Matrial
{
	d3d diffuse ;
	double reflection ;
} ;
Matrial matrial ;

const double INFINITY = 1e300 ;
const double SMALL = 1e-300 ;

class Sphere
{
public :
  d3d center ;
	double radius , radius2 ;	
  Matrial mat ;
  void fill( d3d c , double r )
  {
  	center = c ;
  	radius = r ;
  	radius2 = r * r ;
  	mat = material ;
	}
  double hit( d3d o , d3d d )
  {
*   double t , a , b , c , disc ;
*   d3d temp = o - center ;
*   a = dot( d , d ) ;
*   b = 2 * dot( temp , d ) ;
*   c = dot( temp , temp ) - radius2 ;
*   disc = b * b - 4 * a * c
*   if ( disc < 0 ) 
* *   return INFINITY ;
*   else
    {
* *   double e = sqrt( disc ) ;
* *   double demon = 2 * a ;
* *   t = ( -b - e ) / demon ;
* *   if ( t > SMALL ) return t ;
* *   t = ( -b + e ) / demon ;
* *   if ( t > SMALL ) return t ;
*   }
*   return INFINITY ;
	}
} ;

Sphere spheres( 100 ) ;
int spheretel ;
void sphere( double x , double y , double z
, double r , d3d color )
{
  matrial.diffuse = color ;
	spheres( spheretel ).fill( x , y , z , r ) ;
  spheretel++ ;
}

d3d light ;

d3d render( d3d o , d3d d , int depth )
{
	double dist , sphdist = INFINITY ;
	int i , isph = -1 ;
	for ( i = 0 ; i < spheretel ; i++ )
	{ 
	  dist = spheres( i ).hit( o , d ) ;
		if ( dist < sphdist )
		{
			sphdist = dist ;
			isph = i ;
		}
	}
	if ( isph == -1 )
	  return d3d()
	d3d p , n ;
	p = o + d * sphdist ;
	n = p - spheres( isph ).center ;
	double a = getAngle( n , light ) ;
	d3d color = spheres( isph ).mat.diffuse ; 
	color = color * ( 0.5 + cos( a * 2 ) / 2 ) ;
	if ( a > PI / 2 )
	  color = d3d() ; 
	for ( i = 0 ; i < spheretel ; i ++ )
	{
		if ( i != isph ) 
		{
			a = spheres( i ).hit( p , light ) ;
			if ( a == INFINITY )
			  color = d3d() ;
		}
	}
	return color ;
}

void saveBMP( string filename , PIXEL[][] pixel
, int w , int h )
{
unsigned nWidthBytes = ((w * 24 + 31) & ~31) / 8;
// EDIT: Corrected
//unsigned nExtra = 8 * ((screenx * 24) % 32);
unsigned nExtra = nWidthBytes - 3 * w ;
unsigned nPixelSize = nWidthBytes * h ;
BITMAPFILEHEADER FileHdr ;
// File header
FileHdr.bfType = 0x4D42; // "BM"
FileHdr.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD) + nPixelSize;
FileHdr.bfReserved1 = pBmHdr.bfReserved2 = 0;
// EDIT: Corrected
//FileHdr.bfOffBits = sizeof(BITMAPFILEHEADER);
FileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
BITMAPINFOHEADER InfoHdr ;
// Info header for 24-bit RGB
InfoHdr.biSize = sizeof(BITMAPINFOHEADER);
InfoHdr.biWidth = screenx;
InfoHdr.biHeight = screeny;
InfoHdr.biPlanes = 1;
InfoHdr.biBitCount = 24;
InfoHdr.biCompression = BI_BITFIELDS;
InfoHdr.biSizeImage = nPixelSize;
InfoHdr.biXPelsPerMeter = 0;
InfoHdr.biYPelsPerMeter = 0;
InfoHdr.biClrUsed = 0;
InfoHdr.biClrImportant = 0;
*
// Color table (bit masks for the three colours) with BI_BITFIELDS
// NOTE: I'm actually not sure if these must be reversed!
DWORD clrTable[3] = { 0xff, 0xff00, 0xff0000 };
*
fwrite(&FileHdr, 1, sizeof(BITMATFILEHEADER), file);
fwrite(&InfoHdr, 1, sizeof(BITMATINFOHEADER), file);
fwrite(clrTable, 1, sizeof(clrTable), file);
for (int y = 0 ; y &lt ; h ; y++ )
{
    // EDIT: Corrected
    //fwrite(pixel[y], 3, nWidthBytes, file);
    fwrite( pixel[y] , 3 , w , file ) ;
    if ( nExtra )
    {
        DWORD dummy = 0;
        fwrite( &dummy , 1 , nExtra , file ) ;
    }
}  
}

/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {

  HDC hdc ;
	PAINTSTRUCKT ps ;
	
	switch( Message ) 
	{
		
		case WM_PAINT :
			int x , y ;
			d3d o , d , WHITE ;
			WHITE.fill( 1.0 , 1.0 , 1.0 ) ;
			PIXEL pixel[ winx ][ winy ] ;
			unsigned long color ; 
			hdc = BeginPaint( hwnd , & ps ) ;

      //scene
			spheretel = 0 ;
			light.fill( -1.0 , 1.0 , -1.0 ) ;
			sphere( 0.0 , 0.0 , 0.0 , 100.0 , WHITE ) ;
			sphere( 0.0 , -INIFINITY - winy / 2 , 0.0
			      , INFINITY , WHITE ) ;
			//create scene on window
      for ( x = 0 ; x < winx ; x++ )
      {
      	for ( y = 0 ; y < winy ; y++ )
      	{
      		o.fill( 0.0 , 0.0 , -1000 ) ;
      		d.fill( (double)x ,
					 (double)y , 1000 ) ;
				  color = render( o, d , 7 ).toColor() 
      	  pixel[y][x].r = color & 255 ;
      	  pixel[y][x].g = ( color >> 8 ) & 255 ;
      	  pixel[y][x].b = ( color >> 16 ) & 255 ;
      	  pixel[y][x].a = 255 ;
      	  SetPixel( hdc , x , y , color ) ;
			  }
			}
			
			saveBMP( "WHITE-sphere.bmp" 
			, pixel , winx , winy ) ;
			
			EndPaint( hwnd , & ps ) ;			
		  break ;

		/* Upon destruction, tell the main thread to stop */
		case WM_DESTROY : {
			PostQuitMessage( 0 ) ;
			break ;
		}
		
		/* All other messages (a lot of them) are processed using default procedures */
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);
	}
	return 0;
}

/* The 'main' function of Win32 GUI programs: this is where execution starts */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc; /* A properties struct of our window */
	HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */
	MSG msg; /* A temporary location for all messages */

	/* zero out the struct and set the stuff we want to modify */
	memset(&wc,0,sizeof(wc));
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.lpfnWndProc	 = WndProc; /* This is where we will send messages to */
	wc.hInstance	 = hInstance;
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	
	/* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszClassName = "WindowClass";
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION); /* Load a standard icon */
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION); /* use the name "A" to use the project icon */

	if(!RegisterClassEx(&wc)) {
		MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, /* x */
		CW_USEDEFAULT, /* y */
		winx, /* width */
		winy, /* height */
		NULL,NULL,hInstance,NULL);

	if(hwnd == NULL) {
		MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	/*
		This is the heart of our program where all input is processed and 
		sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
		this loop will not produce unreasonably high CPU usage
	*/
	while(GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
		TranslateMessage(&msg); /* Translate key codes to chars if present */
		DispatchMessage(&msg); /* Send it to WndProc */
	}
	return msg.wParam;
}
 
raytracer

update :
m44 [ matrix ] class toegevoegd
3d engine toegevoegd
kleur constanten toegevoegd

ik denk niet dat het nu helemaal klopt
alle help is welkom

Code:
// bluatigro 1 okt 2017
// windows raytracer 0.2
 
#include <windows.h>
#include <string>
#include <math.h>
#include <tchar.h>
 
const int winx = 800 ;
const int winy = 600 ;

#define SMALL 1e-300
#define PI = 3.1415929203

// double3d
class d3d
{
public :
  double x , y , z ;
  d3d()
  {
    x = 0.0 ;
    y = 0.0 ;
    z = 0.0 ;
  }
  d3d( double X , double Y , double Z )
  {
    x = X ;
    y = Y ;
    z = Z ;
  }
  void fill( double X , double Y , double Z )
  {
    x = X ;
    y = Y ;
    z = Z ;
  }
  unsigned long toColor()
  {
    return (unsigned long)
      ( floor( x * 255 ) +
        floor( y * 255 ) * 256 +
        floor( z * 255 ) * 256 * 256 ) ;
  }
} ;
d3d operator + ( d3d a , d3d b )
{
  return d3d( a.x + b.x ,
              a.y + b.y ,
              a.z + b.z ) ;
}
d3d operator - ( d3d a , d3d b )
{
  return d3d( a.x - b.x ,
              a.y - b.y ,
              a.z - b.z ) ;
}
d3d operator / ( d3d a , double b )
{
  return d3d( a.x / b ,
              a.y / b ,
              a.z / b ) ;
}
d3d operator * ( d3d a , double b )
{
  return d3d( a.x * b ,
              a.y * b ,
              a.z * b ) ;
}
double dot( d3d a , d3d b )
{
  return a.x * b.x
       + a.y * b.y
       + a.z * b.z ;
}
double length( d3d a )
{
  return sqrt( dot( a , a ) ) ;
}
d3d normalize( d3d a )
{
  return a / length( a ) ;
}
double getAngle( d3d a , d3d b )
{
  double d , la , lb ;
  d = dot( a , b ) ;
  la = length( a ) ;
  lb = length( b ) ;
  return acos( d / ( la * lb ) ) ;
}
d3d cross( d3d a , d3d b )
{
   return d3d( a.y * b.z - a.z * b.y ,
               a.z * b.x - a.x * b.z ,
               a.x * b.y - a.y * b.x ) ;
}
// primary colors
const d3d BLACK   = d3d( 0.0 , 0.0 , 0.0 ) ;
const d3d RED     = d3d( 1.0 , 0.0 , 0.0 ) ;
const d3d GREEN   = d3d( 0.0 , 1.0 , 0.0 ) ;
const d3d YELLOW  = d3d( 1.0 , 1.0 , 0.0 ) ;
const d3d BLUE    = d3d( 0.0 , 0.0 , 1.0 ) ;
const d3d MAGENTA = d3d( 1.0 , 0.0 , 1.0 ) ;
const d3d CYAN    = d3d( 0.0 , 1.0 , 1.0 ) ;
const d3d WHITE   = d3d( 1.0 , 1.0 , 1.0 ) ;
// mix colors
const d3d GRAY    = WHITE / 2.0 ;
const d3d ORANGE  = ( YELLOW + RED ) / 2.0 ;
const d3d PINK    = ( WHITE + RED ) / 2.0 ;

// matrix
class m44
{
public :
  double m[ 4 ][ 4 ] ;
  m44()
  {
    int i , j ;
    for ( i = 0 ; i < 4 ; i++ )
    {
      for ( j = 0 ; j < 4 ; j++ )
        m[ i ][ j ] = 0.0 ;
      m[ i ][ i ] = 1.0 ;
    }
  }
  ~m44()
  {
    // here : give memory back
  }
  void translate( double x , double y , double z )
  {
    m[ 3 ][ 0 ] = x ;
    m[ 3 ][ 1 ] = y ;
    m[ 3 ][ 2 ] = z ;
  }
  void rotate( double deg , int ax )
  {
    int a = 1 , b = 2 ;
    if ( ax == 1 )
    {
      a = 0 ;
      b = 2 ;
    }
    if ( ax == 2 )
    {
      a = 0 ;
      b = 1 ;
    }
    m[ a ][ a ] = cos( deg * PI / 180 ) ;
    m[ a ][ b ] = -sin( deg * PI / 180 ) ; 
    m[ b ][ a ] = sin( deg * PI / 180 ) ;
    m[ b ][ b ] = cos( deg * PI / 180 ) ;
  }
} ;
m44 operator * ( m44 a , m44 b )
{
  int i , j , k ;
  m44 uit ;
  for ( i = 0 ; i < 4 ; i++ )
  {
    for ( j = 0 ; j < 4 ; j++ )
    {
      uit.m[ i ][ j ] = 0.0 ;
      for ( k = 0 ; k < 4 ; k++ )
        uit.m[ i ][ j ] += a.m[ i ][ k ] * b.m[ k ][ j ] ;
    }
  }
  return uit ;
}
d3d operator * ( m44 m , d3d v )
{
  return d3d( m.m[0][0]*v.x+m.m[1][0]*v.y+m.m[2][0]+m.m[3][0] 
            , m.m[0][1]*v.x+m.m[1][1]*v.y+m.m[2][1]+m.m[3][1]
            , m.m[0][2]*v.x+m.m[1][2]*v.y+m.m[2][2]+m.m[3][2]); 
}
m44 inverse( m44 a )
{
// only rotation matrix
  double d ;
  m44 uit ;
  
  d = q.m[0][0]*q.m[1][1]*q.m[2][2] 
    - q.m[0][0]*q.m[2][1]*q.m[1][2] 
    + q.m[1][0]*q.m[2][1]*q.m[0][2] 
    - q.m[1][0]*q.m[0][1]*q.m[2][2] 
    + q.m[2][0]*q.m[0][1]*q.m[1][2] 
    - q.m[2][0]*q.m[1][1]*q.m[0][2] ;
    
  uit.m[0][0]=(q.m[1][1)*q.m[2][2]-q.m[1][2]*q.m[2][1])/d;
  uit.m[1][0]=(q.m[0][1)*q.m[2][2]-q.m[0][2]*q.m[2][1])/d;
  uit.m[2][0]=(q.m[0][1)*q.m[1][2]-q.m[0][2]*q.m[1][1])/d;
  uit.m[0][1]=(q.m[1][0)*q.m[2][2]-q.m[1][2]*q.m[2][0])/d;
  uit.m[1][1]=(q.m[0][0)*q.m[2][2]-q.m[0][2]*q.m[2][0])/d;
  uit.m[2][1]=(q.m[0][0)*q.m[1][2]-q.m[0][2]*q.m[1][0])/d;
  uit.m[0][2]=(q.m[1][0)*q.m[2][1]-q.m[1][1]*q.m[2][0])/d;
  uit.m[1][2]=(q.m[0][0)*q.m[2][1]-q.m[0][1]*q.m[2][0])/d;
  uit.m[2][2]=(q.m[0][0)*q.m[1][1]-q.m[0][1]*q.m[1][2])/d;
  
  return uit ;
}

// 3d engine

d3d SK[ 64 ] ;
m44 V[ 20 ] ;
int number ;
const int XYZ = 0 ;
const int XZY = 1 ;
const int YXZ = 2 ;
const int YZX = 3 ;
const int ZXY = 4 ;
const int ZYX = 5 ;

void link( int no , double x , double y , double z
, double pan , double tilt , double rol , int ax , int p )
{
// create a new matrix
// will afect furture drawings

  if ( no < 1 ) return ;
  if ( no >= 20 ) return ;
  if ( p < 0 ) return ;
  if ( p >= 20 ) return ;
  if ( p == no ) return ;
  
  m44 trans , rotx , roty , rotz ;
  trans.translate( x , y , z ) ;
  rotx.rotate( tilt , 0 ) ;
  roty.rotate( pan , 1 ) ;
  rotz.rotate( rol , 2 ) ;

  switch( ax )
  {
    case XYZ :
      V[ no ] = rotx * roty * rotz * trans * V[ p ] ;
    break ;
    case XZY :
      V[ no ] = rotx * rotz * roty * trans * V[ p ] ;
    break ;
    case YXZ :
      V[ no ] = roty * rotx * rotz * trans * V[ p ] ;
    break ;
    case YZX :
      V[ no ] = roty * rotz * rotx * trans * V[ p ] ;
    break ;
    case ZXY :
      V[ no ] = rotz * rotx * roty * trans * V[ p ] ;
    break ;
    case ZYX :
      V[ no ] = rotz * roty * rotx * trans * V[ p ] ;
    break ;
    default :
      V[ no ] = rotx * roty * rotz * trans * V[ p ] ;
  }  
  number = no ;
}

void child( int no , doube x , double y , double z
, int lim , int ax , int p )
{
// create a lim matrix
// for animated avatar building

  if ( lim < 0 ) then return ;
  if ( lim >= 64 ) then return ;
  link( no , x , y , z
  , SK[ lim ].y , SK[ lim ].x , SK[ lim ].z
  , ax , p ) ;
}

void skelet( int lim , double x , double y , double z )
{
// set the angles [ in degees ] 
// of a lim of a avartar

  if ( lim < 0 ) return ;
  if ( lim >= 64 ) return ;
  SK[ lim ].fill( x , y , z ) ;
}

double pend( double fase , double amp )
{
// for smooth animations

  return sin( fase * PI / 180 ) * amp ;
}

d3d spot( d3d q )
{
// from lokal to world coordinates

  return V[ number ] * q ;
}

// end 3d engine

struct Matrial
{
  d3d diffuse ;
  double reflection ;
} ;
Matrial material ;
 
class Sphere
{
public :
  d3d center ;
  double radius , radius2 ;
  Matrial mat ;
  void fill( d3d c , double r )
  {
    center = spot( c ) ;
    radius = r ;
    radius2 = r * r ;
    mat = material ;
  }
  double hit( d3d o , d3d d )
  {
    double t , a , b , c , disc ;
    d3d temp = o - center ;
    a = dot( d , d ) ;
    b = 2 * dot( temp , d ) ;
    c = dot( temp , temp ) - radius2 ;
    disc = b * b - 4 * a * c ;
    if ( disc < 0 )
      return INFINITY;
    else
    {
      double e = sqrt( disc ) ;
      double demon = 2 * a ;
      t = ( -b - e ) / demon ;
      if ( t > SMALL ) return t ;
      t = ( -b + e ) / demon ;
      if ( t > SMALL ) return t ;
    }
    return INFINITY ;
  }
} ;
 
Sphere spheres[ 100 ] ;
int spheretel ;
void sphere( double x , double y , double z
           , double r , d3d color )
{
  d3d pt ;
  pt.fill( x , y , z ) ;
  material.diffuse = color ;
  spheres[ spheretel ].fill( pt , r ) ;
  spheretel++ ;
}
 
d3d light;
 
d3d render( d3d o , d3d d , int depth )
{
  double dist , sphdist = INFINITY ;
  int i , isph = -1 ;
  for ( i = 0 ; i < spheretel ; i++ )
  {
    dist = spheres[ i ].hit( o , d ) ;
    if ( dist < sphdist )
    {
      sphdist = dist ;
      isph = i ;
    }
  }
  if (isph == -1) return BLACK ;
  d3d p , n ;
  p = o + d * sphdist ;
  n = p - spheres[ isph ].center ;
  double a = getAngle( n , light ) ;
  d3d color = spheres[ isph ].mat.diffuse ;
  color = color * ( 0.5 + cos( a * 2 ) / 2 ) ;
  if ( a > PI / 2 ) color = BLACK ;
  for ( i = 0 ; i < spheretel ; i++ )
  {
    if ( i != isph )
    {
      a = spheres[ i ].hit( p , light ) ;
      if ( a == INFINITY ) color = BLACK ;
    }
  }
  return color ;
}

char * frame( char * filmname , int no , int len )
{
  /*
  this is [ in basic ] what i want to do :
  return filmname 
  + right( "00000000" + str( no ) , len ) 
  + ".bmp" ;
  */
}
 
int CaptureAnImage( HWND hWnd , char* filename )
{
	HDC hdcScreen;
	HDC hdcWindow;
	HDC hdcMemDC = NULL;
	HBITMAP hbmScreen = NULL;
	BITMAP bmpScreen;
 
	// Retrieve the handle to a display device context for the client 
	// area of the window. 
	hdcScreen = GetDC(NULL);
	hdcWindow = GetDC(hWnd);
 
	// Create a compatible DC which is used in a BitBlt from the window DC
	hdcMemDC = CreateCompatibleDC(hdcWindow);
 
	if (!hdcMemDC)
	{
		MessageBox(hWnd, _T("CreateCompatibleDC has failed"), _T("Failed"), MB_OK);
		goto done;
	}
 
	// Get the client area for size calculation
	RECT rcClient;
	GetClientRect(hWnd, &rcClient);
 
	//This is the best stretch mode
	SetStretchBltMode(hdcWindow, HALFTONE);
 
	//The source DC is the entire screen and the destination DC is the current window (HWND)
	if (!StretchBlt(hdcWindow,
		0, 0,
		rcClient.right, rcClient.bottom,
		hdcScreen,
		0, 0,
		GetSystemMetrics(SM_CXSCREEN),
		GetSystemMetrics(SM_CYSCREEN),
		SRCCOPY))
	{
		MessageBox(hWnd, _T("StretchBlt has failed"), _T("Failed"), MB_OK);
		goto done;
	}
 
	// Create a compatible bitmap from the Window DC
	hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
 
	if (!hbmScreen)
	{
		MessageBox(hWnd, _T("CreateCompatibleBitmap Failed"), _T("Failed"), MB_OK);
		goto done;
	}
 
	// Select the compatible bitmap into the compatible memory DC.
	SelectObject(hdcMemDC, hbmScreen);
 
	// Bit block transfer into our compatible memory DC.
	if (!BitBlt(hdcMemDC,
		0, 0,
		rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
		hdcWindow,
		0, 0,
		SRCCOPY))
	{
		MessageBox(hWnd, _T("BitBlt has failed"), _T("Failed"), MB_OK);
		goto done;
	}
 
	// Get the BITMAP from the HBITMAP
	GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);
 
	BITMAPFILEHEADER   bmfHeader;
	BITMAPINFOHEADER   bi;
 
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = bmpScreen.bmWidth;
	bi.biHeight = bmpScreen.bmHeight;
	bi.biPlanes = 1;
	bi.biBitCount = 32;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;
 
	DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
 
	// Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
	// call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 
	// have greater overhead than HeapAlloc.
	HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
	char *lpbitmap = (char *)GlobalLock(hDIB);
 
	// Gets the "bits" from the bitmap and copies them into a buffer 
	// which is pointed to by lpbitmap.
	GetDIBits(hdcWindow, hbmScreen, 0,
		(UINT)bmpScreen.bmHeight,
		lpbitmap,
		(BITMAPINFO *)&bi, DIB_RGB_COLORS);
 
	// A file is created, this is where we will save the screen capture.
	HANDLE hFile = CreateFile(filename,
		GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL, NULL);
 
	// Add the size of the headers to the size of the bitmap to get the total file size
	DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
 
	//Offset to where the actual bitmap bits start.
	bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
 
	//Size of the file
	bmfHeader.bfSize = dwSizeofDIB;
 
	//bfType must always be BM for Bitmaps
	bmfHeader.bfType = 0x4D42; //BM   
 
	DWORD dwBytesWritten = 0;
	WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
	WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
	WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
 
	//Unlock and Free the DIB from the heap
	GlobalUnlock(hDIB);
	GlobalFree(hDIB);
 
	//Close the handle for the file that was created
	CloseHandle(hFile);
 
	//Clean up
done:
	DeleteObject(hbmScreen);
	DeleteObject(hdcMemDC);
	ReleaseDC(NULL, hdcScreen);
	ReleaseDC(hWnd, hdcWindow);
 
	return 0;
}
 
/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc( HWND hwnd , 
                          UINT Message , 
                          WPARAM wParam ,
                          LPARAM lParam ) 
{
  HDC hdc ;
  PAINTSTRUCT ps ;
 
  switch (Message)
  {
    case WM_PAINT : 
    {
      int x , y , picno ;
      d3d o , d ; 
      unsigned long color ;
      hdc = BeginPaint( hwnd , &ps ) ;
      //film
//      for ( picno = 0 ; picno < 32 ; picno )
//      {
      //scene
      spheretel = 0 ;
      light.fill( -1.0 , 1.0 , -1.0 ) ;
      link( 1 , 0.0 , 0.0 , 0.0 
      , (double)picno * 360 / 16 , 0.0 , 0.0 , XYZ , 0 ) ;
      sphere( 0.0 , 100.0 , 0.0 , 100.0 , MAGENTA ) ;
      sphere( -50.0 , -86.0 , 0.0 , 100.0 , CYAN ) ;
      sphere( 50.0 , -86.0 , 0.0 , 100.0 , YELLOW ) ;
      sphere( 0.0 , -INFINITY - winy / 2 , 0.0
        , INFINITY , WHITE ) ;
		
      //create scene on window
      for ( x = 0 ; x < winx ; x++ )
      {
        for ( y = 0 ; y < winy ; y++ )
        {
          o.fill( 0.0 , 0.0 , -1000.0 ) ;
          d.fill( (double)x , (double)y , 1000.0 ) ;
	  color = render( o , d , 7 ).toColor() ;
          SetPixel( hdc , x , y , color ) ;
        }
      } // end of drawing frame

      int dummy = CaptureAnImage( hwnd , 
        _T( "sphere-3.bmp" ) ;

//      } //end film loop

      EndPaint( hwnd , &ps ) ;
      break ;
    }
/* Upon destruction, tell the main thread to stop */
    case WM_DESTROY : 
    {
      PostQuitMessage( 0 ) ;
      break ;
    }
/* All other messages (a lot of them) are processed using default procedures */
    default :
      return DefWindowProc(hwnd, Message, wParam, lParam);
  }
  return 0 ;
}
 
/* The 'main' function of Win32 GUI programs: this is where execution starts */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc; /* A properties struct of our window */
	HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */
	MSG msg; /* A temporary location for all messages */
 
			 /* zero out the struct and set the stuff we want to modify */
	memset(&wc, 0, sizeof(wc));
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.lpfnWndProc = WndProc; /* This is where we will send messages to */
	wc.hInstance = hInstance;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
 
	/* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.lpszClassName = "WindowClass";
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* Load a standard icon */
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* use the name "A" to use the project icon */
 
	if (!RegisterClassEx(&wc)) {
		MessageBox(NULL, _T("Window Registration Failed!"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
 
	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, _T("WindowClass"), _T("Caption"), WS_VISIBLE | WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, /* x */
		CW_USEDEFAULT, /* y */
		winx, /* width */
		winy, /* height */
		NULL, NULL, hInstance, NULL);
 
	if (hwnd == NULL) {
		MessageBox(NULL, _T("Window Creation Failed!"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
 
	/*
	This is the heart of our program where all input is processed and
	sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
	this loop will not produce unreasonably high CPU usage
	*/
	while (GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
		TranslateMessage(&msg); /* Translate key codes to chars if present */
		DispatchMessage(&msg); /* Send it to WndProc */
	}
	return msg.wParam;
}
 
raytracer

update :
avatar + animation toegevoegd

Code:
// bluatigro 1 okt 2017
// windows raytracer 0.3
 
#include <windows.h>
#include <string>
#include <math.h>
#include <tchar.h>
 
const int winx = 800 ;
const int winy = 600 ;

#define SMALL 1e-300
#define PI = 3.14159265358979323846

// double3d
class d3d
{
public :
  double x , y , z ;
  d3d()
  {
    x = 0.0 ;
    y = 0.0 ;
    z = 0.0 ;
  }
  d3d( double X , double Y , double Z )
  {
    x = X ;
    y = Y ;
    z = Z ;
  }
  void fill( double X , double Y , double Z )
  {
    x = X ;
    y = Y ;
    z = Z ;
  }
  unsigned long toColor()
  {
    return (unsigned long)
      ( floor( x * 255 ) +
        floor( y * 255 ) * 256 +
        floor( z * 255 ) * 256 * 256 ) ;
  }
} ;
d3d operator + ( d3d a , d3d b )
{
  return d3d( a.x + b.x ,
              a.y + b.y ,
              a.z + b.z ) ;
}
d3d operator - ( d3d a , d3d b )
{
  return d3d( a.x - b.x ,
              a.y - b.y ,
              a.z - b.z ) ;
}
d3d operator / ( d3d a , double b )
{
  return d3d( a.x / b ,
              a.y / b ,
              a.z / b ) ;
}
d3d operator * ( d3d a , double b )
{
  return d3d( a.x * b ,
              a.y * b ,
              a.z * b ) ;
}
double dot( d3d a , d3d b )
{
  return a.x * b.x
       + a.y * b.y
       + a.z * b.z ;
}
double length( d3d a )
{
  return sqrt( dot( a , a ) ) ;
}
d3d normalize( d3d a )
{
  return a / length( a ) ;
}
double getAngle( d3d a , d3d b )
{
  double d , la , lb ;
  d = dot( a , b ) ;
  la = length( a ) ;
  lb = length( b ) ;
  return acos( d / ( la * lb ) ) ;
}
d3d cross( d3d a , d3d b )
{
   return d3d( a.y * b.z - a.z * b.y ,
               a.z * b.x - a.x * b.z ,
               a.x * b.y - a.y * b.x ) ;
}
// primary colors
const d3d BLACK   = d3d( 0.0 , 0.0 , 0.0 ) ;
const d3d RED     = d3d( 1.0 , 0.0 , 0.0 ) ;
const d3d GREEN   = d3d( 0.0 , 1.0 , 0.0 ) ;
const d3d YELLOW  = d3d( 1.0 , 1.0 , 0.0 ) ;
const d3d BLUE    = d3d( 0.0 , 0.0 , 1.0 ) ;
const d3d MAGENTA = d3d( 1.0 , 0.0 , 1.0 ) ;
const d3d CYAN    = d3d( 0.0 , 1.0 , 1.0 ) ;
const d3d WHITE   = d3d( 1.0 , 1.0 , 1.0 ) ;
// mix colors
const d3d GRAY    = WHITE / 2.0 ;
const d3d ORANGE  = ( YELLOW + RED ) / 2.0 ;
const d3d PINK    = ( WHITE + RED ) / 2.0 ;

// matrix
class m44
{
public :
  double m[ 4 ][ 4 ] ;
  m44()
  {
    int i , j ;
    for ( i = 0 ; i < 4 ; i++ )
    {
      for ( j = 0 ; j < 4 ; j++ )
        m[ i ][ j ] = 0.0 ;
      m[ i ][ i ] = 1.0 ;
    }
  }
  ~m44()
  {
    // here : give memory back
  }
  void translate( double x , double y , double z )
  {
    m[ 3 ][ 0 ] = x ;
    m[ 3 ][ 1 ] = y ;
    m[ 3 ][ 2 ] = z ;
  }
  void rotate( double deg , int ax )
  {
    int a = 1 , b = 2 ;
    if ( ax == 1 )
    {
      a = 0 ;
      b = 2 ;
    }
    if ( ax == 2 )
    {
      a = 0 ;
      b = 1 ;
    }
    m[ a ][ a ] = cos( deg * PI / 180 ) ;
    m[ a ][ b ] = -sin( deg * PI / 180 ) ; 
    m[ b ][ a ] = sin( deg * PI / 180 ) ;
    m[ b ][ b ] = cos( deg * PI / 180 ) ;
  }
} ;
m44 operator * ( m44 a , m44 b )
{
  int i , j , k ;
  m44 uit ;
  for ( i = 0 ; i < 4 ; i++ )
  {
    for ( j = 0 ; j < 4 ; j++ )
    {
      uit.m[ i ][ j ] = 0.0 ;
      for ( k = 0 ; k < 4 ; k++ )
        uit.m[ i ][ j ] += a.m[ i ][ k ] * b.m[ k ][ j ] ;
    }
  }
  return uit ;
}
d3d operator * ( m44 m , d3d v )
{
  return d3d( m.m[0][0]*v.x+m.m[1][0]*v.y+m.m[2][0]+m.m[3][0] 
            , m.m[0][1]*v.x+m.m[1][1]*v.y+m.m[2][1]+m.m[3][1]
            , m.m[0][2]*v.x+m.m[1][2]*v.y+m.m[2][2]+m.m[3][2]); 
}
m44 inverse( m44 a )
{
// only rotation matrix
  double d ;
  m44 uit ;
  
  d = q.m[0][0]*q.m[1][1]*q.m[2][2] 
    - q.m[0][0]*q.m[2][1]*q.m[1][2] 
    + q.m[1][0]*q.m[2][1]*q.m[0][2] 
    - q.m[1][0]*q.m[0][1]*q.m[2][2] 
    + q.m[2][0]*q.m[0][1]*q.m[1][2] 
    - q.m[2][0]*q.m[1][1]*q.m[0][2] ;
    
  uit.m[0][0]=(q.m[1][1)*q.m[2][2]-q.m[1][2]*q.m[2][1])/d;
  uit.m[1][0]=(q.m[0][1)*q.m[2][2]-q.m[0][2]*q.m[2][1])/d;
  uit.m[2][0]=(q.m[0][1)*q.m[1][2]-q.m[0][2]*q.m[1][1])/d;
  uit.m[0][1]=(q.m[1][0)*q.m[2][2]-q.m[1][2]*q.m[2][0])/d;
  uit.m[1][1]=(q.m[0][0)*q.m[2][2]-q.m[0][2]*q.m[2][0])/d;
  uit.m[2][1]=(q.m[0][0)*q.m[1][2]-q.m[0][2]*q.m[1][0])/d;
  uit.m[0][2]=(q.m[1][0)*q.m[2][1]-q.m[1][1]*q.m[2][0])/d;
  uit.m[1][2]=(q.m[0][0)*q.m[2][1]-q.m[0][1]*q.m[2][0])/d;
  uit.m[2][2]=(q.m[0][0)*q.m[1][1]-q.m[0][1]*q.m[1][2])/d;
  
  return uit ;
}

// 3d engine

d3d SK[ 64 ] ;
m44 V[ 20 ] ;
int number ;
const int XYZ = 0 ;
const int XZY = 1 ;
const int YXZ = 2 ;
const int YZX = 3 ;
const int ZXY = 4 ;
const int ZYX = 5 ;

void link( int no , double x , double y , double z
, double pan , double tilt , double rol , int ax , int p )
{
// create a new matrix
// will afect furture drawings

  if ( no < 1 ) return ;
  if ( no >= 20 ) return ;
  if ( p < 0 ) return ;
  if ( p >= 20 ) return ;
  if ( p == no ) return ;
  
  m44 trans , rotx , roty , rotz ;
  trans.translate( x , y , z ) ;
  rotx.rotate( tilt , 0 ) ;
  roty.rotate( pan , 1 ) ;
  rotz.rotate( rol , 2 ) ;

  switch( ax )
  {
    case XYZ :
      V[ no ] = rotx * roty * rotz * trans * V[ p ] ;
    break ;
    case XZY :
      V[ no ] = rotx * rotz * roty * trans * V[ p ] ;
    break ;
    case YXZ :
      V[ no ] = roty * rotx * rotz * trans * V[ p ] ;
    break ;
    case YZX :
      V[ no ] = roty * rotz * rotx * trans * V[ p ] ;
    break ;
    case ZXY :
      V[ no ] = rotz * rotx * roty * trans * V[ p ] ;
    break ;
    case ZYX :
      V[ no ] = rotz * roty * rotx * trans * V[ p ] ;
    break ;
    default :
      V[ no ] = rotx * roty * rotz * trans * V[ p ] ;
  }  
  number = no ;
}

void child( int no , doube x , double y , double z
, int lim , int ax , int p )
{
// create a lim matrix
// for animated avatar building

  if ( lim < 0 ) then return ;
  if ( lim >= 64 ) then return ;
  link( no , x , y , z
  , SK[ lim ].y , SK[ lim ].x , SK[ lim ].z
  , ax , p ) ;
}

void skelet( int lim , double x , double y , double z )
{
// set the angles [ in degees ] 
// of a lim of a avartar

  if ( lim < 0 ) return ;
  if ( lim >= 64 ) return ;
  SK[ lim ].fill( x , y , z ) ;
}

double pend( double fase , double amp )
{
// for smooth animations

  return sin( fase * PI / 180 ) * amp ;
}

d3d spot( d3d q )
{
// from lokal to world coordinates

  return V[ number ] * q ;
}

// end 3d engine

struct Matrial
{
  d3d diffuse ;
  double reflection ;
} ;
Matrial material ;
 
class Sphere
{
public :
  d3d center ;
  double radius , radius2 ;
  Matrial mat ;
  void fill( d3d c , double r )
  {
    center = spot( c ) ;
    radius = r ;
    radius2 = r * r ;
    mat = material ;
  }
  double hit( d3d o , d3d d )
  {
    double t , a , b , c , disc ;
    d3d temp = o - center ;
    a = dot( d , d ) ;
    b = 2 * dot( temp , d ) ;
    c = dot( temp , temp ) - radius2 ;
    disc = b * b - 4 * a * c ;
    if ( disc < 0 )
      return INFINITY;
    else
    {
      double e = sqrt( disc ) ;
      double demon = 2 * a ;
      t = ( -b - e ) / demon ;
      if ( t > SMALL ) return t ;
      t = ( -b + e ) / demon ;
      if ( t > SMALL ) return t ;
    }
    return INFINITY ;
  }
} ;
 
Sphere spheres[ 100 ] ;
int spheretel ;
void sphere( double x , double y , double z
           , double r , d3d color )
{
  d3d pt ;
  pt.fill( x , y , z ) ;
  material.diffuse = color ;
  spheres[ spheretel ].fill( pt , r ) ;
  spheretel++ ;
}
 
d3d light;
 
d3d render( d3d o , d3d d , int depth )
{
  double dist , sphdist = INFINITY ;
  int i , isph = -1 ;
  for ( i = 0 ; i < spheretel ; i++ )
  {
    dist = spheres[ i ].hit( o , d ) ;
    if ( dist < sphdist )
    {
      sphdist = dist ;
      isph = i ;
    }
  }
  if (isph == -1) return BLACK ;
  d3d p , n ;
  p = o + d * sphdist ;
  n = p - spheres[ isph ].center ;
  double a = getAngle( n , light ) ;
  d3d color = spheres[ isph ].mat.diffuse ;
  color = color * ( 0.5 + cos( a * 2 ) / 2 ) ;
  if ( a > PI / 2 ) color = BLACK ;
  for ( i = 0 ; i < spheretel ; i++ )
  {
    if ( i != isph )
    {
      a = spheres[ i ].hit( p , light ) ;
      if ( a == INFINITY ) color = BLACK ;
    }
  }
  return color ;
}

// lim consts for avatar
const int arm   = 1 ;
const int elbow = 2 ;
const int wrist = 3 ;
const int leg   = 4 ;
const int knee  = 5 ;
const int enkle = 6 ;
const int neck  = 7 ;
const int eye   = 8 ;
const int wenk  = 9 ;
const int tail  = 10 ;
const int thumb = 11 ;
const int index = 14 ;
const int midle = 17 ;
const int ring  = 20 ;
const int lr    = 32 ;

void Kop( int qq , d3d kl )
{
    link( 15, 0, 0, 0, 0, 0, 0, xyz, number ) ;
        sphere( 0, 0, 0, 30, kl ) ;
    if ( qq == 1 ) 
    {
        sphere( 25, 25, 0, 9, kl ) ;
        sphere( -25, 25, 0, 9, kl ) ;
        sphere( 0, 0, -40, 12, GRAY ) ;
    }
    else
    {
        sphere( 30, 0, 0, 9, kl ) ;
        sphere( -30, 0, 0, 9, kl ) ;
        sphere( 0, 0, -40, 12, kl ) ;
    }
    child( 16, 14, 14, -14, eye , xyz, 15 ) ;
        sphere( 0, 0, 0, 13, WHITE ) ;
        sphere( 0, 0, -10, 7, BLACK ) ;
    child( 16, -14, 14, -14, eye + lr, xyz, 15 ) ;
        sphere( 0, 0, 0, 13, WHITE ) ;
        sphere( 0, 0, -10, 7, BLACK ) ;
}

void human( trui as d3d , broek as d3d )
{
// example of a avatar
// has a skeleton whith can be animated
    link( 9 , 0,0,0 , 0,0,0 , xyz , number ) ;
        sphere( 0, 50, 0, 30, trui ) ;
        sphere( 0, 25, 0, 23, broek ) ;
        sphere( 0, 0, 0, 15, broek ) ;
    child( 11, 0, 70, 0, neck, xyz, 9 ) ;
    child( 12, 0, 30, 0, neck+lr, xyz, 11 ) ;
        Kop( 0, PINK ) ;
    child( 11, 20, -10, 0, leg, yzx, 9 ) ;
        sphere( 0, 0, 0, 16, broek ) ;
        sphere( 0, -20, 0, 16, broek ) ;
    child( 12, 0, -40, 0, knee, xyz, 11 ) ;
        sphere( 0, 0, 0, 16, broek ) ;
        sphere( 0, -20, 0, 16, broek ) ;
    child( 13, 0, -40, 0, enkle, xzy, 12 ) ;
        sphere( 0, 0, 0, 12, GRAY ) ;
        sphere( 0, 0, -20, 12, GRAY ) ;
    child( 11, -20, -10, 0, leg+lr , yzx, 9 ) ;
        sphere( 0, 0, 0, 16, broek ) ;
        sphere( 0, -20, 0, 16, broek ) ;
    child( 12, 0, -40, 0, knee+lr, xyz, 11 ) ;
        sphere( 0, 0, 0, 16, broek ) ;
        sphere( 0, -20, 0,16, broek ) ;
    child( 13, 0, -40, 0,enkle+lr, xzy, 12 ) ;
        sphere( 0, 0, 0, 12, GRAY ) ;
        sphere( 0, 0, -20, 12, GRAY ) ;
    child( 11, 40, 60, 0, arm, xzy, 9 ) ;
        sphere( 0, 0, 0, 16, trui ) ;
        sphere( 6, -20, 0, 12, trui ) ;
    child( 12, 6, -40, 0, elbow, xyz, 11 ) ;
        sphere( 0, 0, 0, 12, trui ) ;
        sphere( 0, -20, 0, 12, trui ) ;
        sphere( 0, -42, 0, 8, PINK ) ;
    child( 11, -40, 60, 0, arm+lr, xzy, 9 ) ;
        sphere( 0, 0, 0, 16, trui ) ;
        sphere( -6, -20, 0, 12, trui ) ;
    child( 12, -6, -40, 0, elbow+lr, xyz, 11 ) ;
        sphere( 0, 0, 0, 12, trui ) ;
        sphere( 0, -20, 0, 12, trui ) ;
        sphere( 0, -42, 0, 8, PINK ) ;
} // end human avatar

void human_walk( f as double , a as double )
{
// example of a animation
    skelet( arm , pend( f , a ) , 0 , 0 ) ;
    skelet( elbow , -abs( a ) , 0 , 0 ) ;
    skelet( arm + lr , pend( f + 180, a ) , 0 , 0 ) ;
    skelet( elbow + lr , -abs( a ) , 0 , 0 ) ;
    skelet( leg , pend( f + 180 , a ) , 0 , 0 ) ;
    skelet( knee , pend( f + 90 , a ) + a , 0 , 0 ) ;
    skelet( leg + lr , pend( f , a ) , 0 , 0 ) ;
    skelet( knee + lr , pend( f - 90 , a ) + a , 0 , 0 ) ;
}

void frameName ( TCHAR* buffer , 
                 int bufsize ,
                 const TCHAR* nameStart ,
                 const TCHAR* ext , 
                 int no , int len )
{
// format string must be ascii .. 
// do not change these 2 lines even on unicode
// I know its strange but thats the way it is .. 
// format strings are always ascii
  char fmtstring[ 32 ] ;	
  sprintf_s( fmtstring , _countof( fmtstring ) ,
    "%s%i%s" , "%s%0" , len , "i.%s" ) ;
// Okay now we swing unicode/ascii for actual string
  _stprintf_s( buffer , bufsize , 
    fmtstring , nameStart , no , ext ) ;
}

int CaptureAnImage( HWND hWnd , char* filename )
{
	HDC hdcScreen;
	HDC hdcWindow;
	HDC hdcMemDC = NULL;
	HBITMAP hbmScreen = NULL;
	BITMAP bmpScreen;
 
	// Retrieve the handle to a display device context for the client 
	// area of the window. 
	hdcScreen = GetDC(NULL);
	hdcWindow = GetDC(hWnd);
 
	// Create a compatible DC which is used in a BitBlt from the window DC
	hdcMemDC = CreateCompatibleDC(hdcWindow);
 
	if (!hdcMemDC)
	{
		MessageBox(hWnd, _T("CreateCompatibleDC has failed"), _T("Failed"), MB_OK);
		goto done;
	}
 
	// Get the client area for size calculation
	RECT rcClient;
	GetClientRect(hWnd, &rcClient);
 
	//This is the best stretch mode
	SetStretchBltMode(hdcWindow, HALFTONE);
 
	//The source DC is the entire screen and the destination DC is the current window (HWND)
	if (!StretchBlt(hdcWindow,
		0, 0,
		rcClient.right, rcClient.bottom,
		hdcScreen,
		0, 0,
		GetSystemMetrics(SM_CXSCREEN),
		GetSystemMetrics(SM_CYSCREEN),
		SRCCOPY))
	{
		MessageBox(hWnd, _T("StretchBlt has failed"), _T("Failed"), MB_OK);
		goto done;
	}
 
	// Create a compatible bitmap from the Window DC
	hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
 
	if (!hbmScreen)
	{
		MessageBox(hWnd, _T("CreateCompatibleBitmap Failed"), _T("Failed"), MB_OK);
		goto done;
	}
 
	// Select the compatible bitmap into the compatible memory DC.
	SelectObject(hdcMemDC, hbmScreen);
 
	// Bit block transfer into our compatible memory DC.
	if (!BitBlt(hdcMemDC,
		0, 0,
		rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
		hdcWindow,
		0, 0,
		SRCCOPY))
	{
		MessageBox(hWnd, _T("BitBlt has failed"), _T("Failed"), MB_OK);
		goto done;
	}
 
	// Get the BITMAP from the HBITMAP
	GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);
 
	BITMAPFILEHEADER   bmfHeader;
	BITMAPINFOHEADER   bi;
 
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = bmpScreen.bmWidth;
	bi.biHeight = bmpScreen.bmHeight;
	bi.biPlanes = 1;
	bi.biBitCount = 32;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;
 
	DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
 
	// Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
	// call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 
	// have greater overhead than HeapAlloc.
	HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
	char *lpbitmap = (char *)GlobalLock(hDIB);
 
	// Gets the "bits" from the bitmap and copies them into a buffer 
	// which is pointed to by lpbitmap.
	GetDIBits(hdcWindow, hbmScreen, 0,
		(UINT)bmpScreen.bmHeight,
		lpbitmap,
		(BITMAPINFO *)&bi, DIB_RGB_COLORS);
 
	// A file is created, this is where we will save the screen capture.
	HANDLE hFile = CreateFile(filename,
		GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL, NULL);
 
	// Add the size of the headers to the size of the bitmap to get the total file size
	DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
 
	//Offset to where the actual bitmap bits start.
	bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
 
	//Size of the file
	bmfHeader.bfSize = dwSizeofDIB;
 
	//bfType must always be BM for Bitmaps
	bmfHeader.bfType = 0x4D42; //BM   
 
	DWORD dwBytesWritten = 0;
	WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
	WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
	WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
 
	//Unlock and Free the DIB from the heap
	GlobalUnlock(hDIB);
	GlobalFree(hDIB);
 
	//Close the handle for the file that was created
	CloseHandle(hFile);
 
	//Clean up
done:
	DeleteObject(hbmScreen);
	DeleteObject(hdcMemDC);
	ReleaseDC(NULL, hdcScreen);
	ReleaseDC(hWnd, hdcWindow);
 
	return 0;
}
 
/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc( HWND hwnd , 
                          UINT Message , 
                          WPARAM wParam ,
                          LPARAM lParam ) 
{
  HDC hdc ;
  PAINTSTRUCT ps ;
 
  switch (Message)
  {
    case WM_PAINT : 
    {
      int x , y , picno ;
      d3d o , d ; 
      unsigned long color ;
      hdc = BeginPaint( hwnd , &ps ) ;
      //film
//      for ( picno = 0 ; picno < 32 ; picno++ )
//      {
      // scene
      // reset number of spheres
      spheretel = 0 ;
      // place light
      light.fill( -1.0 , 1.0 , -1.0 ) ;
      // place and rotate avatar
      link( 1 , 0.0 , 100 - winy / 2 , 0.0 , 
            30.0 , 0.0 , 0.0 , XYZ , 0 ) ;
      // animate avatar
      // human_walk( picno * 360.0 / 32 , 30 ) ;
      // draw avatar
      human( YELLOW , BLUE ) ;
      // draw ground
      sphere( 0.0 , -INFINITY - winy / 2 , 0.0
        , INFINITY , ( WHITE + GREEN ) / 2 ) ;
		
      //create scene on window
      for ( x = 0 ; x < winx ; x++ )
      {
        for ( y = 0 ; y < winy ; y++ )
        {
          o.fill( 0.0 , 0.0 , -1000.0 ) ;
          d.fill( (double)x , (double)y , 1000.0 ) ;
	  color = render( o , d , 7 ).toColor() ;
          SetPixel( hdc , x , y , color ) ;
        }
      } // end of drawing frame
//      TCHAR buf[ 256 ] ;
//      frameName( buf , _countof( buf ) , 
//        _T( "human" ) , _T( "bmp" ) , picno , 2 ) ; 
//        int dummy = CaptureAnImage( hwnd , _T( buf ) ;

//    } // end film loop

      EndPaint( hwnd , &ps ) ;
      break ;
    }
/* Upon destruction, tell the main thread to stop */
    case WM_DESTROY : 
    {
      PostQuitMessage( 0 ) ;
      break ;
    }
/* All other messages (a lot of them) are processed using default procedures */
    default :
      return DefWindowProc(hwnd, Message, wParam, lParam);
  }
  return 0 ;
}
 
/* The 'main' function of Win32 GUI programs: this is where execution starts */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc; /* A properties struct of our window */
	HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */
	MSG msg; /* A temporary location for all messages */
 
			 /* zero out the struct and set the stuff we want to modify */
	memset(&wc, 0, sizeof(wc));
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.lpfnWndProc = WndProc; /* This is where we will send messages to */
	wc.hInstance = hInstance;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
 
	/* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.lpszClassName = "WindowClass";
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* Load a standard icon */
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* use the name "A" to use the project icon */
 
	if (!RegisterClassEx(&wc)) {
		MessageBox(NULL, _T("Window Registration Failed!"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
 
	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, _T("WindowClass"), _T("Caption"), WS_VISIBLE | WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, /* x */
		CW_USEDEFAULT, /* y */
		winx, /* width */
		winy, /* height */
		NULL, NULL, hInstance, NULL);
 
	if (hwnd == NULL) {
		MessageBox(NULL, _T("Window Creation Failed!"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
 
	/*
	This is the heart of our program where all input is processed and
	sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
	this loop will not produce unreasonably high CPU usage
	*/
	while (GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
		TranslateMessage(&msg); /* Translate key codes to chars if present */
		DispatchMessage(&msg); /* Send it to WndProc */
	}
	return msg.wParam;
}
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan