home *** CD-ROM | disk | FTP | other *** search
Wrap
#define STRICT // Includes standard Windows #include <windows.h> #include <windowsx.h> #include <time.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <stdio.h> // Includes D3D #define D3D_OVERLOADS #include <ddraw.h> #include <d3d.h> // Includes utilitaires D3D #include "d3dmath.h" #include "d3dutil.h" #include "D3DEnum.h" #include <d3dx.h> // Ids Resources #include "resource.h" // Constantes #include "const.h" // Types #include "types.h" // Variables globales projet #include "vars.h" // Prototypes fonctions autres modules #include "proto.h" // Macros #include "macros.h" static W3D_Context *hWC3D; static HBITMAP hbDBuf3D; static DC dcDBuf3D, *hdcDBuf3D = &dcDBuf3D; static bZBuf = FALSE; static int iW, iH; static long lError; static BOOL bImage; extern W3D_Texture *tex; void vShow3DFrame(void) { if (!bImage) return; int iLeftEdge = hWndPersp -> BorderLeft, iTopEdge = hWndPersp -> BorderTop, iW = hWndPersp -> Width - iLeftEdge - hWndPersp -> BorderRight, iH = hWndPersp -> Height - iTopEdge - hWndPersp -> BorderBottom; ClipBlit(hdcDBuf3D, iLeftEdge, iTopEdge, hWndPersp -> RPort, iLeftEdge, iTopEdge, iW, iH, 0xc0); } void vRender3DEnvironment(void) { bImage = FALSE; // Verrouiller le bitmap en VRAM lError = TAG_DONE; #if 0 APTR hBM = LockBitMapTagList(hbDBuf3D,(struct TagItem *) &lError); if (!hBM) { vTrace("*** E0077 : vue 3D : lock bitmap (contexte @%08lX, code %ld)", hWC3D, lError); return; } #endif // Verrouiller le hardware 3D if (!hWC3D || !hbDBuf3D || W3D_SUCCESS != (lError = W3D_LockHardware(hWC3D))) { #if 0 // Déverrouiller le bitmap UnLockBitMap(hBM); #endif vTrace("*** E0067 : vue 3D : lock hardware (contexte @%08lX, code %ld, bm %08lX)", hWC3D, lError, hbDBuf3D); return; } W3D_Triangle sTriangle; W3D_Double dZdepth = 1.; W3D_Float fLeftEdge = hWndPersp -> BorderLeft, fTopEdge = hWndPersp -> BorderTop, fW = hWndPersp -> Width - fLeftEdge - hWndPersp -> BorderRight, fH = hWndPersp -> Height - fTopEdge - hWndPersp -> BorderBottom, fXMed = fLeftEdge + fW / 2., fYMed = fTopEdge + fH / 2.; W3D_Vertex sV[4]; W3D_Triangles sTs; sTs.vertexcount = 4; sTs.v = sV; W3D_Color sC = {0., 0., 0., 1.}; // Clearer le zbuf if (bZBuf) W3D_ClearZBuffer(hWC3D, &dZdepth); // Set Drawing region sScissor.left = (int) fLeftEdge; sScissor.top = (int) fTopEdge; sScissor.width = (int) fW; sScissor.height = (int) fH; W3D_SetDrawRegion(hWC3D, NULL, 0, &sScissor); // Calculer le produit des matrices view / proj D3DMath_MatrixMultiply(matWorld, matView, matProj); // Gouraud shading & zbuffer off W3D_SetState(hWC3D, W3D_GOURAUD, W3D_DISABLE); W3D_SetState(hWC3D, W3D_ZBUFFER, W3D_DISABLE); // Remplir le fond WSetPen(hWC3D, cBack); WRectFill(hWC3D, 0, 0, fW - 1, fH - 1); // Gouraud shading & zBuffer on W3D_SetState(hWC3D, W3D_GOURAUD, W3D_ENABLE); if (bZBuf) W3D_SetState(hWC3D, W3D_ZBUFFER, W3D_ENABLE); // Calculer le vecteur normalisé observateur / cible (pour le lighting simpliste) D3DVECTOR vObs = Normalize(Observer - Target); // Dessiner les triangles for (register int iTriangles = 0 ; iTriangles <= iTriaLastUsed ; iTriangles++) { register gTri *hTri = &Triangles[iTriangles]; if (!hTri -> bEnabled) continue; if (hTri -> bHidden) continue; D3DVECTOR // Déréférencer les 3 sommets du triangle v0_UnT = Vertices[hTri -> iSommets[0]].vPoint, v1_UnT = Vertices[hTri -> iSommets[1]].vPoint, v2_UnT = Vertices[hTri -> iSommets[2]].vPoint, // Transformés normalisés des 3 vecteurs ci-dessus v0, v1, v2; // TRANSFORM, step 1 : Transformation coordonnées objets vers [-1..+1] en utilisant la concaténation des matrices View et Proj D3DMath_VectorMatrixMultiply(v0, v0_UnT, matWorld); D3DMath_VectorMatrixMultiply(v1, v1_UnT, matWorld); D3DMath_VectorMatrixMultiply(v2, v2_UnT, matWorld); // TRANSFORM, step 2 : ajustement du span X/Y dans fenêtre 3D sTriangle.v1.x = fXMed + v0.x * fW; sTriangle.v1.y = fYMed + v0.y * fH; sTriangle.v2.x = fXMed + v1.x * fW; sTriangle.v2.y = fYMed + v1.y * fH; sTriangle.v3.x = fXMed + v2.x * fW; sTriangle.v3.y = fYMed + v2.y * fH; sTriangle.v1.z = v0.z; sTriangle.v2.z = v1.z; sTriangle.v3.z = v2.z; // LIGHT, step 1 : calculer les vecteurs normaux sur les trois sommets et les facteurs de correction D3DVECTOR v01 = v1_UnT - v0_UnT, v02 = v2_UnT - v0_UnT, v12 = v2_UnT - v1_UnT, vn0 = Normalize(CrossProduct(v01, v02)), vn1 = Normalize(CrossProduct(v01, v12)), vn2 = Normalize(CrossProduct(v02, v12)); FLOAT f0 = fabs(DotProduct(vObs, vn0)), f1 = fabs(DotProduct(vObs, vn1)), f2 = fabs(DotProduct(vObs, vn2)); // LIGHT, step 2 : moduler la couleur en fonction orientation D3DMATERIAL7 *hMtrl = &Materials[hTri -> iMtrl].mtrl; sC.r = hMtrl -> diffuse.r; sC.g = hMtrl -> diffuse.g; sC.b = hMtrl -> diffuse.b; sTriangle.v1.color.r = sC.r * f0; sTriangle.v1.color.g = sC.g * f0; sTriangle.v1.color.b = sC.b * f0; sTriangle.v2.color.r = sC.r * f1; sTriangle.v2.color.g = sC.g * f1; sTriangle.v2.color.b = sC.b * f1; sTriangle.v3.color.r = sC.r * f2; sTriangle.v3.color.g = sC.g * f2; sTriangle.v3.color.b = sC.b * f2; if (Materials[hTri -> iMtrl].bTextured) { // Set Texture mapping on W3D_SetState(hWC3D, W3D_TEXMAPPING, W3D_ENABLE); // Affecter les u & v sTriangle.v1.u = hTri -> u[0]; sTriangle.v1.v = hTri -> v[0]; sTriangle.v2.u = hTri -> u[1]; sTriangle.v2.v = hTri -> v[1]; sTriangle.v3.u = hTri -> u[2]; sTriangle.v3.v = hTri -> v[2]; // Affecter la texture sTriangle.tex = Materials[hTri -> iMtrl].hTexture; /********/ sTriangle.tex = tex; // Dessiner le triangle W3D_DrawTriangle(hWC3D, &sTriangle); // Set Texture mapping off W3D_SetState(hWC3D, W3D_TEXMAPPING, W3D_DISABLE); } else W3D_DrawTriangle(hWC3D, &sTriangle); } // Déverrouiller le hardware 3D W3D_UnLockHardware(hWC3D); #if 0 // Déverrouiller le bitmap UnLockBitMap(hBM); #endif // Mémoriser qu'on a bien créé une image dans le double buffer bImage = TRUE; // Blitter le double dans la fenêtre vShow3DFrame(); } void vForce3DRefresh(BOOL bFull) { if (bFull == XDC_MODE_COMPLET) vRender3DEnvironment(); else vShow3DFrame(); } LRESULT CALLBACK lrPerspWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { case WM_PAINT: // If we get WM_PAINT messages, it usually means our window was // covered up, so we need to refresh it by re-showing the contents // of the current frame. vForce3DRefresh(XDC_MODE_PARTIEL); break; case WM_CREATE: InitRastPort(hdcDBuf3D); case WM_SIZE: #ifndef _AMIGA_ // Check to see if we are losing or gaining our window. Set the // active flag to match. if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam ) bActive = FALSE; else bActive = TRUE; // A new window size will require a new backbuffer size. The // easiest way to achieve this is to release and re-create // everything. if( bActive && bReady ) #endif { bReady = FALSE; #ifndef _AMIGA_ if( FAILED( hrCloseD3D(FALSE) ) ) DestroyWindow( hWnd ); if( FAILED( hrInitD3D( hWnd, &gDeviceGUID ) ) ) DestroyWindow( hWnd ); if (FAILED(hrInitWorld( lpd3dDevice ))) { hrCloseD3D(TRUE); DestroyWindow( hWnd ); } // Mettre à jour les variables d'état du pipe D3D vSetD3DState(); // Remettre en service les lampes for (int iCnt = 0 ; iCnt <= iLampLastUsed ; iCnt++) if (Lampes[iCnt].bEnabled) bUpdateLamp(iCnt); // Redessiner la scène #else // Si la taille n'a pas changé, ne rien faire if (iW == hWnd -> Width && iH == hWnd -> Height) break; iW = hWnd -> Width; iH = hWnd -> Height; // Supprimer le contexte 3D s'il est déjà alloué if (hWC3D) { if (bZBuf) { W3D_FreeZBuffer(hWC3D); bZBuf = FALSE; } vCloseTextures(hWC3D); W3D_DestroyContext(hWC3D); hWC3D = NULL; } // Supprimer le bitmap offscreen s'il est déjà alloué if (hbDBuf3D) FreeBitMap(hbDBuf3D); // Créer le bitmap offscreen if (!(hbDBuf3D = AllocBitMap(hWnd -> Width, hWnd -> Height, 8, BMF_MINPLANES | BMF_DISPLAYABLE, hWnd -> RPort -> BitMap))) { vTrace("*** E0068 : vue 3D : allocation double buffer"); break; } // Attacher le bitmap au rastport dcDBuf3D.BitMap = hbDBuf3D; // Créer le contexte W3D extern ULONG lModeID, lError; if (!(hWC3D = W3D_CreateContextTags(&lError, W3D_CC_MODEID, lModeID, W3D_CC_BITMAP, (ULONG) hbDBuf3D, W3D_CC_YOFFSET, 0, W3D_CC_DRIVERTYPE, W3D_DRIVER_BEST, W3D_CC_FAST, TRUE, TAG_DONE))) { vTrace("*** E0069 : vue 3D : crétion contexte Warp3D (code %ld)", lError); FreeBitMap(hbDBuf3D); hbDBuf3D = NULL; break; } // Set dithering. This will look considerably better on 15 bit displays. W3D_SetState(hWC3D, W3D_DITHERING, W3D_ENABLE); // Activer le clipping W3D_SetState(hWC3D, W3D_SCISSOR, W3D_ENABLE); // Allouer le ZBuffer if (W3D_SUCCESS != W3D_AllocZBuffer(hWC3D)) { bZBuf = FALSE; vTrace("*** E0047 : vue 3D : allocation ZBuffer -> pas de suppression faces cachées"); } else { W3D_SetZCompareMode(hWC3D, W3D_Z_LESS); W3D_SetState(hWC3D, W3D_ZBUFFERUPDATE, W3D_ENABLE); bZBuf = TRUE; vTrace("Vue 3D : allocation double buffer / contexte Warp3D / z-buffer OK"); } vInitTextures(hWC3D); #endif // Redessiner la 3D dans le double buffer, Intuition va de de toute façon nous envoyer un REFRESH qui nous donnera un PAINT qui nous fera blitter le double buffer dans la fenêtre vRender3DEnvironment(); bReady = TRUE; } break; case WM_COMMAND: // Rediriger les frappes clavier et chois menus vers la fenêtre menus case WM_CHAR : PostMessage(hWndMenu, uMsg, wParam, lParam ); break; case WM_DESTROY: // Supprimer le contexte 3D if (hWC3D) { if (bZBuf) { W3D_FreeZBuffer(hWC3D); bZBuf = FALSE; } vCloseTextures(hWC3D); W3D_DestroyContext(hWC3D); hWC3D = NULL; } // Supprimer le bitmap offscreen if (hbDBuf3D) FreeBitMap(hbDBuf3D); PostQuitMessage(0); return 0L; } #ifndef _AMIGA_ return DefWindowProc( hWnd, uMsg, wParam, lParam ); #else return 0; #endif }