home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Graphics / sKulpt / skulpt-src / Objects-Base.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-30  |  35.5 KB  |  1,270 lines

  1. #define STRICT
  2.  
  3. // Includes standard Windows
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <time.h>
  7. #include <stdlib.h>
  8. #include <malloc.h>
  9. #include <memory.h>
  10. #include <stdio.h>
  11.  
  12. // Includes D3D
  13. #define  D3D_OVERLOADS
  14. #include <ddraw.h>
  15. #include <d3d.h>
  16.  
  17. // Includes utilitaires D3D
  18. #include "d3dmath.h"
  19. #include "d3dutil.h"
  20. #include "D3DEnum.h"
  21.  
  22. #include <d3dx.h>
  23.  
  24. // Ids Resources
  25. #include "resource.h"
  26.  
  27. // Constantes
  28. #include "const.h"
  29.  
  30. // Types
  31. #include "types.h"
  32.  
  33. // Variables globales projet
  34. #include "vars.h"
  35.  
  36. // Prototypes fonctions autres modules
  37. #include "proto.h"
  38.  
  39. // Macros
  40. #include "macros.h"
  41.  
  42. //************************************* C O M M U N S ***********************
  43. void vDeleteObjects(void)
  44. {
  45.     // RAZ points
  46.     for (int iVert = 0 ; iVert < XDC_NUMPT ; iVert++)
  47.     {
  48.         Vertices[iVert].bEnabled = FALSE;
  49.         Vertices[iVert].bHidden = FALSE;
  50.         Vertices[iVert].bSelected = FALSE;
  51.         Vertices[iVert].bSmooth = FALSE;
  52.         Vertices[iVert].iDepend = 0;
  53.     }
  54.     iVertFirstAvailable = 0;
  55.     iVertLastUsed = -1;
  56.  
  57.     // RAZ arêtes
  58.     for (int iEdge = 0 ; iEdge < XDC_NUMEDGE ; iEdge++)
  59.     {
  60.         Edges[iEdge].bEnabled = FALSE;
  61.         Edges[iEdge].bHidden = FALSE;
  62.     }
  63.     iEdgeFirstAvailable = 0;
  64.     iEdgeLastUsed = -1;
  65.  
  66.     // RAZ lampes
  67.     for (int iLamp = 0 ; iLamp < XDC_NUMLAMP ; iLamp++)
  68.         if (Lampes[iLamp].bEnabled) bDeleteLamp(iLamp);
  69.  
  70.     iLampFirstAvailable = 0;
  71.     iLampLastUsed = -1;
  72.  
  73.     // RAZ facettes
  74.     for (int iTriangle = 0 ; iTriangle < XDC_NUMTRI ; iTriangle++)
  75.     {
  76.         Triangles[iTriangle].bEnabled = FALSE;
  77.         Triangles[iTriangle].bHidden = FALSE;
  78.     }
  79.     iTriaFirstAvailable = 0;
  80.     iTriaLastUsed = -1;
  81.  
  82.     // RAZ matériaux
  83.     for (int iMtrl = 0 ; iMtrl < XDC_NUMMTRL ; iMtrl++)
  84.     {
  85.         Materials[iMtrl].bEnabled = FALSE;
  86.         Materials[iMtrl].bTextured = FALSE;
  87.     }
  88.     iMtrlFirstAvailable = 0;
  89.     iMtrlLastUsed = -1;
  90.  
  91.     iFastMaterial("Blanc",    255,  255,  255);
  92.     iFastMaterial("Noir",       0,    0,    0);
  93.     iFastMaterial("Rouge",    255,    0,    0);
  94.     iFastMaterial("Vert",       0,  255,    0);
  95.     iFastMaterial("Bleu",       0,    0,  255);
  96.  
  97. #ifndef _AMIGA_
  98.     // RAZ Objets D3D
  99.     vDeleteD3DObjects();
  100. #endif
  101. }
  102.  
  103. //************************************** M A T E R I A L S *************************
  104. BOOL bSameMaterial(D3DMATERIAL7 *hMtrl1, D3DMATERIAL7 *hMtrl2)
  105. {
  106.     double fDist =
  107.                     fabs(hMtrl2 -> ambient.a - hMtrl1 -> ambient.a) +
  108.                     fabs(hMtrl2 -> ambient.r - hMtrl1 -> ambient.r) +
  109.                     fabs(hMtrl2 -> ambient.g - hMtrl1 -> ambient.g) +
  110.                     fabs(hMtrl2 -> ambient.b - hMtrl1 -> ambient.b) +
  111.  
  112.                     fabs(hMtrl2 -> diffuse.a - hMtrl1 -> diffuse.a) +
  113.                     fabs(hMtrl2 -> diffuse.r - hMtrl1 -> diffuse.r) +
  114.                     fabs(hMtrl2 -> diffuse.g - hMtrl1 -> diffuse.g) +
  115.                     fabs(hMtrl2 -> diffuse.b - hMtrl1 -> diffuse.b) +
  116.  
  117.                     fabs(hMtrl2 -> specular.a - hMtrl1 -> specular.a) +
  118.                     fabs(hMtrl2 -> specular.r - hMtrl1 -> specular.r) +
  119.                     fabs(hMtrl2 -> specular.g - hMtrl1 -> specular.g) +
  120.                     fabs(hMtrl2 -> specular.b - hMtrl1 -> specular.b) +
  121.                     fabs(hMtrl2 -> power - hMtrl1 -> power);
  122.  
  123.     return (fDist < 0.1);
  124. }
  125.  
  126. int iFindMaterial(D3DMATERIAL7 *hMtrl, int iPrevious)
  127. {
  128.     int iCnt;
  129.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  130.     
  131.     // Rechercher le matériau
  132.     for (iCnt = max(iPrevious + 1, 0) ;
  133.             (iCnt <= iMtrlLastUsed)
  134.          && (!(   (Materials[iCnt].bEnabled == TRUE)
  135.                && (!bSameMaterial(hMtrl, &(Materials[iCnt].mtrl)))
  136.               ))
  137.          ;
  138.          iCnt++) ;
  139.  
  140.     // Si matériau trouvé alors renvoyer son indice
  141.     if (iCnt <= iMtrlLastUsed)
  142.         return(iCnt);
  143.  
  144.     // Sinon renvoyer -1
  145.     return -1;
  146. }
  147.  
  148. BOOL bTextureMaterial(int iMtrl, char *sTexName)
  149. {
  150.     if (iMtrl > iMtrlLastUsed) return FALSE;
  151.     if (!Materials[iMtrl].bEnabled) return FALSE;
  152.  
  153.     if (sTexName) // Il faudrait sans doute uploader la texture...
  154.     {
  155.         strcpy(Materials[iMtrl].sTexName, sTexName);
  156.         Materials[iMtrl].hTexture = NULL;
  157.         Materials[iMtrl].bTextured = TRUE;
  158.     }
  159.     else // Il faudrait sans doute releaser la texture...
  160.         Materials[iMtrl].bTextured = FALSE;
  161.  
  162.     return TRUE;
  163. }
  164.  
  165. int iFastMaterial(char *sName, unsigned char bRouge, unsigned char bVert, unsigned char bBleu)
  166. {
  167.     D3DMATERIAL7 Mtrl, *pMtrl = &Mtrl;
  168.     ZeroMemory(pMtrl, sizeof(D3DMATERIAL7));
  169.     pMtrl -> ambient.a = 0.8f;
  170.     pMtrl -> ambient.r = (float) bRouge / 256.f / 6.f;
  171.     pMtrl -> ambient.g = (float) bVert / 256.f / 6.f;
  172.     pMtrl -> ambient.b = (float) bBleu / 256.f / 6.f;
  173.  
  174.     pMtrl -> diffuse.a = 0.8f;
  175.     pMtrl -> diffuse.r = (float) bRouge / 256.f;
  176.     pMtrl -> diffuse.g = (float) bVert / 256.f;
  177.     pMtrl -> diffuse.b = (float) bBleu / 256.f;
  178.  
  179.     pMtrl -> specular.a = 0.8f;
  180.     pMtrl -> specular.r = 1.f;
  181.     pMtrl -> specular.g = 1.f;
  182.     pMtrl -> specular.b = 1.f;
  183.     pMtrl -> power = 1.f;
  184.  
  185.     return iMakeMaterial(pMtrl, sName, XDC_ALLOWSAME);
  186. }
  187.  
  188. int iMakeMaterial(D3DMATERIAL7 *hMtrl, char *sName, BOOL bSame)
  189. {
  190.     int iCnt;
  191.     
  192.     // Rechercher le premier index libre
  193.     for (iCnt = bSame ? 0 : iMtrlFirstAvailable ;
  194.             (iCnt <= iMtrlLastUsed)
  195.          && (   ((!bSame) && (Materials[iCnt].bEnabled == TRUE))
  196.              || ((bSame) && (!(       (Materials[iCnt].bEnabled == TRUE) 
  197.                                 && (bSameMaterial(hMtrl, &(Materials[iCnt].mtrl)))
  198.                 )            ) )
  199.             ) ;
  200.          iCnt++) ;
  201.  
  202.     // Si limite tableau atteinte alors renvoyer erreur
  203.     if (iCnt >= XDC_NUMMTRL)
  204.     {
  205.         vTrace("*** E0016 : Plus de slots matériaux libres");
  206.         return -1;
  207.     }
  208.  
  209.     // Si matériau trouvé dans tableau alors le renvoyer
  210.     if (bSame)
  211.     {
  212.         if ((iCnt < XDC_NUMMTRL) && (Materials[iCnt].bEnabled == TRUE) 
  213.                                  && (bSameMaterial(hMtrl, &(Materials[iCnt].mtrl))))
  214.             return(iCnt);
  215.         else
  216.             return(iMakeMaterial(hMtrl, sName, XDC_FORCENEW));
  217.     }
  218.  
  219.     // Créer un nouveau point
  220.     Materials[iCnt].mtrl = *hMtrl;
  221.     if (sName) strcpy(Materials[iCnt].sName, sName); else strcpy(Materials[iCnt].sName, "[unnamed]");
  222.     Materials[iCnt].bEnabled  =TRUE;
  223.  
  224.     while (Materials[iMtrlFirstAvailable].bEnabled == TRUE) iMtrlFirstAvailable++;
  225.     if (iMtrlLastUsed < iCnt) iMtrlLastUsed = iCnt;
  226.  
  227.     return iCnt;
  228. }
  229.  
  230.  
  231. BOOL bDeleteMaterial(int iMtrl)
  232. {
  233.     // Si le material n'est pas enabled alors ne rien faire
  234.     if (Materials[iMtrl].bEnabled == FALSE) return FALSE;
  235.  
  236.     // Disabler le point
  237.     Materials[iMtrl].bEnabled = FALSE;
  238.     
  239.     // Mettre à jour les indices globaux du tableau des vertices
  240.     if (iMtrl == iMtrlLastUsed) while ((iMtrlLastUsed > -1) && (!Materials[--iMtrlLastUsed].bEnabled)) ;
  241.     if (iMtrl < iMtrlFirstAvailable) iMtrlFirstAvailable = iMtrl;
  242.  
  243.     return TRUE;
  244. }
  245.  
  246. //************************************** V E R T E X *************************
  247. int iFindVertex(D3DVECTOR p, int iPrevious)
  248. {
  249.     int iCnt;
  250.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  251.     
  252.     // Rechercher le point
  253.     for (iCnt = max(iPrevious + 1, 0) ;
  254.             (iCnt <= iVertLastUsed)
  255.          && (!(   (Vertices[iCnt].bEnabled == TRUE)
  256.                && (Vertices[iCnt].bHidden == FALSE)
  257.                && (fabs(Vertices[iCnt].vPoint.x - p.x) < fTolerance)
  258.                && (fabs(Vertices[iCnt].vPoint.y - p.y) < fTolerance)
  259.                && (fabs(Vertices[iCnt].vPoint.z - p.z) < fTolerance)
  260.               ))
  261.          ;
  262.          iCnt++) ;
  263.  
  264.     // Si point trouvé alors renvoyer son indice
  265.     if (iCnt <= iVertLastUsed)
  266.         return(iCnt);
  267.  
  268.     // Sinon renvoyer -1
  269.     return -1;
  270. }
  271.  
  272. int iMakeVertex(D3DVECTOR p, BOOL bSame)
  273. {
  274.     int iCnt;
  275.     
  276.     // Rechercher le premier index libre
  277.     for (iCnt = bSame ? 0 : iVertFirstAvailable ;
  278.             (iCnt <= iVertLastUsed)
  279.          && (   ((!bSame) && (Vertices[iCnt].bEnabled == TRUE))
  280.              || ((bSame) && (!((Vertices[iCnt].bEnabled == TRUE) && (Vertices[iCnt].bHidden == FALSE) && (Magnitude(Vertices[iCnt].vPoint - p) < 10.f * g_EPSILON))))
  281.             ) ;
  282.          iCnt++) ;
  283.  
  284.     // Si limite tableau atteinte alors renvoyer erreur
  285.     if (iCnt >= XDC_NUMPT)
  286.     {
  287.         vTrace("*** E0016 : Plus de slots vertex libres");
  288.         return -1;
  289.     }
  290.  
  291.     // Si point trouvé dans tableau alors le renvoyer
  292.     if (bSame)
  293.     {
  294.         if ((iCnt < XDC_NUMPT) && (Vertices[iCnt].bEnabled == TRUE) && (Vertices[iCnt].bHidden == FALSE) && (Magnitude(Vertices[iCnt].vPoint - p) < 10.f * g_EPSILON))
  295.             return(iCnt);
  296.         else
  297.             return(iMakeVertex(p, XDC_FORCENEW));
  298.     }
  299.  
  300.     // Créer un nouveau point
  301.     Vertices[iCnt].vPoint = p;
  302.     Vertices[iCnt].bSelected = FALSE;
  303.     Vertices[iCnt].bHidden = FALSE;
  304.     Vertices[iCnt].bEnabled  =TRUE;
  305.  
  306.     while (Vertices[iVertFirstAvailable].bEnabled == TRUE) iVertFirstAvailable++;
  307.     if (iVertLastUsed < iCnt) iVertLastUsed = iCnt;
  308.  
  309.     return iCnt;
  310. }
  311.  
  312. BOOL bVertInEdge(int iVert, int iEdge)
  313. {
  314.     if (    (Edges[iEdge].iSommets[0] == iVert)
  315.          || (Edges[iEdge].iSommets[1] == iVert)
  316.        )
  317.         return TRUE;
  318.     else
  319.         return FALSE;
  320. }
  321.  
  322. BOOL bVertInTriangle(int iVert, int iTriangle)
  323. {
  324.     if (    (Triangles[iTriangle].iSommets[0] == iVert)
  325.          || (Triangles[iTriangle].iSommets[1] == iVert)
  326.          || (Triangles[iTriangle].iSommets[2] == iVert)
  327.        )
  328.         return TRUE;
  329.     else
  330.         return FALSE;
  331. }
  332.  
  333. int iEdgesPerVert(int iVert)
  334. {
  335.     int iCnt, jCnt = 0;
  336.  
  337.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  338.         if (bVertInEdge(iVert, iCnt))
  339.             jCnt++;
  340.  
  341.     return jCnt;
  342. }
  343.  
  344. int iTrianglesPerVert(int iVert)
  345. {
  346.     int iCnt, jCnt = 0;
  347.  
  348.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  349.         if (bVertInTriangle(iVert, iCnt))
  350.             jCnt++;
  351.  
  352.     return jCnt;
  353. }
  354.  
  355. BOOL bDeleteVertex(int iVert)
  356. {
  357.     int iCnt;
  358.  
  359.     // Si le point n'est pas enabled alors ne rien faire
  360.     if (Vertices[iVert].bEnabled == FALSE) return FALSE;
  361.  
  362.     // Disabler le point
  363.     Vertices[iVert].bEnabled = FALSE;
  364.     
  365.     // Mettre à jour les indices globaux du tableau des vertices
  366.     if (iVert == iVertLastUsed) while ((iVertLastUsed > -1) && (!Vertices[--iVertLastUsed].bEnabled)) ;
  367.     if (iVert < iVertFirstAvailable) iVertFirstAvailable = iVert;
  368.  
  369.     // Supprimer toutes les arêtes desquelles le sommet supprimé est une extrêmité
  370.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  371.         if (bVertInEdge(iVert, iCnt))
  372.             bDeleteEdge(iCnt);
  373.  
  374.     // Pour tout triangle duquel le sommet supprimé est un sommet, transformer le triangle en une arête entre les 2 sommets restants
  375.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  376.         if (bVertInTriangle(iVert, iCnt))
  377.         {
  378.             /*
  379.             if (Triangles[iCnt].iSommets[0] == iVert) iMakeEdge(Triangles[iCnt].iSommets[1], Triangles[iCnt].iSommets[2]);
  380.             if (Triangles[iCnt].iSommets[1] == iVert) iMakeEdge(Triangles[iCnt].iSommets[0], Triangles[iCnt].iSommets[2]);
  381.             if (Triangles[iCnt].iSommets[2] == iVert) iMakeEdge(Triangles[iCnt].iSommets[0], Triangles[iCnt].iSommets[1]);
  382.             */
  383.             bDeleteTriangle(iCnt);
  384.         }
  385.  
  386.     return TRUE;
  387. }
  388.  
  389. #ifndef _AMIGA_
  390. BOOL bSmoothNorm(int iVertex)
  391. {
  392.     if (Vertices[iVertex].bEnabled == FALSE) return FALSE;
  393.     if (Vertices[iVertex].bSmooth == FALSE) return FALSE;
  394.     if (Vertices[iVertex].iDepend == 0) return FALSE;
  395.  
  396.     D3DVECTOR vn = D3DVECTOR(0.f, 0.f, 0.f);
  397.  
  398.     for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
  399.     {
  400.         if (Triangles[iTriangle].bEnabled == FALSE) continue;
  401.         if (!bVertInTriangle(iVertex, iTriangle)) continue;
  402.  
  403.         D3DVECTOR vc;
  404. /*
  405.         short iS0 = Triangles [iTriangle].iSommets[0],
  406.               iS1 = Triangles [iTriangle].iSommets[1],
  407.               iS2 = Triangles [iTriangle].iSommets[2];
  408.  
  409.         D3DVECTOR
  410.                 v01 = Vertices[iS1].vPoint - Vertices[iS0].vPoint,
  411.                 v02 = Vertices[iS2].vPoint - Vertices[iS0].vPoint,
  412.                 v12 = Vertices[iS2].vPoint - Vertices[iS1].vPoint,
  413.                 vn0, vn1, vn2;
  414.  
  415.         vn0 = Normalize(CrossProduct(v01, v02));
  416.         vn1 = Normalize(CrossProduct(v01, v12));
  417.         vn2 = Normalize(CrossProduct(v02, v12));
  418.  
  419. */
  420.         for (int iCnt = 0 ; iCnt < 3 ; iCnt++)
  421.             if (iVertex == Triangles [iTriangle].iSommets[iCnt])
  422.                 vc = D3DVECTOR(
  423.                     Triangles [iTriangle].pSommets[iCnt].nx,
  424.                     Triangles [iTriangle].pSommets[iCnt].ny,
  425.                     Triangles [iTriangle].pSommets[iCnt].nz);
  426.  
  427. /*
  428.         if (iVertex == iS0) vc = vn0;
  429.         if (iVertex == iS1) vc = vn1;
  430.         if (iVertex == iS2) vc = vn2;
  431.  
  432.         float fdp = DotProduct(vn, vc);
  433.  
  434.         if (fdp >= 0)
  435. */
  436.             vn += vc;
  437. /*
  438.         else
  439.             vn -= vc;
  440. */
  441.     }
  442.  
  443.     Vertices[iVertex].vNormal = Normalize(vn);
  444.  
  445.     return TRUE;
  446. }
  447. #endif
  448.  
  449. BOOL bIsVertexSelected(int iVertex)
  450. {
  451.     return
  452.         Vertices[iVertex].bEnabled && Vertices[iVertex].bSelected;
  453. }
  454.  
  455. //************************************** L A M P E S *************************
  456. int iFindLamp(D3DVECTOR p, int iPrevious)
  457. {
  458.     int iCnt;
  459.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  460.     
  461.     // Rechercher la lampe
  462.     for (iCnt = max(iPrevious + 1, 0) ;
  463.             (iCnt <= iLampLastUsed)
  464.          && (!(   (Lampes[iCnt].bEnabled == TRUE)
  465.                && (fabs(Lampes[iCnt].lLamp.dvPosition.x - p.x) < fTolerance)
  466.                && (fabs(Lampes[iCnt].lLamp.dvPosition.y - p.y) < fTolerance)
  467.                && (fabs(Lampes[iCnt].lLamp.dvPosition.z - p.z) < fTolerance)
  468.               ))
  469.          ;
  470.          iCnt++) ;
  471.  
  472.     // Si point trouvé alors renvoyer son indice
  473.     if (iCnt <= iLampLastUsed)
  474.         return(iCnt);
  475.  
  476.     // Sinon renvoyer -1
  477.     return -1;
  478. }
  479.  
  480. int iMakeLamp(
  481.     D3DLIGHTTYPE    dltType,            /* Type of light source */
  482.     D3DCOLORVALUE   dcvDiffuse,         /* Diffuse color of light */
  483.     D3DCOLORVALUE   dcvSpecular,        /* Specular color of light */
  484.     D3DCOLORVALUE   dcvAmbient,         /* Ambient color of light */
  485.     D3DVECTOR       dvPosition,         /* Position in world space */
  486.     D3DVECTOR       dvDirection,        /* Direction in world space */
  487.     D3DVALUE        dvRange,            /* Cutoff range */
  488.     D3DVALUE        dvFalloff,          /* Falloff */
  489.     D3DVALUE        dvAttenuation0,     /* Constant attenuation */
  490.     D3DVALUE        dvAttenuation1,     /* Linear attenuation */
  491.     D3DVALUE        dvAttenuation2,     /* Quadratic attenuation */
  492.     D3DVALUE        dvTheta,            /* Inner angle of spotlight cone */
  493.     D3DVALUE        dvPhi               /* Outer angle of spotlight cone */
  494. )
  495. {
  496.     int iCnt;
  497.     
  498.     // Rechercher le premier index libre
  499.     for (iCnt = iLampFirstAvailable ;
  500.             (iCnt <= iLampLastUsed)
  501.          && (Lampes[iCnt].bEnabled == TRUE) ;
  502.          iCnt++) ;
  503.  
  504.     // Si limite tableau atteinte alors renvoyer erreur
  505.     if (iCnt >= XDC_NUMLAMP)
  506.     {
  507.         vTrace("*** E0017 : Plus de slots vertex libres");
  508.         return -1;
  509.     }
  510.  
  511.     // Créer une nouvelle lampe
  512.     ZeroMemory(&Lampes[iCnt].lLamp, sizeof(D3DLIGHT7));
  513.     Lampes[iCnt].bEnabled = TRUE;
  514.     Lampes[iCnt].bSelected = FALSE;
  515.     Lampes[iCnt].bLit = TRUE;
  516.     Lampes[iCnt].lLamp.dltType = dltType; // D3DLIGHT_POINT ou D3DLIGHT_DIRECTIONAL ou D3DLIGHT_SPOT
  517.     Lampes[iCnt].lLamp.dcvDiffuse = dcvDiffuse;
  518.     Lampes[iCnt].lLamp.dcvSpecular = dcvSpecular;
  519.     Lampes[iCnt].lLamp.dcvAmbient = dcvAmbient;
  520.     Lampes[iCnt].lLamp.dvPosition = dvPosition;
  521.     Lampes[iCnt].lLamp.dvDirection = dvDirection;
  522.     Lampes[iCnt].lLamp.dvRange = dvRange;
  523.     Lampes[iCnt].lLamp.dvFalloff = dvFalloff;
  524.     Lampes[iCnt].lLamp.dvAttenuation0 = dvAttenuation0; 
  525.     Lampes[iCnt].lLamp.dvAttenuation1 = dvAttenuation1; 
  526.     Lampes[iCnt].lLamp.dvAttenuation2 = dvAttenuation2; 
  527.     Lampes[iCnt].lLamp.dvTheta = dvTheta; 
  528.     Lampes[iCnt].lLamp.dvPhi = dvPhi; 
  529.  
  530. #ifndef NO3D
  531.     lpd3dDevice->SetLight(iCnt, &Lampes[iCnt].lLamp);
  532.     lpd3dDevice->LightEnable(iCnt, Lampes[iCnt].bLit);
  533. #endif
  534.  
  535.     while (Lampes[iLampFirstAvailable].bEnabled == TRUE) iLampFirstAvailable++;
  536.     if (iLampLastUsed < iCnt) iLampLastUsed = iCnt;
  537.  
  538.     return iCnt;
  539. }
  540.  
  541. BOOL bUpdateLamp(int iLamp)
  542. {
  543.     // Si la lampe n'est pas enabled alors ne rien faire
  544.     if (Lampes[iLamp].bEnabled == FALSE) return FALSE;
  545.  
  546. #ifndef NO3D
  547.     lpd3dDevice->SetLight(iLamp, &Lampes[iLamp].lLamp);
  548.     lpd3dDevice->LightEnable(iLamp, Lampes[iLamp].bLit);
  549. #endif
  550.  
  551.     return TRUE;
  552. }
  553.  
  554. BOOL bDeleteLamp(int iLamp)
  555. {
  556.     // Si la lampe n'est pas enabled alors ne rien faire
  557.     if (Lampes[iLamp].bEnabled == FALSE) return FALSE;
  558.  
  559.     // Disabler la lampe
  560. #ifndef NO3D
  561.     lpd3dDevice->LightEnable(iLamp, FALSE);
  562. #endif
  563.     Lampes[iLamp].bEnabled = FALSE;
  564.     Lampes[iLamp].bLit = FALSE;
  565.     
  566.     // Mettre à jour les indices globaux du tableau des lampes
  567.     if (iLamp == iLampLastUsed) while ((iLampLastUsed > -1) && (!Lampes[--iLampLastUsed].bEnabled)) ;
  568.     if (iLamp < iLampFirstAvailable) iLampFirstAvailable = iLamp;
  569.  
  570.     return TRUE;
  571. }
  572.  
  573. //************************************** E D G E S ***************************
  574. int iFindEdge(int i1, int i2)
  575. {
  576.     int iCnt;
  577.  
  578.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  579.         if (    ((Edges[iCnt].iSommets[0] == i1) || (Edges[iCnt].iSommets[1] == i1))
  580.              && ((Edges[iCnt].iSommets[0] == i2) || (Edges[iCnt].iSommets[1] == i2))
  581.            )
  582.            return iCnt;
  583.  
  584.     return -1;
  585. }
  586.  
  587. int iMakeEdge(int i1, int i2)
  588. {
  589.     int iCnt;
  590.  
  591.     // Rechercher un slot d'arête libre
  592.     for (iCnt = iEdgeFirstAvailable ; (iCnt <= iEdgeLastUsed) && (Edges [iCnt].bEnabled == TRUE) ; iCnt++);
  593.  
  594.     // Si pas trouvé alors fail
  595.     if (iCnt >= XDC_NUMEDGE)
  596.     {
  597.         vTrace("*** E0018 : Plus de slots arêtes libres");
  598.         return -1;
  599.     }
  600.  
  601.     // Créer l'arête
  602.     Edges [iCnt].iSommets[0] = i1;
  603.     Edges [iCnt].iSommets[1] = i2;
  604.  
  605.     Edges[iCnt].bEnabled = TRUE;
  606.     Edges[iCnt].bHidden = FALSE;
  607.  
  608.     while (Edges[iEdgeFirstAvailable].bEnabled == TRUE) iEdgeFirstAvailable++;
  609.     if (iEdgeLastUsed < iCnt) iEdgeLastUsed = iCnt;
  610.     
  611.     return iCnt;
  612. }
  613.  
  614. BOOL bDeleteEdge(int iEdge)
  615. {
  616.     // Si l'arête n'est pas enabled alors ne rien faire
  617.     if (Edges[iEdge].bEnabled == FALSE) return FALSE;
  618.  
  619.     // Disabler l'arête
  620.     Edges[iEdge].bEnabled = FALSE;
  621.     
  622.     // Mettre à jour les indices globaux du tableau des arêtes
  623.     if (iEdge == iEdgeLastUsed) while ((iEdgeLastUsed > -1) && !(Edges[--iEdgeLastUsed].bEnabled)) ;
  624.     if (iEdge < iEdgeFirstAvailable) iEdgeFirstAvailable = iEdge;
  625.  
  626.     return TRUE;
  627. }
  628.  
  629. BOOL    bIsEdgeSelected(int iEdge)
  630. {
  631.     return
  632.         Edges[iEdge].bEnabled &&
  633.         bIsVertexSelected(Edges[iEdge].iSommets[0]) &&
  634.         bIsVertexSelected(Edges[iEdge].iSommets[1]);
  635. }
  636.  
  637. BOOL    bIsEdgePartiallySelected(int iEdge)
  638. {
  639.     return 
  640.         Edges[iEdge].bEnabled &&
  641.         (bIsVertexSelected(Edges[iEdge].iSommets[0]) ||
  642.          bIsVertexSelected(Edges[iEdge].iSommets[1]));
  643. }
  644.  
  645. //************************************** T R I A N G L E S *******************
  646. int iFindTriangle(int i1, int i2, int i3)
  647. {
  648.     int iCnt;
  649.  
  650.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  651.         if (    ((Triangles[iCnt].iSommets[0] == i1) || (Triangles[iCnt].iSommets[1] == i1) || (Triangles[iCnt].iSommets[2] == i1))
  652.              && ((Triangles[iCnt].iSommets[0] == i2) || (Triangles[iCnt].iSommets[1] == i2) || (Triangles[iCnt].iSommets[2] == i2))
  653.              && ((Triangles[iCnt].iSommets[0] == i3) || (Triangles[iCnt].iSommets[1] == i3) || (Triangles[iCnt].iSommets[2] == i3))
  654.            )
  655.            return iCnt;
  656.  
  657.     return -1;
  658. }
  659.  
  660. BOOL bSetUV(int iTriangle, int u0, int v0, int u1, int v1, int u2, int v2)
  661. {
  662.     if (iTriangle > iTriaLastUsed) return FALSE;
  663.     if (!Triangles[iTriangle].bEnabled) return FALSE;
  664.  
  665.     Triangles[iTriangle].u[0] = u0;
  666.     Triangles[iTriangle].u[1] = u1;
  667.     Triangles[iTriangle].u[2] = u2;
  668.     Triangles[iTriangle].v[0] = v0;
  669.     Triangles[iTriangle].v[1] = v1;
  670.     Triangles[iTriangle].v[2] = v2;
  671.  
  672.     return TRUE;
  673. }
  674.  
  675. int iMakeTriangle(int i1, int i2, int i3, int iMtrl)
  676. {
  677.     int iCnt;
  678.  
  679.     // Rechercher un slot de triangle libre
  680.     for (iCnt = iTriaFirstAvailable ; (iCnt <= iTriaLastUsed) && (Triangles [iCnt].bEnabled == TRUE) ; iCnt++);
  681.  
  682.     // Si pas trouvé alors fail
  683.     if (iCnt >= XDC_NUMTRI)
  684.     {
  685.         vTrace("*** E0019 : Plus de slots triangles libres");
  686.         return -1;
  687.     }
  688.  
  689.     // Créer le triangle
  690.     Triangles [iCnt].iSommets[0] = i1;
  691.     Triangles [iCnt].iSommets[1] = i2;
  692.     Triangles [iCnt].iSommets[2] = i3;
  693.  
  694.     // Incrémenter le compteur de triangles des sommets
  695.     Vertices[Triangles [iCnt].iSommets[0]].iDepend++;
  696.     Vertices[Triangles [iCnt].iSommets[1]].iDepend++;
  697.     Vertices[Triangles [iCnt].iSommets[2]].iDepend++;
  698.  
  699.     // Affecter couleur et aspect
  700.     Triangles[iCnt].iMtrl = iMtrl;
  701.     Triangles[iCnt].bEnabled = TRUE;
  702.     Triangles[iCnt].bHidden = FALSE;
  703.  
  704. #ifndef _AMIGA_
  705.     // Mettre à jour les coordonnées du triangle D3D correspondant
  706.     bUpdateD3DTri(iCnt);
  707. #endif
  708.  
  709.     while (Triangles[iTriaFirstAvailable].bEnabled == TRUE) iTriaFirstAvailable++;
  710.     if (iTriaLastUsed < iCnt) iTriaLastUsed = iCnt;
  711.     
  712.     return iCnt;
  713. }
  714.  
  715. BOOL bDeleteTriangle(int iTriangle)
  716. {
  717.     // Si le triangle n'est pas enabled alors ne rien faire
  718.     if (Triangles[iTriangle].bEnabled == FALSE) return FALSE;
  719.  
  720.     // Disabler le triangle
  721.     Triangles[iTriangle].bEnabled = FALSE;
  722.     
  723.     // Mettre à jour les indices globaux du tableau des triangles
  724.     if (iTriangle == iTriaLastUsed) while ((iTriaLastUsed > -1) && (!Triangles[--iTriaLastUsed].bEnabled)) ;
  725.     if (iTriangle < iTriaFirstAvailable) iTriaFirstAvailable = iTriangle;
  726.  
  727.     // Décrémenter le compteur de triangles des sommets
  728.     Vertices[Triangles [iTriangle].iSommets[0]].iDepend--;
  729.     Vertices[Triangles [iTriangle].iSommets[1]].iDepend--;
  730.     Vertices[Triangles [iTriangle].iSommets[2]].iDepend--;
  731.  
  732.     return TRUE;
  733. }
  734.  
  735. #ifndef _AMIGA_
  736. BOOL bUpdateD3DTri(int iCnt)
  737. {
  738.     if (Triangles[iCnt].bEnabled == FALSE) return FALSE;
  739.     
  740.     short iS0 = Triangles [iCnt].iSommets[0],
  741.           iS1 = Triangles [iCnt].iSommets[1],
  742.           iS2 = Triangles [iCnt].iSommets[2];
  743.  
  744.     D3DVECTOR
  745.             v01 = Vertices[iS1].vPoint - Vertices[iS0].vPoint,
  746.             v02 = Vertices[iS2].vPoint - Vertices[iS0].vPoint,
  747.             v12 = Vertices[iS2].vPoint - Vertices[iS1].vPoint,
  748.             vn0, vn1, vn2,
  749.             v1, v2, vp2, v3, v4;
  750.     
  751.     D3DMATRIX p;
  752.  
  753.     // Calculer la normale au point 0 : v3
  754.     v1 = Normalize(v01);
  755.     v2 = Normalize(v02);
  756.     v3 = Normalize(CrossProduct(v01, v02));
  757.     
  758.     // On fait un repère orthonormal avec v3 et v1 (qui sont orthonormés) et leur produit vectoriel
  759.     vp2 = Normalize(CrossProduct(v3, v1));
  760.  
  761.     // On fait la matrice de changement de repère 
  762.     D3DUtil_SetIdentityMatrix(p);
  763.     p._11 = v1.x;
  764.     p._21 = v1.y;
  765.     p._31 = v1.z;
  766.     p._12 = vp2.x;
  767.     p._22 = vp2.y;
  768.     p._32 = vp2.z;
  769.     p._13 = v3.x;
  770.     p._23 = v3.y;
  771.     p._33 = v3.z;
  772.  
  773.     // on calcule l'image de z dans le nouveau repère : v4
  774.     D3DMath_VectorMatrixMultiply(v4, D3DVECTOR(0.f, 0.f, 1.f), p);
  775.  
  776.     // On vérifie que v4 est dans le même sens que z, ce qui nous dit si le triangle est CW ou CCW
  777.     float fSign = DotProduct(D3DVECTOR(0.f, 0.f, 1.f), v4);
  778.  
  779.     // On calcule les vecteurs normaux
  780.     if (Vertices[iS0].bSmooth) { bSmoothNorm(iS0); vn0 = Vertices[iS0].vNormal; }
  781.     else vn0 = Normalize(CrossProduct(v01, v02));
  782.  
  783.     if (Vertices[iS1].bSmooth) { bSmoothNorm(iS1); vn1 = Vertices[iS1].vNormal; }
  784.     else vn1 = Normalize(CrossProduct(v01, v12));
  785.  
  786.     if (Vertices[iS2].bSmooth) { bSmoothNorm(iS2); vn2 = Vertices[iS2].vNormal; }
  787.     else vn2 = Normalize(CrossProduct(v02, v12));
  788.  
  789.     // Créer les 2 triangles D3D (CW, CCW) en ordonnant les sommets pour avoir les CCW en 1er
  790.     if (fSign >= 0)
  791.     {
  792.         Triangles [iCnt].pSommets[0] = D3DVERTEX(Vertices[iS0].vPoint, vn0, 0, 0);
  793.         Triangles [iCnt].pSommets[1] = D3DVERTEX(Vertices[iS1].vPoint, vn1, 0, 0);
  794.         Triangles [iCnt].pSommets[2] = D3DVERTEX(Vertices[iS2].vPoint, vn2, 0, 0);
  795.         Triangles [iCnt].pSommets[3] = D3DVERTEX(Vertices[iS0].vPoint, -vn0, 0, 0);
  796.         Triangles [iCnt].pSommets[4] = D3DVERTEX(Vertices[iS2].vPoint, -vn2, 0, 0);
  797.         Triangles [iCnt].pSommets[5] = D3DVERTEX(Vertices[iS1].vPoint, -vn1, 0, 0);
  798.     }
  799.     else
  800.     {
  801.         Triangles [iCnt].pSommets[0] = D3DVERTEX(Vertices[iS0].vPoint, -vn0, 0, 0);
  802.         Triangles [iCnt].pSommets[1] = D3DVERTEX(Vertices[iS2].vPoint, -vn2, 0, 0);
  803.         Triangles [iCnt].pSommets[2] = D3DVERTEX(Vertices[iS1].vPoint, -vn1, 0, 0);
  804.         Triangles [iCnt].pSommets[3] = D3DVERTEX(Vertices[iS0].vPoint, vn0, 0, 0);
  805.         Triangles [iCnt].pSommets[4] = D3DVERTEX(Vertices[iS1].vPoint, vn1, 0, 0);
  806.         Triangles [iCnt].pSommets[5] = D3DVERTEX(Vertices[iS2].vPoint, vn2, 0, 0);
  807.     }
  808.  
  809.     return TRUE;
  810. }
  811. #endif
  812.  
  813. BOOL bSubdivideTriangle(int iTriangle)
  814. {
  815.     int iNewV[3], iNewT[4];
  816.     
  817.     if (Triangles[iTriangle].bEnabled == FALSE) return(FALSE);
  818.  
  819.     if (-1 == (iNewV[0] = iMakeVertex(
  820.                 (Vertices[Triangles[iTriangle].iSommets[0]].vPoint +
  821.                  Vertices[Triangles[iTriangle].iSommets[1]].vPoint
  822.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  823.  
  824.     if (-1 == (iNewV[1] = iMakeVertex(
  825.                 (Vertices[Triangles[iTriangle].iSommets[1]].vPoint +
  826.                  Vertices[Triangles[iTriangle].iSommets[2]].vPoint
  827.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  828.  
  829.     if (-1 == (iNewV[2] = iMakeVertex(
  830.                 (Vertices[Triangles[iTriangle].iSommets[2]].vPoint +
  831.                  Vertices[Triangles[iTriangle].iSommets[0]].vPoint
  832.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  833.  
  834.     if (-1 == (iNewT[0] = iMakeTriangle(iNewV[0], iNewV[1], iNewV[2], Triangles[iTriangle].iMtrl))) return FALSE;
  835.     if (-1 == (iNewT[1] = iMakeTriangle(iNewV[0], iNewV[1], Triangles[iTriangle].iSommets[1], Triangles[iTriangle].iMtrl))) return FALSE;
  836.     if (-1 == (iNewT[2] = iMakeTriangle(iNewV[1], iNewV[2], Triangles[iTriangle].iSommets[2], Triangles[iTriangle].iMtrl))) return FALSE;
  837.     if (-1 == (iNewT[3] = iMakeTriangle(iNewV[0], iNewV[2], Triangles[iTriangle].iSommets[0], Triangles[iTriangle].iMtrl))) return FALSE;
  838.  
  839.     Vertices[iNewV[0]].bSelected =
  840.     Vertices[iNewV[1]].bSelected =
  841.     Vertices[iNewV[2]].bSelected = Vertices[Triangles[iTriangle].iSommets[0]].bSelected;
  842.  
  843.     return bDeleteTriangle(iTriangle);
  844. }
  845.  
  846. BOOL    bIsTriangleSelected(int iTriangle)
  847. {
  848.     return
  849.         Triangles[iTriangle].bEnabled &&
  850.         bIsVertexSelected(Triangles[iTriangle].iSommets[0]) &&
  851.         bIsVertexSelected(Triangles[iTriangle].iSommets[1]) &&
  852.         bIsVertexSelected(Triangles[iTriangle].iSommets[2]);
  853. }
  854.  
  855. BOOL    bIsTrianglePartiallySelected(int iTriangle)
  856. {
  857.     return 
  858.         Triangles[iTriangle].bEnabled &&
  859.         (bIsVertexSelected(Triangles[iTriangle].iSommets[0]) ||
  860.          bIsVertexSelected(Triangles[iTriangle].iSommets[1]) ||
  861.          bIsVertexSelected(Triangles[iTriangle].iSommets[2]));
  862. }
  863.  
  864. //********************************************** O U T I L S *************************
  865. // Propager de façon **non** récursive la dé/sélection d'un vertex aux vertices connexes (à travers edges ou triangles)
  866. void vPropagateSelection(void)
  867. {
  868.     register BOOL bReste;
  869.  
  870.     bReste = TRUE;
  871.     while (bReste)
  872.     {
  873.         bReste = FALSE;
  874.  
  875.         for (register int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++)
  876.             if (bIsEdgePartiallySelected(iEdge) && !bIsEdgeSelected(iEdge))
  877.                 bReste =
  878.                 Vertices[Edges[iEdge].iSommets[0]].bSelected = 
  879.                 Vertices[Edges[iEdge].iSommets[1]].bSelected = TRUE;
  880.     }
  881.  
  882.     bReste = TRUE;
  883.     while (bReste)
  884.     {
  885.         bReste = FALSE;
  886.  
  887.         for (register int iTria = 0 ; iTria <= iTriaLastUsed ; iTria++)
  888.             if (bIsTrianglePartiallySelected(iTria) && !bIsTriangleSelected(iTria))
  889.                 bReste =
  890.                 Vertices[Triangles[iTria].iSommets[0]].bSelected = 
  891.                 Vertices[Triangles[iTria].iSommets[1]].bSelected = 
  892.                 Vertices[Triangles[iTria].iSommets[2]].bSelected = TRUE;
  893.     }
  894. }
  895.  
  896. // Cloner la sélection
  897. BOOL bCloneSelection(D3DVECTOR vShift, BOOL bCloneMode)
  898. {
  899.     int iCnt, jCnt, iNumSelected, *iIndex;
  900.  
  901.     // Compter les points sélectionnés
  902.     iNumSelected = 0;
  903.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  904.         if (bIsVertexSelected(iCnt)) iNumSelected++;
  905.  
  906.     if (!iNumSelected) return FALSE;
  907.  
  908.     // Allouer la table de correspondance ancien / nouvel index
  909.     iIndex = (int *) malloc(iNumSelected * 2 * sizeof(int));
  910.  
  911.     // Cloner les points sélectionnés en conservant la table de correspondance ancien / nouveau
  912.     // et en décalant les nouveaux de vShift
  913.     jCnt = 0;
  914.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  915.     {
  916.         D3DVECTOR vVect = Vertices[iCnt].vPoint + vShift;
  917.  
  918.         if (!bIsVertexSelected(iCnt)) continue;
  919.  
  920.         // Remplir la table de correspondance ancien / nouveau
  921.         iIndex[jCnt] = iCnt;
  922.         iIndex[jCnt + 1] = iMakeVertex(vVect, XDC_FORCENEW);
  923.         jCnt += 2;
  924.     }
  925.  
  926.     // Cloner les arêtes éventuelles entre les anciens points
  927.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  928.     {
  929.         if (Edges[iCnt].bEnabled == FALSE) continue;
  930.  
  931.         int iOVert1 = Edges[iCnt].iSommets[0],
  932.             iOVert2 = Edges[iCnt].iSommets[1],
  933.             iCVert1 = -1,
  934.             iCVert2 = -1;
  935.  
  936.         // Vérifier que les deux sommets originaux de l'arête sont sélectionnés
  937.         if (bIsVertexSelected(iOVert1) && bIsVertexSelected(iOVert2))
  938.         {
  939.             // Alors il faut créer une nouvelle arête avec les sommets clonés
  940.             for (jCnt = 0 ; jCnt < iNumSelected ; jCnt++)
  941.             {
  942.                 if (iIndex[jCnt * 2] == iOVert1) iCVert1 = iIndex[jCnt * 2 + 1];
  943.                 if (iIndex[jCnt * 2] == iOVert2) iCVert2 = iIndex[jCnt * 2 + 1];
  944.             }
  945.             if ((iCVert1 != -1) && (iCVert2 != -1))
  946.             {
  947.                 iMakeEdge(iCVert1, iCVert2);
  948.  
  949.                 // Si le mode de clonage est avec extrusion, créer les triangles de l'élévation
  950.                 if (bCloneMode == XDC_MODE_EXTRUDE)
  951.                 {
  952.                     iMakeTriangle(iOVert1, iCVert1, iCVert2, 0);
  953.                     iMakeTriangle(iOVert1, iOVert2, iCVert2, 0);
  954.                 }
  955.             }
  956.         }
  957.     }
  958.  
  959.     // Cloner les triangles éventuels entre les différents points
  960.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  961.     {
  962.         if (Triangles[iCnt].bEnabled == FALSE) continue;
  963.  
  964.         int iOVert1 = Triangles[iCnt].iSommets[0],
  965.             iOVert2 = Triangles[iCnt].iSommets[1],
  966.             iOVert3 = Triangles[iCnt].iSommets[2],
  967.             iCVert1 = -1,
  968.             iCVert2 = -1,
  969.             iCVert3 = -1;
  970.  
  971.         // Vérifier que les trois sommets originaux du triangle sont sélectionnés
  972.         if (bIsVertexSelected(iOVert1) && bIsVertexSelected(iOVert2) && bIsVertexSelected(iOVert3))
  973.         {
  974.             // Alors il faut créer un nouveau triangle avec les sommets clonés
  975.             for (jCnt = 0 ; jCnt < iNumSelected ; jCnt++)
  976.             {
  977.                 if (iIndex[jCnt * 2] == iOVert1) iCVert1 = iIndex[jCnt * 2 + 1];
  978.                 if (iIndex[jCnt * 2] == iOVert2) iCVert2 = iIndex[jCnt * 2 + 1];
  979.                 if (iIndex[jCnt * 2] == iOVert3) iCVert3 = iIndex[jCnt * 2 + 1];
  980.             }
  981.             if ((iCVert1 != -1) && (iCVert2 != -1) && (iCVert3 != -1))
  982.             {
  983.                 iMakeTriangle(iCVert1, iCVert2, iCVert3, Triangles[iCnt].iMtrl);
  984.  
  985.                 // Si le mode de clonage est avec extrusion, créer les triangles de l'élévation
  986.                 if (bCloneMode == XDC_MODE_EXTRUDE)
  987.                 {
  988.                     iMakeTriangle(iOVert1, iCVert1, iCVert2, Triangles[iCnt].iMtrl);
  989.                     iMakeTriangle(iOVert1, iOVert2, iCVert2, Triangles[iCnt].iMtrl);
  990.                     iMakeTriangle(iOVert2, iCVert2, iCVert3, Triangles[iCnt].iMtrl);
  991.                     iMakeTriangle(iOVert2, iOVert3, iCVert3, Triangles[iCnt].iMtrl);
  992.                     iMakeTriangle(iOVert1, iCVert1, iCVert3, Triangles[iCnt].iMtrl);
  993.                     iMakeTriangle(iOVert1, iOVert3, iCVert3, Triangles[iCnt].iMtrl);
  994.                 }
  995.             }
  996.         }
  997.     }
  998.  
  999.     // Inverser la sélection (sélectionner les nouveaux points)
  1000.     for (iCnt = 0 ; iCnt < iNumSelected ; iCnt++)
  1001.     {
  1002.         Vertices[iIndex[iCnt * 2    ]].bSelected = FALSE;
  1003.         Vertices[iIndex[iCnt * 2 + 1]].bSelected = TRUE;
  1004.     }
  1005.  
  1006.     // Libérer la table de correspondance
  1007.     free(iIndex);
  1008.  
  1009.     return TRUE;
  1010. }
  1011.  
  1012. // Cacher les éléments de la sélection
  1013. void vHideSelection(void)
  1014. {
  1015.     int iVert, iCnt;
  1016.  
  1017.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1018.     {
  1019.         if (bIsVertexSelected(iVert))
  1020.         {
  1021.             Vertices[iVert].bHidden = TRUE;
  1022.             Vertices[iVert].bSelected = FALSE;
  1023.  
  1024.             for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  1025.             {
  1026.                 if (Edges[iCnt].bEnabled == FALSE) continue;
  1027.  
  1028.                 if (bVertInEdge(iVert, iCnt))
  1029.                     Edges[iCnt].bHidden = TRUE;
  1030.             }
  1031.             for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  1032.             {
  1033.                 if (Triangles[iCnt].bEnabled == FALSE) continue;
  1034.  
  1035.                 if (bVertInTriangle(iVert, iCnt))
  1036.                     Triangles[iCnt].bHidden = TRUE;
  1037.             }
  1038.         }
  1039.     }
  1040. }
  1041.  
  1042. // Rendre visibles les éléments cachés
  1043. void vRevealHidden(void)
  1044. {
  1045.     int iCnt;
  1046.  
  1047.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  1048.     {
  1049.         if (Vertices[iCnt].bEnabled == FALSE) continue;
  1050.  
  1051.         Vertices[iCnt].bHidden = FALSE;
  1052.     }
  1053.  
  1054.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  1055.     {
  1056.         if (Edges[iCnt].bEnabled == FALSE) continue;
  1057.  
  1058.         Edges[iCnt].bHidden = FALSE;
  1059.     }
  1060.  
  1061.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  1062.     {
  1063.         if (Triangles[iCnt].bEnabled == FALSE) continue;
  1064.  
  1065.         Triangles[iCnt].bHidden = FALSE;
  1066.     }
  1067. }
  1068.  
  1069. // Déterminer le barycentre de la sélection
  1070. D3DVECTOR vCenter(void)
  1071. {
  1072.     D3DVECTOR dVect = D3DVECTOR(0.f, 0.f, 0.f);
  1073.     int jCnt = 0;
  1074.  
  1075.     for (int iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1076.         if (bIsVertexSelected(iVert))
  1077.         {
  1078.             // Mémoriser les coordonnées avant modification
  1079.             Vertices[iVert].vPointBack = Vertices[iVert].vPoint;
  1080.             
  1081.             // Compter les points
  1082.             jCnt++;
  1083.  
  1084.             // Additionner les coordonnées du point à celles du barycentre
  1085.             dVect.x += Vertices[iVert].vPoint.x;
  1086.             dVect.y += Vertices[iVert].vPoint.y;
  1087.             dVect.z += Vertices[iVert].vPoint.z;
  1088.         }
  1089.  
  1090.     if (!jCnt) 
  1091.     {
  1092.         vTrace("*** E0022 : Pas de sélection");
  1093.         return dVect;
  1094.     }
  1095.  
  1096.     // Moyenner la somme des points
  1097.     dVect.x /= jCnt;
  1098.     dVect.y /= jCnt;
  1099.     dVect.z /= jCnt;
  1100.  
  1101.     return dVect;
  1102. }
  1103.  
  1104. // Garbage collektor !-)
  1105. void vCollect(void)
  1106. {
  1107.     int iShift, iVert, iMtrl, *iMapTo;
  1108.  
  1109.     // Réindexer les arêtes
  1110.     iShift = 0;
  1111.  
  1112.     for (int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++)
  1113.     {
  1114.         if (Edges[iEdge].bEnabled == FALSE)
  1115.         {
  1116.             while (Edges[iEdge + iShift].bEnabled == FALSE)
  1117.             {
  1118.                 iShift++;
  1119.                 iEdgeLastUsed--;
  1120.             }
  1121.         }
  1122.         if (iShift)
  1123.         {
  1124.             Edges[iEdge] = Edges[iEdge + iShift];
  1125.             Edges[iEdge + iShift].bEnabled = FALSE;
  1126.         }
  1127.     }
  1128.  
  1129.     iEdgeFirstAvailable = iEdgeLastUsed + 1;
  1130.  
  1131.     // Réindexer les triangles
  1132.     iShift = 0;
  1133.  
  1134.     for (int iTria = 0 ; iTria <= iTriaLastUsed ; iTria++)
  1135.     {
  1136.         if (Triangles[iTria].bEnabled == FALSE)
  1137.         {
  1138.             while (Triangles[iTria + iShift].bEnabled == FALSE)
  1139.             {
  1140.                 iShift++;
  1141.                 iTriaLastUsed--;
  1142.             }
  1143.         }
  1144.         if (iShift)
  1145.         {
  1146.             Triangles[iTria] = Triangles[iTria + iShift];
  1147.             Triangles[iTria + iShift].bEnabled = FALSE;
  1148.         }
  1149.     }
  1150.  
  1151.     iTriaFirstAvailable = iTriaLastUsed + 1;
  1152.  
  1153.     // Compter les sommets inutilisés pour ne faire la suite que s'il y en a
  1154.     iShift = 0;
  1155.  
  1156.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1157.         if (Vertices[iVert].bEnabled == FALSE)
  1158.             iShift++;
  1159.  
  1160.     if (!iShift)
  1161.         goto _DoneVert;
  1162.  
  1163.     // Allouer la table de mapping
  1164.     if (!(iMapTo = (int *) malloc((iVertLastUsed + 1) * sizeof(int))))
  1165.     {
  1166.         vTrace("*** E0032 : erreur malloc table mapping GC");
  1167.         return;
  1168.     }
  1169.  
  1170.     // Préinitialiser la table de mapping
  1171.     for (iShift = 0 ; iShift <= iVertLastUsed ; iShift++)
  1172.         iMapTo[iShift] = iShift;
  1173.  
  1174.     // Réindexer les sommets
  1175.     iShift = 0;
  1176.  
  1177.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1178.     {
  1179.         if (Vertices[iVert].bEnabled == FALSE)
  1180.         {
  1181.             while (Vertices[iVert + iShift].bEnabled == FALSE)
  1182.             {
  1183.                 iShift++;
  1184.                 iVertLastUsed--;
  1185.             }
  1186.         }
  1187.  
  1188.         if (iShift)
  1189.         {
  1190.             Vertices[iVert] = Vertices[iVert + iShift];
  1191.             Vertices[iVert + iShift].bEnabled = Vertices[iVert + iShift].bSelected = FALSE;
  1192.             iMapTo[iVert + iShift] = iVert;
  1193.         }
  1194.     }
  1195.  
  1196.     iVertFirstAvailable = iVertLastUsed + 1;
  1197.  
  1198.     // Réindexer les sommets dans les arêtes
  1199.     for(iShift = 0 ; iShift <= iEdgeLastUsed ; iShift++)
  1200.     {
  1201.         Edges[iShift].iSommets[0] = iMapTo[Edges[iShift].iSommets[0]];
  1202.         Edges[iShift].iSommets[1] = iMapTo[Edges[iShift].iSommets[1]];
  1203.     }
  1204.  
  1205.     // Réindexer les sommets dans les triangles
  1206.     for(iShift = 0 ; iShift <= iTriaLastUsed ; iShift++)
  1207.     {
  1208.         Triangles[iShift].iSommets[0] = iMapTo[Triangles[iShift].iSommets[0]];
  1209.         Triangles[iShift].iSommets[1] = iMapTo[Triangles[iShift].iSommets[1]];
  1210.         Triangles[iShift].iSommets[2] = iMapTo[Triangles[iShift].iSommets[2]];
  1211.     }
  1212.  
  1213.     // Libérer la table
  1214.     free(iMapTo);
  1215.  
  1216. _DoneVert:
  1217.  
  1218.     // Compter les matériaux inutilisés pour ne faire la suite que s'il y en a
  1219.     iShift = 0;
  1220.  
  1221.     for (iMtrl = 0 ; iMtrl <= iMtrlLastUsed ; iMtrl++)
  1222.         if (Materials[iMtrl].bEnabled == FALSE)
  1223.             iShift++;
  1224.  
  1225.     if (!iShift)
  1226.         return;
  1227.  
  1228.     // Allouer la table de mapping
  1229.     if (!(iMapTo = (int *) malloc((iMtrlLastUsed + 1) * sizeof(int))))
  1230.     {
  1231.         vTrace("*** E0032 : erreur malloc table mapping GC");
  1232.         return;
  1233.     }
  1234.  
  1235.     // Préinitialiser la table de mapping
  1236.     for (iShift = 0 ; iShift <= iMtrlLastUsed ; iShift++)
  1237.         iMapTo[iShift] = iShift;
  1238.  
  1239.     // Réindexer les matériaux
  1240.     iShift = 0;
  1241.  
  1242.     for (iMtrl = 0 ; iMtrl <= iMtrlLastUsed ; iMtrl++)
  1243.     {
  1244.         if (Materials[iMtrl].bEnabled == FALSE)
  1245.         {
  1246.             while (Materials[iMtrl + iShift].bEnabled == FALSE)
  1247.             {
  1248.                 iShift++;
  1249.                 iMtrlLastUsed--;
  1250.             }
  1251.         }
  1252.  
  1253.         if (iShift)
  1254.         {
  1255.             Materials[iMtrl] = Materials[iMtrl + iShift];
  1256.             Materials[iMtrl + iShift].bEnabled = FALSE;
  1257.             iMapTo[iMtrl + iShift] = iMtrl;
  1258.         }
  1259.     }
  1260.  
  1261.     iMtrlFirstAvailable = iMtrlLastUsed + 1;
  1262.  
  1263.     // Réindexer les matériaux dans les triangles
  1264.     for(iShift = 0 ; iShift <= iTriaLastUsed ; iShift++)
  1265.         Triangles[iShift].iMtrl = iMapTo[Triangles[iShift].iMtrl];
  1266.  
  1267.     // Libérer la table
  1268.     free(iMapTo);
  1269. }
  1270.