Copy Link
Add to Bookmark
Report

fxtunray

eZine's profile picture
Published in 
2d3dfx
 · 3 years ago

Tunnel à direction libre

Encore une fois, ce tuteur traitera de tunnel. Cependant, ce qui rend la chose très différente cette fois-ci, c’est qu’on utilisera la technique du raytracing (traçage de rayons), et que cette technique permet de réaliser beaucoup plus que des tunnels (ie : des sphères, des plans, des polygones). Également, ce tuteur sera uniquement disponible sous format Win32, avec DirectX. Il va sans dire qu’une bonne connaissance des 2 premiers chapitres de la section Windows est impérative à la compréhension de ce document.

LA BASE DU RAYTRACING

Le raytracing est une technique de représentation 3D qui se base sur le comportement physique de la lumière. Dans le monde réel, la lumière émane des sources de lumière, touche les objets dans la scène, et après touche nos yeux. Mais comme il existe une infinité de rayons tracé à partir de chaque sources de lumière, il serait impossible d’appliquer cet algorithme. Nous allons donc nous contenter simplement des rayons qui touche nos yeux (ou caméra), en procédant de façon inverse : en lançant les rayons de la caméra, en vérifiant l’intersection avec des objets, puis ensuite avec les sources de lumières. Ce diagramme illustre ce principe :

fxtunray
Pin it

TEST D’INTERSECTIONS

Afin de déterminer si notre rayon imaginaire entre en intersection avec un objet, il faudra développer l’équation du rayon dans celle de l’objet dont nous vérifions l’intersection. Nous obtenons alors une équation quadratique, qui nous permettra de déterminer s’il y a collision. Tout d’abord, regardons l’équation du rayon :

camera + t * direction

Dans cette équation, « camera » est le vecteur d’origine (notre œil) du rayon, « direction » est un vecteur normalisé représentant la direction du rayon, et « t » est le temps que le rayon a traversé depuis son départ de l’origine.

À présent, il faut l’équation de l’objet avec lequel nous allons tester l’intersection. Dans le cas d’un tunnel, il s’agit en fait d’une série de cercles concentriques, qui possède l’équation (en supposant une origine de 0,0):

x^2 + y^2 = r^2

Comme mentionner plus haut, nous devons substituer les termes de l’équation du rayon dans ceux de l’objet (dans notre cas, un cercle) :

(camera.x + t*direction.x)^2 + (camera.y + t*direction.y)^2 = r^2

Si on simplifie cette équation en groupant tous les termes qui doivent être groupés, on peut la ré-écrire sous la forme d’une équation quadratique Ax^2 + Bx+ C = 0 :

a = direction.x^2 + direction.y^2
b = 2*(camera.x*direction.x + camera.y*direction.y)
c = camera.x^2 + camera.y^2 - r^2

Pour résoudre une équation quadratique, il faut tout d’abord trouver son discriminant delta (b2-4ac). Si le delta est différent de 0, nous pouvons calculer 2 intersections (le point d’entré du rayon, ainsi que son point de sorti, toujours en fonction du temps t), avec

–b (+ ou -) sqrt(delta)/2a

Nous utilisons la plus petite des deux (le t le plus petit) et nous avons notre point d’intersection. Tout ce qu’il reste à présent, c’est de calculer les coordonnées pour le texture mapping, en utilisant le mapping conique :

u = fabs(intersection.z)*0.2;
v = fabs(atan2(intersection.y, intersection.x) * 256/M_PI );


INTERPOLATION

Il est évident que de tels calculs en temps réels peuvent s’avérer très lents. Puisqu’il faut calculer pour chaque rayon (pixel), un écran de 320x200 demanderait 64,000 rayon par trame. La solution la plus logique est d’interpoler en utilisant une grille. On calcule les intersections à tous les 8 pixels (ou 4), et on interpole la texture entre les coordonnées U,V. Plus grande sera la grille, plus grand sera la perte de précision. Regarder le schéma suivant :

fxtunray
Pin it

De cette façon, on obtient une très bonne approximation des coordonnées dans la texture, et la vitesse du programme est quand même très respectable. En utilisant des puissances de 2 pour la taille de la grille, il devient très facile d’optimiser le code en utilisant des nombres à virgule fixe et en utilisant le bit shifting au lieu des divisions.

