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> #include <d3dx.h> // Includes utilitaires D3D #include "d3dmath.h" #include "d3dutil.h" #include "D3DEnum.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" #undef XDC_LOCKBITMAP // Variables statiques au module static WPARAM wModifier; // Mémorisé sur le LBUTTONDOWN : SHIFT / CTRL / ... static HBRUSH hbrDkBlueSk, hbrLtBlueSk; // Brosses de remplissage static HPEN hpenWhite, hpenGrey, hpenCyan, hpenYellow, hpenPink, hpenDkBlueSk, hpenRed, hpenLtBlueSk, hpenGrid; // Crayons static HFONT hFont; static HBITMAP hbTBuf; // Bitmap du triple buffer (unique pour les 3 fenêtres) static DC dcTBuf, *hdcTBuf = &dcTBuf; // Forcer le redessin des 3 vues 2D (WM_PAINT) // Le paramètre sert à indiquer s'il faut tout redessiner (y/c triangles & sommets) -> TRUE // ou s'il ne faut redessiner que les curseurs, caméra & target void vForce2DRefresh(BOOL bMode) { PostMessage(hWndTop, WM_PAINT, 0, (LPARAM) bMode); PostMessage(hWndFace, WM_PAINT, 0, (LPARAM) bMode); PostMessage(hWndRight, WM_PAINT, 0, (LPARAM) bMode); } // Callback management fenêtres vues 2D LRESULT CALLBACK lrPlanarWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Variables à usage général HDC hdcWin = GetDC(hWnd), hdcDoubleBuf; // Récupérer notre identifiant (vue dessus, face, droite) et mémoriser dans une globale pour que les autres fonctions sachent quelle fenêtre 2D est active POINT pClick; WinThings *pWT; // Pointeur sur structure étendue fenêtre (double buffer, gadgets etc.) char cCoords[256]; char cAxis; D3DVECTOR vVect1, vVect2, vVect3; RECT rExtRect, rIntRect; // Zones client externe (avec gadgets) et interne (zone de dessin uniquement) register int iX, iY, iZ, iT, iWindowXMin, iWindowXMax, iWindowYMin, iWindowYMax; float fX, fY, fZ, fT, fXs, fYs, fZs, f3D2DXCoef, f3D2DYCoef; W3D_Point sP; W3D_Line sL; sL.st_enable = FALSE; sL.linewidth = 1.0; W3D_Vertex sV[4]; W3D_Triangles sTs; sTs.vertexcount = 4; sTs.v = sV; W3D_Lines sLs; sLs.vertexcount = 4; sLs.v = sV; sLs.st_enable = FALSE; sLs.linewidth = 1.0; W3D_Color sC = {0., 0., 0., 1.}; float fTopEdge, fLeftEdge, fU, fV; long lError; #ifdef XDC_LOCKBITMAP APTR hBM; #endif // Récupérer le rectangle complet de la zone client de la fenêtre GetClientRect(hWnd, &rExtRect); // Cloner ce rectangle et le réduire pour laisser la place aux gadgets CopyRect(&rIntRect, &rExtRect); InflateRect(&rIntRect, -XDC_G_LARG, -XDC_G_HAUT); if (hWnd == hWndTop) lWActive = XDC_WID_TOP; if (hWnd == hWndFace) lWActive = XDC_WID_FACE; if (hWnd == hWndRight) lWActive = XDC_WID_SIDE; // Précalculer les coefficients de pente de conversion 3D/2D et déréférencer les coordonnées de la fenêtre iWindowXMin = rIntRect.left; iWindowXMax = rIntRect.right; iWindowYMax = rIntRect.top; iWindowYMin = rIntRect.bottom; switch(lWActive) { case XDC_WID_TOP : // X et Z f3D2DXCoef = (float) (iWindowXMax - iWindowXMin) / (fXmax - fXmin); f3D2DYCoef = (float) (iWindowYMax - iWindowYMin) / (fZmax - fZmin); break; case XDC_WID_FACE : // X et Y f3D2DXCoef = (float) (iWindowXMax - iWindowXMin) / (fXmax - fXmin); f3D2DYCoef = (float) (iWindowYMax - iWindowYMin) / (fYmax - fYmin); break; case XDC_WID_SIDE : // Z et Y f3D2DXCoef = (float) (iWindowXMax - iWindowXMin) / (fZmax - fZmin); f3D2DYCoef = (float) (iWindowYMax - iWindowYMin) / (fYmax - fYmin); break; } // Récupérer le pointeur sur la structure de données étendue de la fenêtre (double & triple buffer, gadgets etc.) pWT = (WinThings *) hWnd -> UserData; switch( uMsg ) { case WM_CREATE: //************************* C R E A T E ************************ // Allouer les objets GDI (globaux à toutes les fenêtres 2D d'où if ...) if (!hpenWhite) hpenWhite = CreatePen(PS_SOLID, 1, XDC_COL_WHITE); if (!hpenRed) hpenRed = CreatePen(PS_SOLID, 1, XDC_COL_RED); if (!hpenYellow) hpenYellow = CreatePen(PS_SOLID, 1, XDC_COL_YELLOW); if (!hpenCyan) hpenCyan = CreatePen(PS_SOLID, 1, XDC_COL_CYAN); if (!hpenPink) hpenPink = CreatePen(PS_SOLID, 1, XDC_COL_PINK); if (!hpenGrey) hpenGrey = CreatePen(PS_SOLID, 1, XDC_COL_GREY); if (!hpenDkBlueSk) hpenDkBlueSk = CreatePen(PS_SOLID, 1, XDC_COL_DKBLUESK); if (!hpenLtBlueSk) hpenLtBlueSk = CreatePen(PS_SOLID, 1, XDC_COL_LTBLUESK); if (!hpenGrid) hpenGrid = CreatePen(PS_SOLID, 1, XDC_COL_GRID); #ifndef _AMIGA_ if (!hbrDkBlueSk) hbrDkBlueSk = CreateSolidBrush(XDC_COL_DKBLUESK); if (!hbrLtBlueSk) hbrLtBlueSk = CreateSolidBrush(XDC_COL_LTBLUESK); // Créer la fonte pour indiquer l'outil en cours à coté du curseur if (!hFont) hFont = CreateFont( -12, 0, 0, 0, FW_BOLD, TRUE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH, "Arial" ); #endif // Créer la structure de données étendue et l'attacher à la fenêtre if (!(pWT = (WinThings *) malloc(sizeof(WinThings)))) { // Si fail, sortir de l'application PostQuitMessage(0); break; } // Attacher la structure de données étendue à la fenêtre hWnd -> UserData = (UBYTE *) pWT; // Initialiser les pointeurs de gadgets sur l'imagerie gadgets (commune à toutes les fenêtres) pWT -> Widgets[XDC_GID_AddPoint].Gad = &gAddPoint; pWT -> Widgets[XDC_GID_Center].Gad = &gCenter; pWT -> Widgets[XDC_GID_GoDown].Gad = &gGoDown; pWT -> Widgets[XDC_GID_GoLeft].Gad = &gGoLeft; pWT -> Widgets[XDC_GID_GoUp].Gad = &gGoUp; pWT -> Widgets[XDC_GID_GoRight].Gad = &gGoRight; pWT -> Widgets[XDC_GID_Grab].Gad = &gGrab; pWT -> Widgets[XDC_GID_MakeTri].Gad = &gMakeTri; pWT -> Widgets[XDC_GID_Reverse].Gad = &gReverse; pWT -> Widgets[XDC_GID_RotAnti].Gad = &gRotAnti; pWT -> Widgets[XDC_GID_RotClock].Gad = &gRotClock; pWT -> Widgets[XDC_GID_ZoomIn].Gad = &gZoomIn; pWT -> Widgets[XDC_GID_ZoomOut].Gad = &gZoomOut; // Mémoriser qu'on doit mettre à jour la zone de clipping fenêtre pWT -> hClip = (struct Region *) ~NULL; // Créer le double buffer et l'attacher à la structure de données étendue pWT -> hbDBuf = NULL; // Sera alloué par le premier WM_SIZE pWT -> hdcDBuf = &(pWT -> dcDBuf); InitRastPort(pWT -> hdcDBuf); // Se rappeler que le prochain WM_PAINT sera le premier pWT -> bFirstPaint = TRUE; break; case WM_USER + 1: //*********************** Rafraichir le point d'indice wParam dans le double buffer // (-> refresh 2D mode partiel à suivre) // Si pas de contexte 3D ou pas de double buffer alors ne rien faire if ((!hW3DContext) || !(pWT -> hbDBuf)) { vTrace("*** E0070 : [%s] / msg %d : contexte @%08lX, bmdBuf %08lX)", hWnd -> Title, uMsg, hW3DContext, pWT -> hbDBuf); break; } // Déréférencer le point à rafraîchir vVect1 = Vertices[wParam].vPoint; switch(lWActive) { case XDC_WID_TOP : // X et Z fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y fX = XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Set Drawing region sur le double buffer fLeftEdge = fTopEdge = 0.; sScissor.left = (int) fLeftEdge + iWindowXMin + 1; sScissor.top = (int) fTopEdge + iWindowYMax + 1; sScissor.width = iWindowXMax - iWindowXMin - 1; sScissor.height = iWindowYMin - iWindowYMax - 1; W3D_SetDrawRegion(hW3DContext, pWT -> hbDBuf, 0, &sScissor); #ifdef XDC_LOCKBITMAP // Verrouiller le bitmap en VRAM lError = TAG_DONE; if (!(hBM = LockBitMapTagList(pWT -> hbDBuf,(struct TagItem *) &lError))) { vTrace("*** E0021 : [%s] / msg %d : lock bitmap (contexte @%08lX, code %ld)", hWnd -> Title, uMsg, hW3DContext, lError); break; } #endif // Si on ne peut pas verrouiller le hardware 3D on ne fait rien if (W3D_SUCCESS != (lError = W3D_LockHardware(hW3DContext))) { #ifdef XDC_LOCKBITMAP // Déverrouiller le bitmap UnLockBitMap(hBM); #endif vTrace("*** E0071 : [%s] / msg %d : lock hardware (contexte @%08lX, code %ld)", hWnd -> Title, uMsg, hW3DContext, lError); break; } // Tracer le sommet (petite croix) WSetPen(hW3DContext, Vertices[wParam].bSelected ? XDC_COL_YELLOW : XDC_COL_DKBLUESK); WPixel(hW3DContext, fX, fY); WPixel(hW3DContext, fX - 1, fY); WPixel(hW3DContext, fX + 1, fY); WPixel(hW3DContext, fX, fY - 1); WPixel(hW3DContext, fX, fY + 1); // Déverrouiller le hardware 3D W3D_UnLockHardware(hW3DContext); #ifdef XDC_LOCKBITMAP // Déverrouiller le bitmap UnLockBitMap(hBM); #endif break; case WM_PAINT: //************************** P A I N T *********************** { // Si pas de contexte 3D ou pas de double buffer, on ne fait rien if ((!hW3DContext) || !(pWT -> hbDBuf)) { vTrace("*** E0072 : [%s] / msg %d : contexte @%08lX, bmdBuf %08lX)", hWnd -> Title, uMsg, hW3DContext, pWT -> hbDBuf); break; } // déréférencer le HDC du double buffer pour aller plus vite hdcDoubleBuf = pWT -> hdcDBuf; // On redessine tout seulement si on nous le demande ou si c'est le premier WM_PAINT if (((BOOL) lParam || pWT -> bFirstPaint) == XDC_MODE_PARTIEL) goto _skip; // Set Drawing region sur le double buffer fLeftEdge = fTopEdge = 0.; sScissor.left = (int) fLeftEdge + iWindowXMin + 1; sScissor.top = (int) fTopEdge + iWindowYMax + 1; sScissor.width = iWindowXMax - iWindowXMin - 1; sScissor.height = iWindowYMin - iWindowYMax - 1; W3D_SetDrawRegion(hW3DContext, pWT -> hbDBuf, 0, &sScissor); #ifdef XDC_LOCKBITMAP // Verrouiller le bitmap en VRAM lError = TAG_DONE; if (!(hBM = LockBitMapTagList(pWT -> hbDBuf,(struct TagItem *) &lError))) { vTrace("*** E0020 : [%s] / msg %d : lock bitmap (contexte @%08lX, code %ld)", hWnd -> Title, uMsg, hW3DContext, lError); break; } #endif // Si on ne peut pas verrouiller le hardware 3D on ne fait rien if (W3D_SUCCESS != (lError = W3D_LockHardware(hW3DContext))) { #ifdef XDC_LOCKBITMAP // Déverrouiller le bitmap UnLockBitMap(hBM); #endif vTrace("*** E0073 : [%s] : lock hardware (contexte @%08lX, code %ld)", hWnd -> Title, hW3DContext, lError); break; } // Se rappeller que les WM_PAINT à venir ne sont pas les premiers pWT -> bFirstPaint = FALSE; // Remplir le grand rectangle en bleu foncé : déplacé dans WM_SIZE // Séparer les zones int/ext avec tour blanc : déplacé dans WM_SIZE // Ajouter tous les gadgets Sculpt3D : déplacé dans WM_SIZE // Tracer les noms des axes : déplacé dans WM_SIZE // Définir la zone de clipping : rectangle interne : déplacé dans WM_SIZE // Remplir le petit rectangle en bleu clair WSetPen(hW3DContext, XDC_COL_LTBLUESK); WRectFill(hW3DContext, iWindowXMin + 1, iWindowYMax + 1, iWindowXMax - 1, iWindowYMin - 1); // Tracer la grille (si elle est activée) if (bGrid) { WSetPen(hW3DContext, XDC_COL_GRID); switch(lWActive) { case XDC_WID_TOP : // Axes X (gauche > droite) et Z (bas > haut) for (fXs = XDM_toGrid(fXmin) ; fXs <= XDM_toGrid(fXmax) ; fXs += fGridSize) for (fZs = XDM_toGrid(fZmin) ; fZs <= XDM_toGrid(fZmax) ; fZs += fGridSize) WPixel(hW3DContext, XDM_to2D(fXs, fXmin, iWindowXMin, f3D2DXCoef), XDM_to2D(fZs, fZmin, iWindowYMin, f3D2DYCoef)); break; case XDC_WID_FACE : // Axes X (gauche > droite) et Y (bas > haut) for (fXs = XDM_toGrid(fXmin) ; fXs <= XDM_toGrid(fXmax) ; fXs += fGridSize) for (fYs = XDM_toGrid(fYmin) ; fYs <= XDM_toGrid(fYmax) ; fYs += fGridSize) WPixel(hW3DContext, XDM_to2D(fXs, fXmin, iWindowXMin, f3D2DXCoef), XDM_to2D(fYs, fYmin, iWindowYMin, f3D2DYCoef)); break; case XDC_WID_SIDE : // Axes Z (gauche > droite) et Y (bas > haut) for (fZs = XDM_toGrid(fZmin) ; fZs <= XDM_toGrid(fZmax) ; fZs += fGridSize) for (fYs = XDM_toGrid(fYmin) ; fYs <= XDM_toGrid(fYmax) ; fYs += fGridSize) WPixel(hW3DContext, XDM_to2D(fZs, fZmin, iWindowXMin, f3D2DXCoef), XDM_to2D(fYs, fYmin, iWindowYMin, f3D2DYCoef)); break; } } // Tracer les axes du repère, en gris WSetPen(hW3DContext, XDC_COL_GREY); switch(lWActive) { case XDC_WID_TOP : // Axes X (gauche > droite) et Z (bas > haut) fY = XDM_to2D(0, fZmin, iWindowYMin, f3D2DYCoef); WDraw(hW3DContext, iWindowXMax, fY, iWindowXMin, fY); fX = XDM_to2D(0, fXmin, iWindowXMin, f3D2DXCoef); WDraw(hW3DContext, fX, iWindowYMin, fX, iWindowYMax); break; case XDC_WID_FACE : // Axes X (gauche > droite) et Y (bas > haut) fY = XDM_to2D(0, fYmin, iWindowYMin, f3D2DYCoef); WDraw(hW3DContext, iWindowXMax, fY, iWindowXMin, fY); fX = XDM_to2D(0, fXmin, iWindowXMin, f3D2DXCoef); WDraw(hW3DContext, fX, iWindowYMin, fX, iWindowYMax); break; case XDC_WID_SIDE : // Axes Z (gauche > droite) et Y (bas > haut) fY = XDM_to2D(0, fYmin, iWindowYMin, f3D2DYCoef); WDraw(hW3DContext, iWindowXMax, fY, iWindowXMin, fY); fX = XDM_to2D(0, fZmin, iWindowXMin, f3D2DXCoef); WDraw(hW3DContext, fX, iWindowYMin, fX, iWindowYMax); break; } // Tracer les objets géométriques { // 1 - Arêtes // Choisir le crayon rouge WSetPen(hW3DContext, XDC_COL_RED); for (int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++) { // Ignorer les arêtes inexistants if (Edges[iEdge].bEnabled == FALSE) continue; // Ignorer les arêtes cachés if (Edges[iEdge].bHidden == TRUE) continue; vVect1 = Vertices[Edges[iEdge].iSommets[0]].vPoint; vVect2 = Vertices[Edges[iEdge].iSommets[1]].vPoint; switch(lWActive) { case XDC_WID_TOP : // X et Z fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); fZ = XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(vVect2.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); fZ = XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y fX = XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); fZ = XDM_to2D(vVect2.z, fZmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer l'arête WDraw(hW3DContext, fX, fY, fZ, fT); } // On ne dessine les triangles que si on n'est pas en dragging if (!bTracking) { // 2 - Triangles // Choisir le crayon rose WSetPen(hW3DContext, XDC_COL_PINK); for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++) { // Ignorer les triangles inexistants if (Triangles[iTriangle].bEnabled == FALSE) continue; // Ignorer les triangles cachés if (Triangles[iTriangle].bHidden == TRUE) continue; vVect1 = Vertices[Triangles[iTriangle].iSommets[0]].vPoint; vVect2 = Vertices[Triangles[iTriangle].iSommets[1]].vPoint; vVect3 = Vertices[Triangles[iTriangle].iSommets[2]].vPoint; switch(lWActive) { case XDC_WID_TOP : // X et Z fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); fZ = XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(vVect2.z, fZmin, iWindowYMin, f3D2DYCoef); fU = XDM_to2D(vVect3.x, fXmin, iWindowXMin, f3D2DXCoef); fV = XDM_to2D(vVect3.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); fZ = XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef); fU = XDM_to2D(vVect3.x, fXmin, iWindowXMin, f3D2DXCoef); fV = XDM_to2D(vVect3.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y fX = XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); fZ = XDM_to2D(vVect2.z, fZmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef); fU = XDM_to2D(vVect3.z, fZmin, iWindowXMin, f3D2DXCoef); fV = XDM_to2D(vVect3.y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer l'arête du triangle WTriEdge(hW3DContext, fX, fY, fZ, fT, fU, fV); } } // 3.1 - Points for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++) { if (PeekSignal(l2DWinSigMask)) { W3D_UnLockHardware(hW3DContext); goto _skip; } // Ignorer les points inexistants if (Vertices[iVertex].bEnabled == FALSE) continue; // Ignorer les points cachés if (Vertices[iVertex].bHidden == TRUE) continue; vVect1 = Vertices[iVertex].vPoint; switch(lWActive) { case XDC_WID_TOP : // X et Z fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y fX = XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer le sommet du triangle (petite croix) WSetPen(hW3DContext, Vertices[iVertex].bSelected ? XDC_COL_YELLOW : XDC_COL_DKBLUESK); WPixel(hW3DContext, fX, fY); if (!bTracking) { WPixel(hW3DContext, fX - 1, fY); WPixel(hW3DContext, fX + 1, fY); WPixel(hW3DContext, fX, fY - 1); WPixel(hW3DContext, fX, fY + 1); } } // 4 - Lampes for (int iLamp = 0 ; iLamp <= iLampLastUsed ; iLamp++) { // Ignorer les lampes inexistantes if (Lampes[iLamp].bEnabled == FALSE) continue; WSetPen(hW3DContext, Lampes[iLamp].bSelected ? XDC_COL_YELLOW : XDC_COL_RED); vVect1 = Lampes[iLamp].lLamp.dvPosition; switch(lWActive) { case XDC_WID_TOP : // X et Z fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y fX = XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y fX = XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; } WDraw(hW3DContext, fX, fY, fX + 3, fY - 3); WDraw(hW3DContext, fX, fY, fX + 3, fY + 3); } } #ifdef XDC_LOCKBITMAP // Déverrouiller le bitmap UnLockBitMap(hBM); #endif // Déverrouiller le hardware 3D W3D_UnLockHardware(hW3DContext); _skip: // Set Drawing region sur la fenêtre ou sur le triple buffer s'il existe sScissor.width = iWindowXMax - iWindowXMin - 1; sScissor.height = iWindowYMin - iWindowYMax - 1; if (hbTBuf) // triple buffer, on va continuer à dessiner dedans { fLeftEdge = fTopEdge = 0.; sScissor.left = (int) fLeftEdge + iWindowXMin + 1; sScissor.top = (int) fTopEdge + iWindowYMax + 1; W3D_SetDrawRegion(hW3DContext, hbTBuf, 0, &sScissor); // BitBlitter le double buffer dans le triple ClipBlit(hdcDoubleBuf, hWnd -> BorderLeft, hWnd -> BorderTop, hdcTBuf, hWnd -> BorderLeft, hWnd -> BorderTop, rExtRect.right, rExtRect.bottom, 0xc0); } else // Pas de triple buffer, on va continuer à dessiner dans la fenêtre { fLeftEdge = hWnd -> LeftEdge; fTopEdge = hWnd -> TopEdge; sScissor.left = (int) fLeftEdge + iWindowXMin + 1; sScissor.top = (int) fTopEdge + iWindowYMax + 1; W3D_SetDrawRegion(hW3DContext, hdcWin -> BitMap, 0, &sScissor); // BitBlitter le double buffer dans la fenêtre ClipBlit(hdcDoubleBuf, hWnd -> BorderLeft, hWnd -> BorderTop, hdcWin, hWnd -> BorderLeft, hWnd -> BorderTop, rExtRect.right, rExtRect.bottom, 0xc0); } #ifdef XDC_LOCKBITMAP // Verrouiller le bitmap en VRAM lError = TAG_DONE; if (!(hBM = LockBitMapTagList(hbTBuf ? hbTBuf : hdcWin -> BitMap, (struct TagItem *) &lError))) { vTrace("*** E0033 : [%s] / msg %d : lock bitmap (contexte @%08lX, code %ld)", hWnd -> Title, uMsg, hW3DContext, lError); break; } #endif // Si on ne peut pas verrouiller le hardware 3D on ne fait rien if (W3D_SUCCESS != (lError = W3D_LockHardware(hW3DContext))) { #ifdef XDC_LOCKBITMAP // Déverrouiller le bitmap UnLockBitMap(hBM); #endif vTrace("*** E0074 : [%s] : lock hardware (contexte @%08lX, code %ld)", hWnd -> Title, hW3DContext, lError); break; } // 5 - Tracer le curseur principal et la zone de tolérance switch(lWActive) { case XDC_WID_TOP : // X et Z iZ = (int) (fX = XDM_to2D(Cursor1.x, fXmin, iWindowXMin, f3D2DXCoef)); iT = (int) (fY = XDM_to2D(Cursor1.z, fZmin, iWindowYMin, f3D2DYCoef)); fZ = XDM_to2D(Cursor1.x - (fXmax - fXmin) / XDC_ZONE, fXmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(Cursor1.z - (fXmax - fXmin) / XDC_ZONE, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iZ = (int) (fX = XDM_to2D(Cursor1.x, fXmin, iWindowXMin, f3D2DXCoef)); iT = (int) (fY = XDM_to2D(Cursor1.y, fYmin, iWindowYMin, f3D2DYCoef)); fZ = XDM_to2D(Cursor1.x - (fXmax - fXmin) / XDC_ZONE, fXmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(Cursor1.y - (fXmax - fXmin) / XDC_ZONE, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iZ = (int) (fX = XDM_to2D(Cursor1.z, fZmin, iWindowXMin, f3D2DXCoef)); iT = (int) (fY = XDM_to2D(Cursor1.y, fYmin, iWindowYMin, f3D2DYCoef)); fZ = XDM_to2D(Cursor1.z - (fXmax - fXmin) / XDC_ZONE, fZmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(Cursor1.y - (fXmax - fXmin) / XDC_ZONE, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer le curseur 1 WSetPen(hW3DContext, XDC_COL_CYAN); WDraw(hW3DContext, fX - 9, fY, fX + 10, fY); WDraw(hW3DContext, fX, fY - 9, fX, fY + 10); // Tracer la zone de tolérance WSetPen(hW3DContext, (cTool == XDC_TOOL_UNSELECT) ? XDC_COL_DKBLUESK : XDC_COL_YELLOW); WDraw(hW3DContext, fZ, fT, fZ + 2 * (fX - fZ), fT); WDraw(hW3DContext, fZ, fT, fZ, fT + 2 * (fY - fT)); if ((cTool == XDC_TOOL_SELECT) || (cTool == XDC_TOOL_UNSELECT)) { WDraw(hW3DContext, fZ, fT + 2 * (fY - fT), fZ + 2 * (fX - fZ), fT + 2 * (fY - fT)); WDraw(hW3DContext, fZ + 2 * (fX - fZ), fT, fZ + 2 * (fX - fZ), fT + 2 * (fY - fT)); } // 6 - Tracer l'observateur WSetPen(hW3DContext, XDC_COL_WHITE); switch(lWActive) { case XDC_WID_TOP : // X et Z fX = XDM_to2D(Observer.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(Observer.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y fX = XDM_to2D(Observer.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(Observer.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y fX = XDM_to2D(Observer.z, fZmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(Observer.y, fYmin, iWindowYMin, f3D2DYCoef); break; } WDraw(hW3DContext, fX, fY, fX + 3, fY - 3); WDraw(hW3DContext, fX, fY, fX + 3, fY + 3); // 7 - Tracer le segment caméra / cible switch(lWActive) { case XDC_WID_TOP : // X et Z fZ = XDM_to2D(Target.x, fXmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(Target.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y fZ = XDM_to2D(Target.x, fXmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(Target.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y fZ = XDM_to2D(Target.z, fZmin, iWindowXMin, f3D2DXCoef); fT = XDM_to2D(Target.y, fYmin, iWindowYMin, f3D2DYCoef); break; } WDraw(hW3DContext, fX, fY, fZ, fT); if (bTracking) goto _fastrefresh; // 8 - Tracer la cible WDraw(hW3DContext, fZ - 2, fT - 2, fZ + 3, fT + 3); WDraw(hW3DContext, fZ - 2, fT + 2, fZ + 3, fT - 3); // 9 - Tracer le curseur 2 WSetPen(hW3DContext, XDC_COL_CYAN); switch(lWActive) { case XDC_WID_TOP : // X et Z fX = XDM_to2D(Cursor2.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(Cursor2.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y fX = XDM_to2D(Cursor2.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(Cursor2.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y fX = XDM_to2D(Cursor2.z, fZmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(Cursor2.y, fYmin, iWindowYMin, f3D2DYCoef); break; } WDraw(hW3DContext, fX - 4, fY, fX + 5, fY); WDraw(hW3DContext, fX, fY - 4, fX, fY + 5); // 10 - Tracer le curseur 3 switch(lWActive) { case XDC_WID_TOP : // X et Z fX = XDM_to2D(Cursor3.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(Cursor3.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y fX = XDM_to2D(Cursor3.x, fXmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(Cursor3.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y fX = XDM_to2D(Cursor3.z, fZmin, iWindowXMin, f3D2DXCoef); fY = XDM_to2D(Cursor3.y, fYmin, iWindowYMin, f3D2DYCoef); break; } WDraw(hW3DContext, fX - 4, fY - 4, fX + 5, fY + 5); WDraw(hW3DContext, fX - 4, fY + 4, fX + 5, fY - 5); _fastrefresh: #ifdef XDC_LOCKBITMAP // Déverrouiller le bitmap UnLockBitMap(hBM); #endif // Déverrouiller le hardware 3D W3D_UnLockHardware(hW3DContext); // Si triple buffer, blitter dans la fenêtre if (hbTBuf) ClipBlit(hdcTBuf, hWnd -> BorderLeft, hWnd -> BorderTop, hdcWin, hWnd -> BorderLeft, hWnd -> BorderTop, rExtRect.right, rExtRect.bottom, 0xc0); // Rappeller l'outil courant à coté du curseur if (cTool != XDC_TOOL_NONE) ExtTextOut(hdcWin, iZ + 2, iT - 13, 0, (RECT *) NULL, &cTool, 1, (int *) NULL); // 10 - Coordonnées courantes if (bCoords) { sprintf(cCoords, "(%012.5f, %012.5f, %012.5f)", vTracker.x, vTracker.y, vTracker.z); ExtTextOut(hdcWin, 18, 10, 0, (RECT *) NULL, cCoords, strlen(cCoords), (int *) NULL); } // Libérer le clipping de la fenêtre : déporté dans WM_SIZE et WM_DESTROY break; } case WM_LBUTTONDOWN : //**************** C L I C K G A U C H E ******************* #ifndef _AMIGA_ RECT rClipCurseur; #endif // Si on est déjà en tracking curseur alors ne rien faire if (bTracking) break; // Noter le qualifier (touches enfoncées au moment du click) wModifier = wParam; // Précalculer les offsets (déplacement, zoom, etc.) en fonction du modifieur fXs = (fXmax - fXmin) / ((wModifier & IEQUALIFIER_LSHIFT) ? 4.f : 8.f), fYs = (fYmax - fYmin) / ((wModifier & IEQUALIFIER_LSHIFT) ? 4.f : 8.f), fZs = (fZmax - fZmin) / ((wModifier & IEQUALIFIER_LSHIFT) ? 4.f : 8.f); // Vérifier si le click n'est pas dans les boutons Sculpt. pClick.x = LOWORD(lParam); pClick.y = HIWORD(lParam); if (XDM_BoutonClic(XDC_GID_MakeTri, pClick)) //********* Bouton MakeTri { int iPoint[3], iPoints = 0; // Compter et mémoriser les points sélectionnés (jusqu'à 3) for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++) if (bIsVertexSelected(iVertex)) { if (iPoints < 3) iPoint[iPoints] = iVertex; iPoints++; } // - soit il existe exactement 2 points sélectionnés et on fait une arête avec // si elle n'existe pas déjà // (on ne transforme pas 3 points reliés par 3 arêtes en triangle ***???) if (iPoints == 2) { vTrace("Deux points sélectionnés -> création arête"); if (-1 == iFindEdge(iPoint[0], iPoint[1])) { iMakeEdge(iPoint[0], iPoint[1]); vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); } else vTrace("*** E0001 : L'arête existe déjà"); break; } // - soit il existe exactement 3 points sélectionnés et on fait un triangle avec // (en supprimant les arêtes éventuelles existant entre ces 3 points) s'il n'existe pas déjà if (iPoints == 3) { vTrace("Trois points sélectionnés -> création facette"); if (-1 == iFindTriangle(iPoint[0], iPoint[1], iPoint[2])) { iMakeTriangle(iPoint[0], iPoint[1], iPoint[2], 0); vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); } else vTrace("*** E0002 : Le triangle existe déjà"); break; } // - soit il existe exactement 0 points sélectionnés et on fait un triangle entre // les 3 curseurs s'il n'existe pas déjà if (iPoints == 0) { vTrace("Zéro points sélectionnés -> création facette avec les 3 curseurs"); iPoint[0] = iMakeVertex(Cursor2, XDC_ALLOWSAME), iPoint[1] = iMakeVertex(Cursor1, XDC_ALLOWSAME), iPoint[2] = iMakeVertex(Cursor3, XDC_ALLOWSAME); if (-1 == iFindTriangle(iPoint[0], iPoint[1], iPoint[2])) { iMakeTriangle(iPoint[0], iPoint[1], iPoint[2], 0); vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); } else vTrace("*** E0003 : Le triangle existe déjà"); break; } vTrace("*** E0004 : Nombre de points sélectionnés incorrect (doit être 0, 2 ou 3)"); break; } if (XDM_BoutonClic(XDC_GID_ZoomOut, pClick)) //********* Bouton Zoom Out { fXmin -= fXs; fXmax += fXs; fYmin -= fYs; fYmax += fYs; fZmin -= fZs; fZmax += fZs; vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_ZoomIn, pClick)) //********* Bouton Zoom In { fXmin += fXs; fXmax -= fXs; fYmin += fYs; fYmax -= fYs; fZmin += fZs; fZmax -= fZs; vForce2DRefresh(XDC_MODE_COMPLET); break; } if ( (XDM_BoutonClic(XDC_GID_RotClock, pClick)) //********* Bouton Rotation clockwise || (XDM_BoutonClic(XDC_GID_RotAnti, pClick)) //********* Bouton Rotation anti-clockwise ) { D3DMATRIX mRot; float fAngle = g_PI / (wModifier & MK_SHIFT ? 10.f : 20.f); if (XDM_BoutonClic(XDC_GID_RotClock, pClick)) fAngle *= -1.f; // Préparer la matrice de rotation switch(lWActive) { case XDC_WID_TOP : // X et Z D3DUtil_SetRotateYMatrix(mRot, -fAngle); break; case XDC_WID_FACE : // X et Y D3DUtil_SetRotateZMatrix(mRot, fAngle); break; case XDC_WID_SIDE : // Z et Y D3DUtil_SetRotateXMatrix(mRot, -fAngle); break; } // Appliquer la matrice aux sommets sélectionnés for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++) if (bIsVertexSelected(iVertex)) { // Changer de repère => Cursor1 D3DVECTOR vTrans = Vertices[iVertex].vPoint - Cursor1; // Appliquer la rotation au point translaté D3DMath_VectorMatrixMultiply(vTrans, vTrans, mRot); // Remettre dans le repère d'origine Vertices[iVertex].vPoint = vTrans + Cursor1; } // Rafraichir les vues 2D et 3D vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_Reverse, pClick)) // ********* Bouton reverse (?) { break; } if (XDM_BoutonClic(XDC_GID_Grab, pClick)) // ********* Bouton Grabber (toggle) { cTool = (cTool == XDC_TOOL_GRAB ? XDC_TOOL_NONE : XDC_TOOL_GRAB); vForce2DRefresh(XDC_MODE_PARTIEL); vUpdateMenu(); break; } if (XDM_BoutonClic(XDC_GID_GoRight, pClick)) //********* Bouton Go Right { switch(lWActive) { case XDC_WID_TOP : // X et Z case XDC_WID_FACE : // X et Y fXmin += fXs; fXmax += fXs; break; case XDC_WID_SIDE : // Z et Y fZmin += fZs; fZmax += fZs; break; } vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_GoUp, pClick)) //********* Bouton Go up { switch(lWActive) { case XDC_WID_TOP : // X et Z fZmin += fZs; fZmax += fZs; break; case XDC_WID_FACE : // X et Y case XDC_WID_SIDE : // Z et Y fYmin += fYs; fYmax += fYs; break; } vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_GoLeft, pClick)) //********* Bouton Go left { switch(lWActive) { case XDC_WID_TOP : // X et Z case XDC_WID_FACE : // X et Y fXmin -= fXs; fXmax -= fXs; break; case XDC_WID_SIDE : // Z et Y fZmin -= fZs; fZmax -= fZs; break; } vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_GoDown, pClick)) //********* Bouton Go down { switch(lWActive) { case XDC_WID_TOP : // X et Z fZmin -= fZs; fZmax -= fZs; break; case XDC_WID_FACE : // X et Y case XDC_WID_SIDE : // Z et Y fYmin -= fYs; fYmax -= fYs; break; } vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_AddPoint, pClick)) //********* Bouton Add Point { PostMessage(hWnd, WM_CHAR, 'p', 0); break; } if (XDM_BoutonClic(XDC_GID_Center, pClick)) //********* Bouton Center { float fXs = (fXmax - fXmin) / 2.f, fYs = (fYmax - fYmin) / 2.f, fZs = (fZmax - fZmin) / 2.f; fXmin = Cursor1.x - fXs; fXmax = Cursor1.x + fXs; fYmin = Cursor1.y - fYs; fYmax = Cursor1.y + fYs; fZmin = Cursor1.z - fZs; fZmax = Cursor1.z + fZs; vForce2DRefresh(XDC_MODE_COMPLET); break; } // Si click dans le rectangle interne, alors : // - déclencher le tracking (curseur, observer ou target en fonction du qualifier // - n'autoriser le déplacement que dans le subrect client (clipcursor) // - initialiser le tracking (MOUSEMOVE) if (PtInRect(&rIntRect, pClick)) { #ifndef _AMIGA_ // Pas de fonction permettant le clipping curseur CopyRect(&rClipCurseur, &rIntRect); ClientToScreen(hWnd, (POINT *) &rClipCurseur); ClientToScreen(hWnd, (POINT *) &rClipCurseur + 1); ClipCursor(&rClipCurseur); #endif bTracking = TRUE; ReportMouse(TRUE, hWnd); PostMessage(hWnd, WM_MOUSEMOVE, wParam, lParam); break; } break; case WM_LBUTTONDBLCLK: pClick.x = LOWORD(lParam); pClick.y = HIWORD(lParam); // Si le double click est dans le rectangle interne alors toggler la sélection du noeud indiqué // en envoyant le message ID_EDITION_SLECTIONNER_NOEUDINDIQU à la fenêtre menu avec lParam = XDC_TOGGLE // Sinon, traiter le message comme un simple click if (PtInRect(&rIntRect, pClick)) PostMessage(hWndMenu, WM_COMMAND, ID_EDITION_SLECTIONNER_NOEUDINDIQU, XDC_SINGLETOGGLE); else PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam); break; case WM_LBUTTONUP : //******************** R E L A C H E B O U T O N G A U C H E ****** /* // (ou envoyer les coordonnées à la dlg d'acquisition des trous des formes à remplir si elle est active). if (hHoleDlgActive) { switch(lWActive) { case XDC_WID_TOP : // X et Z dHoles[iHoles * 2 + 0] = XDM_to3D(LOWORD(lParam), fXmin, iWindowXMin, f3D2DXCoef); dHoles[iHoles * 2 + 1] = XDM_to3D(HIWORD(lParam), fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y dHoles[iHoles * 2 + 0] = XDM_to3D(LOWORD(lParam), fXmin, iWindowXMin, f3D2DXCoef); dHoles[iHoles * 2 + 1] = XDM_to3D(HIWORD(lParam), fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y dHoles[iHoles * 2 + 0] = XDM_to3D(LOWORD(lParam), fZmin, iWindowXMin, f3D2DXCoef); dHoles[iHoles * 2 + 1] = XDM_to3D(HIWORD(lParam), fYmin, iWindowYMin, f3D2DYCoef); break; } iHoles++; SendMessage(hHoleDlgActive, WM_USER+1, 0, 0); } */ // Si on n'est pas en mode tracking, ne rien faire if (!bTracking) break; // Si on est en mode tracking, arrêter le mode tracking et supprimer le clipping. bTracking = FALSE; // Arrêter le reporting des mouvements souris sur la fenêtre ReportMouse(FALSE, hWnd); // Forcer le redessin des fenêtres 2D vForce2DRefresh(XDC_MODE_COMPLET); // ClipCursor(NULL); break; case WM_MOUSEMOVE : //****************** M O U V E M E N T S O U R I S ************* D3DVECTOR *pObject; // Si on n'est pas en tracking alors on ne fait rien. if (!bTracking) break; // Déterminer l'objet à déplacer en fonction des qualifiers du WM_LBUTTONDOWN (par défaut, sans qualifiers, c'est le curseur principal) pObject = &Cursor1; if (wModifier & IEQUALIFIER_RALT) pObject = &Target; if (wModifier & IEQUALIFIER_RCOMMAND) pObject = &Observer; if (wModifier & IEQUALIFIER_CONTROL) pObject = &Cursor2; if (wModifier & IEQUALIFIER_LSHIFT) pObject = &Cursor3; // Mémoriser l'ancien vecteur vVect1 = *pObject; // Déterminer les nouvelles coordonnées 2D de l'objet à déplacer iX = LOWORD(lParam); // horizontal position iY = HIWORD(lParam); // vertical position // Mettre à jour les coordonnées 3D de l'objet à déplacer switch(lWActive) { case XDC_WID_TOP : // X et Z pObject -> x = XDM_to3D(iX, fXmin, iWindowXMin, f3D2DXCoef); pObject -> z = XDM_to3D(iY, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y pObject -> x = XDM_to3D(iX, fXmin, iWindowXMin, f3D2DXCoef); pObject -> y = XDM_to3D(iY, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y pObject -> z = XDM_to3D(iX, fZmin, iWindowXMin, f3D2DXCoef); pObject -> y = XDM_to3D(iY, fYmin, iWindowYMin, f3D2DYCoef); break; } // Si la grille est activée, snapper l'objet à la grille (en x/y/z) if (bGrid) { pObject -> x = XDM_toGrid(pObject -> x); pObject -> y = XDM_toGrid(pObject -> y); pObject -> z = XDM_toGrid(pObject -> z); } // Mémoriser les coordonnées pour l'affichage des coordonnées if (bCoords) vTracker = *pObject; // Si on a déplacé l'observer ou le target, mettre à jour la VIEW MATRIX // (la vue 3D se met automatiquement à jour par timer dans 3dwndproc) if ((pObject == &Target) || (pObject == &Observer)) { D3DUtil_SetViewMatrix(matView, Observer, // From Target, // To D3DVECTOR(0.f, 0.f, 0.f)); // Mettre à jour les variables d'état du pipe D3D vSetD3DState(); // Recalculer la scène vForce3DRefresh(XDC_MODE_COMPLET); } // Si on a un outil sélectionné, appliquer l'outil à la sélection if ((pObject == &Cursor1) && (cTool != XDC_TOOL_NONE)) { switch(cTool) { case XDC_TOOL_SELECT: PostMessage(hWndMenu, WM_COMMAND, ID_EDITION_SLECTIONNER_NOEUDINDIQU, XDC_SELECTALL); break; case XDC_TOOL_UNSELECT: PostMessage(hWndMenu, WM_COMMAND, ID_EDITION_SLECTIONNER_NOEUDINDIQU, XDC_DESELECTALL); break; case XDC_TOOL_MAGNET: break; case XDC_TOOL_CURVE: break; case XDC_TOOL_EXTRUDE: break; case XDC_TOOL_EDGE: break; case XDC_TOOL_GRAB: // Faire suivre le mouvement du curseur à tous les vertices sélectionnés for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++) if (bIsVertexSelected(iVertex)) Vertices[iVertex].vPoint += (Cursor1 - vVect1); // Faire suivre le mouvement du curseur à toutes les lampes sélectionnées for (int iLamp = 0 ; iLamp <= iLampLastUsed ; iLamp++) { if (Lampes[iLamp].bEnabled == FALSE) continue; if (Lampes[iLamp].bSelected == FALSE) continue; Lampes[iLamp].lLamp.dvPosition += (Cursor1 - vVect1); bUpdateLamp(iLamp); } vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); goto _break; } } // Forcer le redessin des fenêtres 2D pour prendre en compte le déplacement de l'objet vForce2DRefresh(XDC_MODE_PARTIEL); _break: break; case WM_SIZE: //**************** T A I L L E F E N E T R E **************** // Si le contexte Warp3D n'est pas initialisé, on s'arrête là if (!hW3DContext) return 0; // Détruire et recréer le double buffer avec les nouvelles dimensions de la fenêtre iX = LOWORD(lParam); // width of client area iY = HIWORD(lParam); // height of client area // Supprimer le bitmap offscreen du double buffer s'il est alloué if (pWT -> hbDBuf) FreeBitMap(pWT -> hbDBuf); // Créer le bitmap offscreen du double buffer if (!(pWT -> hbDBuf = AllocBitMap(hWnd -> Width, hWnd -> Height, 8, BMF_MINPLANES | BMF_DISPLAYABLE, hWnd -> RPort -> BitMap))) { vTrace("*** E0075 : allocation double buffer %s", hWnd -> Title); return 0; } pWT -> hdcDBuf -> BitMap = pWT -> hbDBuf; // Libérer le clipping de la fenêtre s'il est activé if (pWT -> hClip != (struct Region *) ~NULL) { UnclipWindow(hWnd); pWT -> hClip = (struct Region *) ~NULL; } // Remplir l'ensemble de la zone cliente en bleu foncé rExtRect.left = hWnd -> BorderLeft; rExtRect.right = iX - hWnd -> BorderRight - 1; rExtRect.top = hWnd -> BorderTop; rExtRect.bottom = iY - hWnd -> BorderBottom - 1; SetAPen(hdcWin, hpenDkBlueSk); RectFill(hdcWin, rExtRect.left, rExtRect.top, rExtRect.right, rExtRect.bottom); // Séparer les zones int/ext avec tour blanc CopyRect(&rIntRect, &rExtRect); InflateRect(&rIntRect, -XDC_G_LARG, -XDC_G_HAUT); SetAPen(hdcWin, hpenWhite); { short rRect[10]; rRect[0] = rIntRect.left; rRect[1] = rIntRect.bottom; rRect[2] = rIntRect.right; rRect[3] = rIntRect.bottom; rRect[4] = rIntRect.right; rRect[5] = rIntRect.top; rRect[6] = rIntRect.left; rRect[7] = rIntRect.top; rRect[8] = rIntRect.left; rRect[9] = rIntRect.bottom; Move(hdcWin, iWindowXMin, iWindowYMin); PolyDraw(hdcWin, 5, &rRect[0]); } // Tracer les noms des axes switch(lWActive) { case XDC_WID_TOP : // Axes X (gauche > droite) et Z (bas > haut) cAxis = 'z'; ExtTextOut(hdcWin, (rExtRect.right - rExtRect.left) / 2 + 13, -3, 0, (RECT *) NULL, &cAxis, 1, (int *) NULL); cAxis = 'x'; ExtTextOut(hdcWin, rExtRect.right - XDC_G_LARG + 5, (rExtRect.bottom - rExtRect.top) / 2 + 4, 0, (RECT *) NULL, &cAxis, 1, (int *) NULL); break; case XDC_WID_FACE : // Axes X (gauche > droite) et Y (bas > haut) cAxis = 'y'; ExtTextOut(hdcWin, (rExtRect.right - rExtRect.left) / 2 + 13, -3, 0, (RECT *) NULL, &cAxis, 1, (int *) NULL); cAxis = 'x'; ExtTextOut(hdcWin, rExtRect.right - XDC_G_LARG + 5, (rExtRect.bottom - rExtRect.top) / 2 + 4, 0, (RECT *) NULL, &cAxis, 1, (int *) NULL); break; case XDC_WID_SIDE : // Axes Z (gauche > droite) et Y (bas > haut) cAxis = 'y'; ExtTextOut(hdcWin, (rExtRect.right - rExtRect.left) / 2 + 13, -3, 0, (RECT *) NULL, &cAxis, 1, (int *) NULL); cAxis = 'z'; ExtTextOut(hdcWin, rExtRect.right - XDC_G_LARG + 5, (rExtRect.bottom - rExtRect.top) / 2 + 4, 0, (RECT *) NULL, &cAxis, 1, (int *) NULL); break; } // Ajouter tous les gadgets Sculpt XDM_Bouton(pWT -> Widgets[XDC_GID_AddPoint], rExtRect.left, rExtRect.top + 11); XDM_Bouton(pWT -> Widgets[XDC_GID_Center], XDC_G_LARG + 6, rExtRect.bottom - XDC_G_HAUT + 1); XDM_Bouton(pWT -> Widgets[XDC_GID_GoDown], (rExtRect.right - rExtRect.left) / 2 - 4, rExtRect.bottom - XDC_G_HAUT + 1); XDM_Bouton(pWT -> Widgets[XDC_GID_GoLeft], rExtRect.left, (rExtRect.bottom - rExtRect.top) / 2 + 6); XDM_Bouton(pWT -> Widgets[XDC_GID_GoUp], (rExtRect.right - rExtRect.left) / 2 - 4, rExtRect.top); XDM_Bouton(pWT -> Widgets[XDC_GID_GoRight], rExtRect.right - XDC_G_LARG + 1, (rExtRect.bottom - rExtRect.top) / 2 + 6); XDM_Bouton(pWT -> Widgets[XDC_GID_Grab], rExtRect.left, rExtRect.bottom - XDC_G_HAUT + 1); XDM_Bouton(pWT -> Widgets[XDC_GID_MakeTri], rExtRect.left, rExtRect.bottom - 19); XDM_Bouton(pWT -> Widgets[XDC_GID_Reverse], rExtRect.right - XDC_G_LARG + 1, 26); XDM_Bouton(pWT -> Widgets[XDC_GID_RotAnti], rExtRect.left, rExtRect.top); XDM_Bouton(pWT -> Widgets[XDC_GID_RotClock], XDC_G_LARG + 6, rExtRect.top); XDM_Bouton(pWT -> Widgets[XDC_GID_ZoomIn], rExtRect.right - 36, rExtRect.bottom - XDC_G_HAUT + 1); XDM_Bouton(pWT -> Widgets[XDC_GID_ZoomOut], rExtRect.right - XDC_G_LARG + 1, rExtRect.bottom - 20); // Définir la zone de clipping : rectangle interne pWT -> hClip = ClipWindow(hWnd, rExtRect.left, rExtRect.top, rExtRect.right, rExtRect.bottom); // Blitter la fenêtre dans le double buffer ClipBlit(hdcWin, hWnd -> BorderLeft, hWnd -> BorderTop, pWT -> hdcDBuf, hWnd -> BorderLeft, hWnd -> BorderTop, iX - hWnd -> BorderRight - 1, iY - hWnd -> BorderBottom - 1, 0xC0); // Déterminer s'il faut réallouer le triple buffer : // - s'il n'est pas déjà alloué ou // - s'il est plus petit que la fenêtre redimensionnée ou // - s'il est plus grand que les trois fenêtres { int iXMax = 0, iYMax = 0; if (iXMax < hWndTop -> Width) iXMax = hWndTop -> Width; if (iXMax < hWndFace -> Width) iXMax = hWndFace -> Width; if (iXMax < hWndRight -> Width) iXMax = hWndRight -> Width; if (iYMax < hWndTop -> Height) iYMax = hWndTop -> Height; if (iYMax < hWndFace -> Height) iYMax = hWndFace -> Height; if (iYMax < hWndRight -> Height) iYMax = hWndRight -> Height; iX = GetBitMapAttr(hbTBuf, BMA_WIDTH); iY = GetBitMapAttr(hbTBuf, BMA_HEIGHT); if (!hbTBuf || iX != iXMax || iY != iYMax) { InitRastPort(hdcTBuf); if (hbTBuf) FreeBitMap(hbTBuf); // Créer le bitmap offscreen du triple buffer if (!(hbTBuf = AllocBitMap(iXMax, iYMax, 8, BMF_MINPLANES | BMF_DISPLAYABLE, hWnd -> RPort -> BitMap))) { vTrace("*** E0076 : allocation triple buffer %d x %d", iXMax, iYMax); break; } hdcTBuf -> BitMap = hbTBuf; vTrace("%s : Redim. triple buffer %d x %d ok", hWnd -> Title, iXMax, iYMax); } } // Forcer le redessin complet de la fenêtre PostMessage(hWnd, WM_PAINT, 0, (LPARAM) XDC_MODE_COMPLET); 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: // Libérer les objets GDI if (hpenWhite) { DeleteObject(hInst -> ViewPort.ColorMap, hpenWhite); hpenWhite = NULL; } if (hpenRed) { DeleteObject(hInst -> ViewPort.ColorMap, hpenRed); hpenRed = NULL; } if (hpenYellow) { DeleteObject(hInst -> ViewPort.ColorMap, hpenYellow); hpenYellow = NULL; } if (hpenCyan) { DeleteObject(hInst -> ViewPort.ColorMap, hpenCyan); hpenCyan = NULL; } if (hpenPink) { DeleteObject(hInst -> ViewPort.ColorMap, hpenPink); hpenPink = NULL; } if (hpenGrey) { DeleteObject(hInst -> ViewPort.ColorMap, hpenGrey); hpenGrey = NULL; } if (hpenLtBlueSk) { DeleteObject(hInst -> ViewPort.ColorMap, hbrLtBlueSk); hbrLtBlueSk = NULL; } if (hpenDkBlueSk) { DeleteObject(hInst -> ViewPort.ColorMap, hpenDkBlueSk); hpenDkBlueSk = NULL; } // Libérer le clipping de la fenêtre s'il est activé if (pWT -> hClip != (struct Region *) ~NULL) { UnclipWindow(hWnd); pWT -> hClip = (struct Region *) ~NULL; } // Supprimer le bitmap offscreen du double buffer s'il est alloué if (pWT -> hbDBuf) FreeBitMap(pWT -> hbDBuf); // Détruire la structure de données attachée à la fenêtre free(pWT); // Supprimer le bitmap offscreen du triple buffer s'il est alloué if (hbTBuf) { FreeBitMap(hbTBuf); hbTBuf = NULL; } PostQuitMessage(0); return 0L; } return 0; }