home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Internet 2000 May / MICD_2000_05.iso / CBuilder5 / INSTALL / DATA1.CAB / Program_Built_Files / Include / dxhelp3.cpp < prev    next >
C/C++ Source or Header  |  2000-02-01  |  11KB  |  340 lines

  1. // DXHELP3.cpp : Contains routines shared by multiple 3D effects
  2. #include "stdafx.h"
  3. #include "dxhelp3.h"
  4. #include <malloc.h>
  5. #include <math.h>
  6. #include <stdio.h>
  7.  
  8. void Rotate::Set(D3DVECTOR d3dvctrNormal, double dAngle)
  9. {
  10. #ifdef _DEBUG
  11.     float NormalSum =   d3dvctrNormal.x * d3dvctrNormal.x + 
  12.                         d3dvctrNormal.y * d3dvctrNormal.y + 
  13.                         d3dvctrNormal.z * d3dvctrNormal.z;
  14.     _ASSERT(NormalSum == 0.0f || (0.99f < NormalSum && NormalSum < 1.01f));
  15. #endif
  16.  
  17.     // The following transformation matrix routines are from
  18.     // Graphics Gems (the first one) page 466 (Converting 
  19.     // between Matrix and Axis-Amount Representations)
  20.     float s = (float)sin(dAngle), c = (float)cos(dAngle);
  21.     float t = 1.0f - c;
  22.  
  23.     m_d3dvctrXComponent.x = t * d3dvctrNormal.x * d3dvctrNormal.x + c;
  24.     m_d3dvctrXComponent.y = t * d3dvctrNormal.x * d3dvctrNormal.y - s * d3dvctrNormal.z;
  25.     m_d3dvctrXComponent.z = t * d3dvctrNormal.x * d3dvctrNormal.z + s * d3dvctrNormal.y;
  26.  
  27.     m_d3dvctrYComponent.x = t * d3dvctrNormal.x * d3dvctrNormal.y + s * d3dvctrNormal.z;
  28.     m_d3dvctrYComponent.y = t * d3dvctrNormal.y * d3dvctrNormal.y + c;
  29.     m_d3dvctrYComponent.z = t * d3dvctrNormal.y * d3dvctrNormal.z - s * d3dvctrNormal.x;
  30.  
  31.     m_d3dvctrZComponent.x = t * d3dvctrNormal.x * d3dvctrNormal.z - s * d3dvctrNormal.y;
  32.     m_d3dvctrZComponent.y = t * d3dvctrNormal.y * d3dvctrNormal.z + s * d3dvctrNormal.x;
  33.     m_d3dvctrZComponent.z = t * d3dvctrNormal.z * d3dvctrNormal.z + c;
  34. }
  35.  
  36. static HRESULT DecoupleOneMeshBuilder(void *lpThis /* Ignored */, 
  37.                       IDirect3DRMMeshBuilder3 *lpMeshBuilderOut,
  38.                       IDirect3DRMMeshBuilder3 *lpMeshBuilderIn)
  39. {
  40.     HRESULT hr = lpMeshBuilderOut->SetAppData(lpMeshBuilderIn->GetAppData());
  41.  
  42.     if(FAILED(hr))
  43.     {
  44.     return hr;
  45.     }
  46.  
  47.     const int ciOutputFaceCount = lpMeshBuilderOut->GetFaceCount();
  48.     const int ciMaxFaceCount = lpMeshBuilderIn->GetFaceCount();
  49.     if(!ciMaxFaceCount)
  50.     {
  51.     return hr;
  52.     }
  53.     CComPtr<IDirect3DRMFaceArray> cpD3DRMFaceArray;
  54.  
  55.     hr = lpMeshBuilderIn->GetFaces(&cpD3DRMFaceArray);
  56.     if(hr != D3DRM_OK)
  57.     {
  58.     return hr;
  59.     }
  60.  
  61.     D3DVECTOR *lpvctrPosition = NULL;
  62.     D3DVECTOR *lpvctrFaceNormals = NULL;
  63.     DWORD dwMaxVertexCount = 0;
  64.  
  65.     // By reserving space we speed things up by a factor of 20 or 30 X!
  66.  
  67.     DWORD dwTotalVertexCount = lpMeshBuilderIn->GetVertexCount();
  68.     _ASSERT(dwTotalVertexCount >= 3);
  69.     if (dwTotalVertexCount/ciMaxFaceCount < 3)
  70.     {
  71.     dwTotalVertexCount = ciMaxFaceCount * 3;  // There will be at least 3 vertices per face.
  72.     }
  73.     hr = lpMeshBuilderOut->ReserveSpace(dwTotalVertexCount, dwTotalVertexCount, ciMaxFaceCount);
  74.  
  75.     if(hr != D3DRM_OK)
  76.     {
  77.     return hr;
  78.     }
  79.  
  80.     // Need to have seperate vertices for each face in the output mesh.
  81.     int iFaceIndex = 0;
  82.     do
  83.     {
  84.     CComPtr<IDirect3DRMFace> cpd3dInFaceTemp;
  85.     CComPtr<IDirect3DRMFace2> cpd3dOutFace;
  86.  
  87.         if(FAILED(hr = cpD3DRMFaceArray->GetElement((DWORD)iFaceIndex, &cpd3dInFaceTemp)))
  88.         {
  89.             break;
  90.         }
  91.         _ASSERT(cpd3dInFaceTemp);
  92.  
  93.     CComPtr<IDirect3DRMFace2> cpd3dInFace;
  94.     if(FAILED(hr = cpd3dInFaceTemp->QueryInterface(
  95.         IID_IDirect3DRMFace2, (void **)&cpd3dInFace)))
  96.     {
  97.         break;
  98.     }
  99.  
  100.         DWORD dwVertexCount;
  101.  
  102.         cpd3dInFace->GetVertices(&dwVertexCount, NULL, NULL);
  103.         _ASSERT(dwVertexCount >= 3);
  104.  
  105.         if(dwVertexCount > dwMaxVertexCount)
  106.         {
  107.             dwMaxVertexCount = dwVertexCount;
  108.  
  109.         D3DVECTOR *lpTemp = lpvctrPosition;
  110.             D3DVECTOR *lpNormalTemp = lpvctrFaceNormals;
  111.  
  112.         lpvctrPosition = (D3DVECTOR *)realloc(lpvctrPosition, dwMaxVertexCount * sizeof (*lpvctrPosition));
  113.         lpvctrFaceNormals = (D3DVECTOR *)realloc(lpvctrFaceNormals, dwMaxVertexCount * sizeof (*lpvctrFaceNormals));
  114.  
  115.         if(!lpvctrPosition || !lpvctrFaceNormals)
  116.         {
  117.         free(lpTemp);
  118.         free(lpNormalTemp);
  119.         hr = E_OUTOFMEMORY;
  120.         break;
  121.         }
  122.  
  123.         // We may have a problem in the amount of space reserved in the output meshbuilder.
  124.         if((ciMaxFaceCount -  iFaceIndex) * dwMaxVertexCount > dwTotalVertexCount)
  125.         {
  126.         dwTotalVertexCount = (ciMaxFaceCount -  iFaceIndex) * dwMaxVertexCount;
  127.         hr = lpMeshBuilderOut->ReserveSpace(dwTotalVertexCount, dwTotalVertexCount, ciMaxFaceCount - iFaceIndex);
  128.  
  129.         if(hr != D3DRM_OK)
  130.         {
  131.             break;
  132.         }
  133.         }
  134.         }
  135.  
  136.         if(FAILED(hr = cpd3dInFace->GetVertices(&dwVertexCount, lpvctrPosition, lpvctrFaceNormals)) ||
  137.        FAILED(hr = lpMeshBuilderOut->CreateFace(&cpd3dOutFace)) ||
  138.        FAILED(hr = cpd3dOutFace->SetAppData(cpd3dInFace->GetAppData())))
  139.         {
  140.             break;
  141.         }
  142.  
  143.  
  144.     CComPtr<IDirect3DRMMaterial2> cpMaterial;
  145.         CComPtr<IDirect3DRMTexture3> cpTexture;
  146.         BOOL bU, bV;
  147.  
  148.         if(hr != D3DRM_OK ||
  149.           (hr = cpd3dInFace->GetMaterial(&cpMaterial)) != D3DRM_OK ||
  150.           (hr = cpd3dOutFace->SetMaterial(cpMaterial)) != D3DRM_OK ||
  151.           (hr = cpd3dOutFace->SetColor(cpd3dInFace->GetColor())) != D3DRM_OK ||
  152.           (hr = cpd3dInFace->GetTexture(&cpTexture)) != D3DRM_OK ||
  153.           (hr = cpd3dOutFace->SetTexture(cpTexture)) != D3DRM_OK ||
  154.           (hr = cpd3dInFace->GetTextureTopology(&bU, &bV)) != D3DRM_OK ||
  155.           (hr = cpd3dOutFace->SetTextureTopology(bU, bV)) != D3DRM_OK)
  156.         {
  157.             break;
  158.         }
  159.  
  160.         DWORD dwInFaceVertex = 0;
  161.         do
  162.         {
  163.             int iVIndex = lpMeshBuilderOut->AddVertex(lpvctrPosition[dwInFaceVertex].x, 
  164.                      lpvctrPosition[dwInFaceVertex].y, 
  165.                      lpvctrPosition[dwInFaceVertex].z);
  166.             int iNIndex = lpMeshBuilderOut->AddNormal(lpvctrFaceNormals[dwInFaceVertex].x, 
  167.                      lpvctrFaceNormals[dwInFaceVertex].y, 
  168.                      lpvctrFaceNormals[dwInFaceVertex].z);
  169.  
  170.             D3DVALUE U, V;
  171.  
  172.             if(FAILED(hr = cpd3dOutFace->AddVertexAndNormalIndexed(iVIndex, iNIndex)) ||
  173.                FAILED(hr = cpd3dInFace->GetTextureCoordinates(dwInFaceVertex, &U, &V)) ||
  174.                FAILED(hr = cpd3dOutFace->SetTextureCoordinates(dwInFaceVertex, U, V)))
  175.             {
  176.                 break;
  177.             }
  178.         } while (++dwInFaceVertex < dwVertexCount);
  179.     dwTotalVertexCount -= dwVertexCount;
  180.     } while (hr == D3DRM_OK && ++iFaceIndex < ciMaxFaceCount);
  181.  
  182.     free(lpvctrPosition);
  183.     free(lpvctrFaceNormals);
  184.  
  185.     return hr;
  186. }
  187.  
  188. HRESULT TraverseSubMeshes(  HRESULT (*lpCallBack)(void *lpThis,
  189.                         IDirect3DRMMeshBuilder3* lpOut,
  190.                         IDirect3DRMMeshBuilder3* lpIn),
  191.                 void *lpThis, 
  192.                 IDirect3DRMMeshBuilder3* lpMeshBuilderOut,
  193.                 IDirect3DRMMeshBuilder3* lpMeshBuilderIn)
  194. {
  195.     HRESULT hr;
  196.  
  197.     _ASSERT(lpCallBack);
  198.     if(FAILED(hr = (*lpCallBack)(lpThis, lpMeshBuilderOut, lpMeshBuilderIn)))
  199.     return hr;
  200.  
  201.     DWORD dwInSubMeshCount;
  202.     hr = lpMeshBuilderIn->GetSubMeshes(&dwInSubMeshCount, NULL);
  203.  
  204.     if(FAILED(hr) || dwInSubMeshCount == 0)
  205.     return hr;
  206.  
  207.     DWORD dwOutSubMeshCount;
  208.     if(FAILED(hr = lpMeshBuilderOut->GetSubMeshes(&dwOutSubMeshCount, NULL)))
  209.     {
  210.     return hr;
  211.     }
  212.  
  213.     const BOOL bCreateOutMeshes = (dwOutSubMeshCount == 0);
  214.     _ASSERT(bCreateOutMeshes || dwInSubMeshCount == dwOutSubMeshCount);
  215.  
  216.     LPUNKNOWN *lplpunkInSubMeshes =
  217.     (LPUNKNOWN *)malloc(dwInSubMeshCount * sizeof(*lplpunkInSubMeshes));
  218.  
  219.     LPUNKNOWN *lplpunkOutSubMeshes = (bCreateOutMeshes? NULL:
  220.     (LPUNKNOWN *)malloc(dwOutSubMeshCount * sizeof(*lplpunkOutSubMeshes)));
  221.  
  222.     if(!lplpunkInSubMeshes || !bCreateOutMeshes && !lplpunkOutSubMeshes)
  223.     {
  224.     return E_OUTOFMEMORY;
  225.     }
  226.  
  227.     if(FAILED(hr = lpMeshBuilderIn->GetSubMeshes(&dwInSubMeshCount, lplpunkInSubMeshes)) ||
  228.     !bCreateOutMeshes && 
  229.     FAILED(hr = lpMeshBuilderOut->GetSubMeshes(&dwOutSubMeshCount, lplpunkOutSubMeshes)))
  230.     {
  231.     return hr;
  232.     }
  233.  
  234.     CComPtr<IDirect3DRMMeshBuilder3> cpInSubMesh, cpOutSubMesh;
  235.  
  236.     DWORD dwSubMesh;
  237.     for(dwSubMesh = 0; SUCCEEDED(hr) && dwSubMesh < dwInSubMeshCount; dwSubMesh++)
  238.     {
  239.     cpInSubMesh = NULL;
  240.     cpOutSubMesh = NULL;
  241.  
  242.     // Get the current input submesh.
  243.     hr = lplpunkInSubMeshes[dwSubMesh]->QueryInterface(IID_IDirect3DRMMeshBuilder3, 
  244.         (void **)&cpInSubMesh);
  245.  
  246.     if(FAILED(hr))
  247.         break;
  248.  
  249.     if(bCreateOutMeshes)
  250.     {
  251.         // Create a new submesh in the output mesh to match the input submesh.        
  252.         LPUNKNOWN lpunkSubmesh;
  253.  
  254.         if(FAILED(hr = lpMeshBuilderOut->CreateSubMesh(&lpunkSubmesh)))
  255.         break;
  256.  
  257.         hr = lpunkSubmesh->QueryInterface(IID_IDirect3DRMMeshBuilder3,
  258.                             (void **)&cpOutSubMesh);
  259.         lpunkSubmesh->Release();
  260.     }
  261.     else
  262.     {
  263.         // Get the current output submesh.
  264.         hr = lplpunkOutSubMeshes[dwSubMesh]->QueryInterface(IID_IDirect3DRMMeshBuilder3,
  265.             (void **)&cpOutSubMesh);
  266.     }
  267.     if(FAILED(hr))
  268.         break;
  269.  
  270.     // Do all the children for these two MeshBuilders.
  271.     hr = TraverseSubMeshes(lpCallBack, lpThis, cpOutSubMesh, cpInSubMesh);
  272.     }
  273.  
  274.     for(dwSubMesh = 0; dwSubMesh < dwInSubMeshCount; dwSubMesh++)
  275.     {
  276.     lplpunkInSubMeshes[dwSubMesh]->Release();
  277.  
  278.     if(lplpunkOutSubMeshes)
  279.     {
  280.         lplpunkOutSubMeshes[dwSubMesh]->Release();
  281.     }
  282.     }
  283.  
  284.     free(lplpunkInSubMeshes);
  285.     free(lplpunkOutSubMeshes);
  286.  
  287.     return hr;
  288. }
  289.  
  290. HRESULT DecoupleVertices(IDirect3DRMMeshBuilder3* lpMeshBuilderOut,
  291.              IDirect3DRMMeshBuilder3* lpMeshBuilderIn)
  292. {
  293.     DWORD dwSubMeshCount;
  294.  
  295.     HRESULT hr = lpMeshBuilderOut->GetSubMeshes(&dwSubMeshCount, NULL);
  296.  
  297.     if(FAILED(hr))
  298.     return hr;
  299.  
  300.     if(lpMeshBuilderOut->GetFaceCount() || dwSubMeshCount)
  301.     {
  302.     if(FAILED(hr = lpMeshBuilderOut->Empty(0)))
  303.         return hr;
  304.     }
  305.     hr = TraverseSubMeshes(DecoupleOneMeshBuilder, NULL,
  306.                 lpMeshBuilderOut, lpMeshBuilderIn);
  307.     return hr;
  308. }
  309.  
  310. float GetDlgItemFloat(HWND hDlg, int id)
  311. {
  312.     TCHAR *pEnd;
  313.     TCHAR szItemText[20];
  314.     GetDlgItemText(hDlg, id, szItemText, 20);
  315.     return (float)strtod(szItemText, &pEnd);
  316. }
  317.  
  318. BOOL SetDlgItemFloat( HWND hDlg, int id, float f )
  319. {
  320.     TCHAR szItem[20];
  321.      _stprintf( szItem, _T("%.2f"), f );
  322.     return SetDlgItemText( hDlg, id, szItem );
  323. }
  324.  
  325. double GetDlgItemDouble(HWND hDlg, int id)
  326. {
  327.     TCHAR *pEnd;
  328.     TCHAR szItemText[20];
  329.     GetDlgItemText(hDlg, id, szItemText, 20);
  330.     return strtod(szItemText, &pEnd);
  331. }
  332.  
  333. BOOL SetDlgItemDouble( HWND hDlg, int id, double d )
  334. {
  335.     TCHAR szItem[20];
  336.      _stprintf( szItem, _T("%.2d"), d );
  337.     return SetDlgItemText( hDlg, id, szItem );
  338. }
  339.  
  340.