MOUVEMENTS DE CAMÉRA

Comme nous avons un vecteur de caméra, il est très facile de lui imposer des transformations. Pour déplacer la caméra, il suffit de modifier ses composantes x, y ou z. Pour la faire tourner sur son axe, il faudra utiliser soit une matrice de rotation (voir 3D chapitre 2), ou utiliser les formules de rotation directement sur le vecteur. N’oubliez pas de normaliser par la suite le vecteur de direction!

AUTRES POSSIBILITÉS

En sachant que la variable « t » représente le temps où le rayon atteint l’objet, il est facile de tenir compte de la profondeur d’un objet, afin de faire des calculs d’ombrages. On peut également grandement simplifié les équations de collisions si on assume certaines choses, comme par exemple que la caméra est fixe sur un certain axe.


fxtunray.cpp

  
// Exemple de tunnel ‡ direction libre (raytracing)
// DATE: 22/06/99
// AUTEUR: Shaun DorÈ
// Krashlog / Creative Impact
// dores@videotron.ca
// http://pages.infinit.net/shaun/
// http://pages.infinit.net/pcdesign/creative.impact/

// MACROS ////////////////////////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN
// Macro qui retourne vrai si une touche est enfoncÈe
#define Touche(VkCode) (GetAsyncKeyState(VkCode) & 0x8000 ? 1 : 0)
// RÈsolution maximale X
#define MAX_X 640
// RÈsolution maximale Y
#define MAX_Y 480

// INCLUDES //////////////////////////////////////////////////////////////

#include <io.h>
#include <math.h>
#include <ddraw.h>
#include <stdio.h>
#include <windows.h>
#include <windowsx.h>
#include "resource.h"

// TYPES /////////////////////////////////////////////////////////////////

// Un vecteur
typedef struct _vecteur
{
float x, y, z;
} _vecteur;

// Grille d'interpolation
typedef struct _Grille
{
float u,v;
} _Grille;

// Image bitmap
typedef struct BITMAP_FILE_TAG
{
BITMAPFILEHEADER bitmapfileheader; // Header du bitmap
BITMAPINFOHEADER bitmapinfoheader; // palette
PALETTEENTRY palette[256]; // 256 couleurs
UCHAR *buffer; // les graphiques
} BITMAP_FILE, *BITMAP_FILE_PTR;


// GLOBALES /////////////////////////////////////////////////////////////

LPDIRECTDRAW DirectDraw = NULL; // Objet DirectDraw
LPDIRECTDRAWSURFACE SurfacePrimaire = NULL; // Surface primaire
LPDIRECTDRAWSURFACE SurfaceSecondaire = NULL; // L'ecran virtuel de la surface primaire
LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to the created dd palette
PALETTEENTRY palette[256]; // color palette
DDSURFACEDESC SurfaceDesc; // Description de la surface
DDSCAPS SurfaceCap; // CapacitÈs de la surface
HINSTANCE InstancePrincipale = NULL; // Instance de l'application
HWND HandlePrincipale = NULL; // Handle sur la fenÍtre principale
BOOL Quitter = FALSE; // Test pour savoir si on quitte l'app
UCHAR *virtuel = NULL; // Ptr sur Ècran virtuel
BITMAP_FILE bitmap8bit; // un bitmap 8-bit


int ECRAN_X = 0; // RÈsolution X
int ECRAN_Y = 0; // RÈsolution Y
int INCR = 0; // IncrÈment d'interpolation
int MID_X = 0; // Millieu des X
int MID_Y = 0; // Millieu des Y

// sin & cos pour rotation
float SinTable[256];
float CosTable[256];

_Grille Grille[MAX_X+16][MAX_Y+16]; // Grille d'interpolation linÈaire
_vecteur camera = {0,0,0}; // vecteur de camera
BYTE angle=0; // Angle de rotation

// D…CLARATIONS ////////////////////////////////////////////////////////////

int InitDirectDraw(); // Initialisation de DirectDraw
void CloseDirectDraw(); // LibËre la mÈmoire des objets DirectDraw
int DessinePixel(); // Dessine des pixels sur l'Ècran secondaire
int InitFenetre(); // Initialise la fenÍtre


// FONCTIONS ///////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// Normalisation d'un vecteur
void vec_norm(_vecteur *v)
{
float l = (float) 1.0 / (float) sqrt(v->x*v->x + v->y*v->y + v->z*v->z);
v->x *= l;
v->y *= l;
v->z *= l;
}

////////////////////////////////////////////////////////////////////////////
// Calcul des tableaux sin/cos
void PreCalc()
{
for(int angle=0; angle<256; angle++)
{
SinTable[angle]=(float)sin(angle*3.14159265358979323/128.0);
CosTable[angle]=(float)cos(angle*3.14159265358979323/128.0);
}
}

////////////////////////////////////////////////////////////////////////////
// Rotation sur l'axe X
void rotx(_vecteur *v, BYTE a)
{
_vecteur temp = *v;
v->y = temp.y*CosTable[a] - temp.z*SinTable[a];
v->z = temp.y*SinTable[a] + temp.z*CosTable[a];
v->x = temp.x;
}

////////////////////////////////////////////////////////////////////////////
// Raytracing (intersection avec tunnel)
void calc_tunnel(int x, int y)
{
_vecteur direction = {(float)x-MID_X,(float)y-MID_Y,256.0}, intersect;
float a, b, c, delta, t, t1, t2;

// Normalise le vecteur et rotation
rotx(&direction,angle);
vec_norm(&direction);

a = direction.x*direction.x + direction.y*direction.y;
b = 2*(camera.x*direction.x + camera.y*direction.y);
c = camera.x*camera.x + camera.y*camera.y - 256*256;

delta = (float) sqrt(b*b - 4*a*c);
t1 = (float) ((-b+delta) / (2*a+.0000001)); // attention aux div/0!
t2 = (float) ((-b-delta) / (2*a+.0000001));

t = t1 > 0 ? t1 : t2;

// Point d'intersection
intersect.x = camera.x + t*direction.x;
intersect.y = camera.y + t*direction.y;
intersect.z = camera.z + t*direction.z;

// Rempli la grille d'interpolation (mapping conique)
Grille[x][y].u = (float) fabs(intersect.z*0.1);
Grille[x][y].v = (float) fabs(atan2(intersect.y, intersect.x)*256/3.14159265358979323);
}

////////////////////////////////////////////////////////////////////////////
// Interpolation bilinÈaire dans la grille (version floating-point)
void interpolation()
{
int x,y,i,j,yoff;
float dul,dur,dbl,dbr,du,dv,ul,ur,bl,br,u,v;

// Lock la surface virtuelle
SurfaceSecondaire->Lock(NULL,&SurfaceDesc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);

// Ramene un ptr sur la surface secondaire
virtuel = (UCHAR *)SurfaceDesc.lpSurface;

for (j=0; j<ECRAN_Y; j+=INCR)
for (i=0; i<ECRAN_X; i+=INCR)
{
// coin gauche supÈrieur, droit supÈrieur, gauche infÈrieur, droit infÈrieur
dul = (Grille[i][j+INCR].u - Grille[i][j].u) / INCR;
dur = (Grille[i+INCR][j+INCR].u - Grille[i+INCR][j].u) / INCR;
dbl = (Grille[i][j+INCR].v - Grille[i][j].v) / INCR;
dbr = (Grille[i+INCR][j+INCR].v - Grille[i+INCR][j].v) / INCR;
ul = (Grille[i][j].u);
bl = (Grille[i][j].v);
ur = (Grille[i+INCR][j].u);
br = (Grille[i+INCR][j].v);

for (y=j; y<j+INCR; y++)
{
du = (ur - ul) / INCR;
dv = (br - bl) / INCR;
u = ul;
v = bl;
yoff=(y*ECRAN_X);
for (x=i; x<i+INCR; x++)
{
virtuel[yoff+x] = bitmap8bit.buffer[(BYTE)u+(((BYTE)v)<<8)];
u+=du;
v+=dv;
}
ul += dul;
ur += dur;
bl += dbl;
br += dbr;
}
}
// LibËre la surface secondaire
SurfaceSecondaire->Unlock(virtuel);
// Flip!
while(SurfacePrimaire->Flip(NULL,DDFLIP_WAIT)!=DD_OK);
if (Touche(VK_ESCAPE))
PostMessage(HandlePrincipale, WM_DESTROY, 0, 0);
}


////////////////////////////////////////////////////////////////////////////
// Le gestionnaire d'ÈvËnements pour notre boÓte de dialogue
LRESULT CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int i;
RECT rc;
// Chaine de car pour le combo box
char* interp[] = {"4","8","16"};
// Int des chaines de ar
int interpola[] = {4,8,16};

switch(msg)
{
// CrÈation de la boÓte de dialogue
case WM_INITDIALOG:
// Centre de l'Ècran
GetWindowRect( hwnd, &rc );
SetWindowPos( hwnd, HWND_TOP,
(GetSystemMetrics(SM_CXSCREEN) - rc.right) / 2,
(GetSystemMetrics(SM_CYSCREEN) - rc.bottom) / 2,
0, 0, SWP_NOSIZE);
// Bouton 1 checked
SendDlgItemMessage( hwnd, IDC_320200, BM_SETCHECK, 1, 0 );
for ( i=0 ; i<3 ; i++ )
{
SendDlgItemMessage( hwnd, IDC_INTERPOL, CB_ADDSTRING, 0, (int)interp[i] );
}
// Choisir interpolation 8x8
SendDlgItemMessage( hwnd, IDC_INTERPOL, CB_SETCURSEL, 1, 0 );
break;
// Un bouton de commande (le # du bouton est contenu dans le low 8-bit de wParam)
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case ID_OK:
if ( SendDlgItemMessage( hwnd, IDC_320200, BM_GETCHECK, 0, 0))
{
ECRAN_X = 320;
ECRAN_Y = 200;
}
else if ( SendDlgItemMessage( hwnd, IDC_512384, BM_GETCHECK, 0, 0))
{
ECRAN_X = 512;
ECRAN_Y = 384;
}
else if ( SendDlgItemMessage( hwnd, IDC_640480, BM_GETCHECK, 0, 0))
{
ECRAN_X = 640;
ECRAN_Y = 480;
}

MID_X = ECRAN_X/2;
MID_Y = ECRAN_Y/2;
INCR = interpola[ SendDlgItemMessage(hwnd,IDC_INTERPOL,CB_GETCURSEL,0,0)];
EndDialog(hwnd, FALSE);
break;

case ID_ABOUT:
{
MessageBox(HandlePrincipale,"TUNNEL \n\nCode: Krashlog/Creative Impact\nEmail: dores@videotron.ca\nhttp://pages.infinit.net/shaun/\nhttp://pages.infinit.net/pcdesign/creative.impact/","A propos...",MB_OK | MB_ICONINFORMATION);
break;
}
case ID_QUIT:
{
EndDialog(hwnd, FALSE);
Quitter = TRUE;
break;
}
}
break;
}
default:
return FALSE;
}
return TRUE;
}


////////////////////////////////////////////////////////////////////////////
// Gestionnaire d'ÈvÈnements de la fenÍtre
LRESULT CALLBACK WindowProc(HWND hWnd, // Handle sur la fenÍtre
UINT Msg, // Identificateur du message
WPARAM wParam,
LPARAM lParam)
{
// Analyse le message
switch (Msg)
{
// La fenÍtre va Ítre dÈtruite
case WM_DESTROY:
{
// Envoie un message ‡ la fenÍtre pour quitter
PostQuitMessage(0);
return 0;
} break;

default:
break;
}
// Le reste des messages au gestionnaire par dÈfaut
return DefWindowProc(hWnd, Msg, wParam, lParam);
}

////////////////////////////////////////////////////////////////////////////
// Initialise et instancie une fenÍtre
int InitFenetre()
{
WNDCLASS ClasseFenetre; // Le nom de notre classe
HWND hWnd; // Handle sur la fenÍtre

// Style de la fenÍtre
ClasseFenetre.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
// Gestionnaire d'ÈvÈnements de la fenÍtre
ClasseFenetre.lpfnWndProc = WindowProc;
// ParamËtres supplÈmentaires
ClasseFenetre.cbClsExtra = 0;
// ParamËtres supplÈmentaires
ClasseFenetre.cbWndExtra = 0;
// Ptr sur instance de l'application
ClasseFenetre.hInstance = InstancePrincipale;
// IcÙne de la fenÍtre
ClasseFenetre.hIcon = LoadIcon(InstancePrincipale, MAKEINTRESOURCE(IDI_ICON1));
// Curseur de la fenÍtre
ClasseFenetre.hCursor = LoadCursor(NULL, IDC_ARROW);
// Palette de couleur
ClasseFenetre.hbrBackground = (struct HBRUSH__ *)GetStockObject(BLACK_BRUSH);
// Ptr sur menu
ClasseFenetre.lpszMenuName = NULL;
// Ptr sur nom de la classe
ClasseFenetre.lpszClassName = "Fenetre";

// Enregistre la classe
if (!RegisterClass(&ClasseFenetre))
return 0;

// CrÈation de la fenÍtre
hWnd = CreateWindow("Fenetre",
"Tunnel",
WS_POPUP | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
InstancePrincipale,
NULL);
// S'assure que tout est OK
if (!hWnd)
return 0;

// Sauvegarde l'handle de la fenÍtre dans une globale
HandlePrincipale = hWnd;
return 1;
}

////////////////////////////////////////////////////////////////////////////
// Fonction principale
int WINAPI WinMain(HINSTANCE hInstance, // Handle sur l'instance prÈsente
HINSTANCE hPrevInstance, // Handle sur l'instance prÈcÈdente
LPSTR lpCmbLine, // Ptr sur les arguments
int nCmdShow) // …tat de la fenÍtre
{
MSG Msg;
InstancePrincipale = hInstance;
DialogBox(InstancePrincipale, MAKEINTRESOURCE(IDD_MENU), NULL, ( DLGPROC ) DlgProc);
EndDialog(HandlePrincipale, FALSE);

if (!Quitter)
{
if(!InitFenetre()) Quitter = TRUE;
if(!InitDirectDraw()) Quitter = TRUE;
}

// Tant qu'on n'a pas quitter
while (Quitter == FALSE)
{
// Regarde s'il y a un message dans la msg queue
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
// VÈrifie si le message est un WM_QUIT
if (Msg.message == WM_QUIT)
Quitter = true;
else
{
// Traduit le message
TranslateMessage(&Msg);
// Envoie le message au gestionnaire d'ÈvÈnements
DispatchMessage(&Msg);
}
}
// Calcule les intersections des rayons avec le tunnel
for (int y=0; y<ECRAN_Y+INCR; y+=INCR)
for (int x=0; x<ECRAN_X+INCR; x+=INCR)
calc_tunnel(x,y);
// Interpolation linÈaire
interpolation();
// Avance la camÈra
camera.z+=64;
// Angle de rotation
angle++;
}
CloseDirectDraw();
return Msg.wParam;
}


////////////////////////////////////////////////////////////////////////////
// Charge l'image bitmap en mÈmoire
int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
{
int file_handle,index;
OFSTRUCT file_data;

if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1) return(0);
_lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
_lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage);
_lread(file_handle, &bitmap->palette,256*sizeof(PALETTEENTRY));
_lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
_lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
_lclose(file_handle);
for (index=0; index < 256; index++)
{
int temp_color = bitmap->palette[index].peRed;
bitmap->palette[index].peRed = bitmap->palette[index].peBlue;
bitmap->palette[index].peBlue = temp_color;
bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
}
return(1);
}


////////////////////////////////////////////////////////////////////////////
// Cette fonction libËre la mÈmoire allouÈ pour le bitmap
int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
{
if (bitmap->buffer)
free(bitmap->buffer);
return(1);
}

////////////////////////////////////////////////////////////////////////////
// Initialise DirectDraw
int InitDirectDraw()
{
// CrÈation d'un objet DirectDraw
if (DirectDrawCreate(NULL, &DirectDraw, NULL) != DD_OK)
return 0;

// Niveau de coopÈration (FullScreen)
if (DirectDraw->SetCooperativeLevel(HandlePrincipale,
DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN |
DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT) != DD_OK)
return 0;

// SÈlection du mode vidÈo
if (DirectDraw->SetDisplayMode(ECRAN_X, ECRAN_Y, 8) != DD_OK)
{
MessageBox(HandlePrincipale,
"Le mode vidÈo dÈsirÈ n'est pas supportÈ par votre pilote. Assurez-vous d'avoir la derniËre version du pilote DirectX de votre carte vidÈo.",
"Erreur mode vidÈo",
MB_OK | MB_ICONERROR);
return 0;
}

// Initialise la structure de description de la surface
ZeroMemory(&SurfaceDesc,sizeof(SurfaceDesc));
SurfaceDesc.dwSize = sizeof(SurfaceDesc);
SurfaceDesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
SurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
SurfaceDesc.dwBackBufferCount = 1;

// CrÈation de la surface primaire
if (DirectDraw->CreateSurface(&SurfaceDesc, &SurfacePrimaire, NULL) != DD_OK)
return 0;

// CrÈation de la surface secondaire (virtuelle)
SurfaceCap.dwCaps = DDSCAPS_BACKBUFFER;
SurfacePrimaire->GetAttachedSurface(&SurfaceCap, &SurfaceSecondaire);

memset(palette,0,256*sizeof(PALETTEENTRY));

for (int index=0; index<256; index++)
palette[index].peFlags = PC_NOCOLLAPSE;

// crÈe l'objet palette
DirectDraw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256,palette,&lpddpal,NULL);
// Precalculation sin/cos
PreCalc();
// Attache la palette 8-bit ‡ la surface primaire
SurfacePrimaire->SetPalette(lpddpal);
// Load le bitmap
Load_Bitmap_File(&bitmap8bit, "tunnel.bmp");
lpddpal->SetEntries(0,0,256,bitmap8bit.palette);
// Cacher le curseur
ShowCursor(FALSE);
return 1;
}

////////////////////////////////////////////////////////////////////////////
// LibËre les objets DirectDraw
void CloseDirectDraw()
{
// LibËre surface secondaire
if (SurfaceSecondaire != NULL)
SurfaceSecondaire->Release();

// LibËre surface primaire
if (SurfacePrimaire != NULL)
SurfacePrimaire->Release();

// LibËre objet COM DirectDraw
if (DirectDraw != NULL)
DirectDraw->Release();

// Affiche le curseur de souris
ShowCursor(TRUE);
}


resource.h

  
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by tunnel.rc
//
#define ID_ABOUT 3
#define IDD_MENU 101
#define IDI_ICON1 106
#define IDC_RES320240 1000
#define IDC_320200 1000
#define IDC_RES640480 1001
#define IDC_640480 1001
#define IDC_RES512384 1002
#define IDC_512384 1002
#define IDC_INTERP 1003
#define IDC_INTER 1003
#define IDC_INTERPOL 1006
#define IDC_PIX 1008
#define ID_QUIT 1009
#define ID_OK 1010
#define IDC_RES -1

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1011
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

tunnel.rc

  
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// French (Canada) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRC)
#ifdef _WIN32
LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_CANADIAN
#pragma code_page(1252)
#endif //_WIN32

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_MENU DIALOG DISCARDABLE 0, 0, 231, 138
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "TUNNEL"
FONT 10, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",ID_OK,153,21,65,15
PUSHBUTTON "ANNULER",ID_QUIT,153,46,65,15
GROUPBOX "R…SOLUTION",IDC_RES,15,15,130,75
CONTROL "320 x 200 x 8 bit (recommendÈ)",IDC_320200,"Button",
BS_AUTORADIOBUTTON | BS_VCENTER,25,30,113,14
CONTROL "640 x 480 x 8 bit (trËs lent)",IDC_640480,"Button",
BS_AUTORADIOBUTTON | BS_VCENTER,25,70,101,14
CONTROL "512 x 384 x 8 bit (lent)",IDC_512384,"Button",
BS_AUTORADIOBUTTON | BS_VCENTER,25,50,101,14
CTEXT "Taille de la grille:",IDC_INTER,25,110,53,8
COMBOBOX IDC_INTERPOL,83,108,25,52,CBS_DROPDOWN |
CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
GROUPBOX "INTERPOLATION",IDC_RES,15,97,130,28
PUSHBUTTON "A PROPOS",ID_ABOUT,153,71,65,15
LTEXT "pixel",IDC_PIX,112,111,15,8
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_MENU, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 224
TOPMARGIN, 7
BOTTOMMARGIN, 131
END
END
#endif // APSTUDIO_INVOKED


#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END

3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "dx.ico"
#endif // French (Canada) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT