home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Utilities / MView / gxu / loadmesh.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-30  |  26.7 KB  |  1,052 lines

  1. /*//////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File: loadmesh.cpp
  4. //
  5. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  6. //
  7. //
  8. //////////////////////////////////////////////////////////////////////////////*/
  9.  
  10. #include "pchgxu.h"
  11.  
  12. #include "loadutil.h"
  13.  
  14. namespace GXU
  15. {
  16. #if 0
  17. /*
  18.  * Template routine to handle dynamic allocation, based on Heap* Win32 APIs.
  19.  *
  20.  *  T **ppBase: base of array.
  21.  *  const T& obj: object to add to end of array.
  22.  *  UINT *pcNum: number of objects in array.
  23.  *  UINT *pcMax: max. number of objects in array.
  24.  *
  25.  * ppBase, pcNum and pcMax point to values that usually get modified
  26.  * by the call. The only case when they are not updated is if there
  27.  * is insufficient memory for the initial allocation (if *pBase is NULL)
  28.  * or a second allocation if *pcNum==*pcMax.
  29.  *
  30.  * Return value: TRUE if allocation was successful
  31.  *               FALSE if there was insufficient memory
  32.  *      FALSE means nothing was added to the array, but nothing
  33.  *        was lost either. No weird realloc semantics allowed!
  34.  */
  35. template<class T>
  36. BOOL
  37. AddToDynamicArray( T **ppBase, const T& obj, UINT *pcNum, UINT *pcMax )
  38. {
  39.     T *pBase = *ppBase;
  40.     if ( ! pBase )
  41.     {
  42.         HeapValidate( GetProcessHeap(), 0, NULL );
  43.         pBase = new T[2];
  44.         *pcNum = 0;
  45.         *pcMax = 2;
  46.     }
  47.     if ( *pcNum == *pcMax )
  48.     {
  49.         UINT cNewMax = *pcMax*2;
  50.         T *newarr = new T[cNewMax];
  51.         if ( ! newarr )
  52.             return FALSE;
  53.         for (UINT i = 0; i < *pcNum; i++)
  54.             newarr[i] = pBase[i];
  55.         *pcMax = cNewMax;
  56.         delete []pBase;
  57.         pBase = newarr;
  58.     }
  59.     pBase[ (*pcNum)++ ] = obj;
  60.     *ppBase = pBase;
  61.     return TRUE;
  62. }
  63.  
  64.  
  65. class GXColorAttributeBundle : public IGXAttributeBundle
  66. {
  67. public:
  68.  
  69.     virtual HRESULT STDMETHODCALLTYPE QueryInterface(
  70.         /* [in] */ REFIID riid,
  71.         /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
  72.     {
  73.         return E_FAIL;
  74.     };
  75.  
  76.     virtual ULONG STDMETHODCALLTYPE AddRef( void) { return 1; }
  77.  
  78.     virtual ULONG STDMETHODCALLTYPE Release( void) { return 1; };
  79.  
  80.     // punch attribute set to device
  81.     virtual HRESULT SetAttributesToDevice( LPDIRECT3DDEVICE9 pD3DDevice )
  82.     {
  83.         return pD3DDevice->SetMaterial(&m_mtrlColor);
  84.     }
  85.  
  86.     // user defined data
  87.     virtual HRESULT SetUserData( PVOID pvUserData ) { return E_NOTIMPL; };
  88.     virtual HRESULT GetUserData( PVOID *ppvUserData ) { return E_NOTIMPL; };
  89.  
  90.     // user defined sort index for preferred order to draw attribute bundle sets in
  91.     virtual HRESULT SetSortIndex( DWORD dwSortIndex ) { return S_OK; };
  92.     virtual HRESULT GetSortIndex( PDWORD pdwSortIndex ) { *pdwSortIndex = 0; return S_OK;};
  93.  
  94.     GXColorAttributeBundle(D3DXCOLOR &color)
  95.     {
  96.         ZeroMemory( &m_mtrlColor, sizeof(D3DMATERIAL9) );
  97.         m_mtrlColor.dcvDiffuse.r = m_mtrlColor.dcvAmbient.r = color.r;
  98.         m_mtrlColor.dcvDiffuse.g = m_mtrlColor.dcvAmbient.g = color.g;
  99.         m_mtrlColor.dcvDiffuse.b = m_mtrlColor.dcvAmbient.b = color.b;
  100.         m_mtrlColor.dcvDiffuse.a = m_mtrlColor.dcvAmbient.a = 1.0f;
  101.         m_mtrlColor.dcvEmissive.r = 0;
  102.         m_mtrlColor.dcvEmissive.g = 0;
  103.         m_mtrlColor.dcvEmissive.b = 0;
  104.     }
  105.  
  106. private:
  107.     D3DMATERIAL9 m_mtrlColor;
  108. };
  109. #endif
  110.  
  111. // identifier was truncated to '255' characters in the browser information
  112. #pragma warning(disable: 4786)
  113.  
  114. const char *x_szSeparators = " \n\r\t";
  115. const char *x_szVertex = "Vertex";
  116. const UINT x_cchVertex = 6;
  117. const char *x_szCorner = "Corner";
  118. const UINT x_cchCorner = 6;
  119. const char *x_szFace = "Face";
  120. const UINT x_cchFace = 4;
  121. const char *x_szOpenParen = "(";
  122. const char *x_szCloseParen = ")";
  123. const char *x_szOptionalArgStart = "{";
  124. const char *x_szOptionalArgEnd = "}";
  125. const char *x_szRGB = "rgb";
  126. const char *x_szMatId = "matid";
  127. const char *x_szNormal = "normal";
  128. const char *x_szUv = "uv";
  129. const char *x_szEquals = "=";
  130.  
  131. HRESULT
  132. CFileContext::GetCharHelper(char *pchBuffer, bool &bEOF)
  133. {
  134.     HRESULT hr = S_OK;
  135.     unsigned long cchRead;
  136.  
  137.     GXASSERT(m_ichBuffer == m_cchBuffer);
  138.  
  139.     if (m_bEndOfFile)
  140.     {
  141.         bEOF = true;
  142.         goto e_Exit;
  143.     }
  144.  
  145.     hr = m_pstream->Read(m_szBuffer, x_cbBufferSize, &cchRead);
  146.     if (FAILED(hr) || (cchRead == 0))
  147.     {
  148.         if ((hr == S_FALSE) || (cchRead == 0))
  149.         {
  150.             m_bEndOfFile = true;
  151.             bEOF = true;
  152.             hr = S_OK;
  153.         }
  154.  
  155.         goto e_Exit;
  156.     }
  157.  
  158.     m_cchBuffer = cchRead;
  159.     m_ichBuffer = 0;
  160.  
  161.     hr = GetChar(pchBuffer, bEOF);
  162.     if (FAILED(hr))
  163.         goto e_Exit;
  164.  
  165. e_Exit:
  166.     return hr;
  167. }
  168.  
  169. HRESULT
  170. CFileContext::GetLine(char *szBuffer, int cchBuffer, bool &bEOF)
  171. {
  172.     int ichBuffer;
  173.     HRESULT hr = S_OK;
  174.     bool bTemp;
  175.     char chTemp;
  176.  
  177.     ichBuffer = 0;
  178.     bEOF = false;
  179.  
  180.     hr = GetChar(&szBuffer[ichBuffer], bEOF);
  181.         if (FAILED(hr) || bEOF)
  182.     {
  183.         // this is both an acceptable EOF case, and an error case, but no way to tell the user
  184.         goto e_Exit;
  185.     }
  186.  
  187.     while ((szBuffer[ichBuffer] != '\n') && (ichBuffer < cchBuffer - 2))
  188.     {
  189.         ichBuffer += 1;
  190.  
  191.         hr = GetChar(&szBuffer[ichBuffer], bTemp);
  192.             if (FAILED(hr) || bTemp)
  193.         {
  194.             szBuffer[ichBuffer+1] = '\0';
  195.             goto e_Exit;
  196.         }
  197.  
  198.         if (szBuffer[ichBuffer] == '\r')
  199.             ichBuffer -= 1;
  200.     }
  201.  
  202.  
  203.     szBuffer[ichBuffer+1] = '\0';
  204.  
  205.     // if we hit the limit of the string without hitting the end of the line
  206.     //    then skip the rest of the line
  207.     if ((ichBuffer == cchBuffer - 2) && (szBuffer[ichBuffer] != '\n'))
  208.     {
  209.         do
  210.         {
  211.             hr = GetChar(&chTemp, bTemp);
  212.             if (FAILED(hr) || bTemp)
  213.                 goto e_Exit;
  214.         }
  215.         while (chTemp != '\n');
  216.     }
  217.  
  218. e_Exit:
  219.     return hr;;
  220. }
  221.  
  222.  
  223.  
  224. const UINT x_cOptionalArgsMax = 4;
  225.  
  226. class CParseOptionalArgs
  227. {
  228. private:
  229.     char *m_rgszArgs[x_cOptionalArgsMax];
  230.     UINT m_rgcchArgs[x_cOptionalArgsMax];
  231.     char *m_rgszValues[x_cOptionalArgsMax];
  232.     UINT m_rgcchValues[x_cOptionalArgsMax];
  233.  
  234.     UINT m_cOptionalArgs;
  235.  
  236. public:
  237.     CParseOptionalArgs()
  238.         :m_cOptionalArgs(0) { }
  239.  
  240.     UINT COptionalArgs() const { return m_cOptionalArgs; }
  241.  
  242.     HRESULT Parse(char *szOptionalArgs);
  243.     bool BCompareArg(UINT iOptionalArg, const char *szPossibleArg);
  244.  
  245.     HRESULT GetPoint2(UINT iOptionalArg, D3DXVECTOR2 *puvPoint);
  246.     HRESULT GetVector3(UINT iOptionalArg, D3DXVECTOR3 *pvVector);
  247.     HRESULT GetCoVector3(UINT iOptionalArg, D3DXVECTOR3 *pvVector);
  248.  
  249.     HRESULT GetColorRGB(UINT iOptionalArg, D3DXCOLOR *pcolor);
  250.     HRESULT GetDWORD(UINT iOptionalArg, DWORD *piArg);
  251. };
  252.  
  253. char *
  254. EatWhiteSpace(char *szBuf)
  255. {
  256.     while ((*szBuf == ' ') || (*szBuf == '\t'))
  257.     {
  258.         szBuf++;
  259.     }
  260.  
  261.     return szBuf;
  262. }
  263.  
  264. bool NotZero(D3DXVECTOR3 &vNormal)
  265. {
  266.     return (vNormal.x != 0.0f) || (vNormal.y != 0.0f) || (vNormal.z != 0.0f);
  267. }
  268.  
  269. char *
  270. EatNonWhiteSpace(char *szBuf, char chTerminator)
  271. {
  272.     while ((*szBuf != '\0') && (*szBuf != ' ') && (*szBuf != '\t') && (*szBuf != chTerminator))
  273.     {
  274.         szBuf++;
  275.     }
  276.  
  277.     return szBuf;
  278. }
  279.  
  280. char *
  281. EatUntilTerminator(char *szBuf, char chTerminator)
  282. {
  283.     while ((*szBuf != '\0') && (*szBuf != chTerminator))
  284.     {
  285.         szBuf++;
  286.     }
  287.  
  288.     return szBuf;
  289. }
  290.  
  291. HRESULT
  292. CParseOptionalArgs::Parse(char *szOptionalArgs)
  293. {
  294.     HRESULT hr = S_OK;
  295.     char *szCur = szOptionalArgs;
  296.     UINT iOptionalArg;
  297.  
  298.     // find the start of the string
  299.     szCur = EatWhiteSpace(szCur);
  300.  
  301.     if (*szCur != '{')
  302.     {
  303.         hr = E_FAIL;
  304.         goto e_Exit;
  305.     }
  306.     szCur++;
  307.  
  308.     while (szCur != '\0')
  309.     {
  310.         szCur = EatWhiteSpace(szCur);
  311.  
  312.         // if at the end of the string, then exit
  313.         if (*szCur == '\0')
  314.             break;
  315.  
  316.         // found the first argument
  317.         iOptionalArg = m_cOptionalArgs;
  318.         m_cOptionalArgs += 1;
  319.  
  320.         m_rgszArgs[iOptionalArg] = szCur;
  321.  
  322.  
  323.         // now figure out how long it is
  324.         szCur = EatNonWhiteSpace(szCur, '=');
  325.         m_rgcchArgs[iOptionalArg] = (DWORD)(szCur - m_rgszArgs[iOptionalArg]);
  326.  
  327.         szCur = EatWhiteSpace(szCur);
  328.  
  329.         // if there is a value, find it, else go to next arg
  330.         if (*szCur == '=')
  331.         {
  332.             szCur++; // skip the '='
  333.  
  334.             szCur = EatWhiteSpace(szCur);
  335.  
  336.             // had better be an argument if there was an '='
  337.             if (*szCur == '\0')
  338.             {
  339.                 hr = E_FAIL;
  340.                 goto e_Exit;
  341.             }
  342.  
  343.             m_rgszValues[iOptionalArg] = szCur;
  344.  
  345.             if (*szCur == '(')
  346.             {
  347.                 szCur = EatUntilTerminator(szCur, ')');
  348.                 if (*szCur == '\0')
  349.                 {
  350.                     hr = E_FAIL;
  351.                     goto e_Exit;
  352.                 }
  353.                 szCur++;  // move beyond the ')'
  354.  
  355.                 m_rgcchValues[iOptionalArg] = (DWORD)(szCur - m_rgszValues[iOptionalArg]);
  356.             }
  357.             else
  358.             {
  359.                 // NOTE: hitting end of string here is completely acceptable
  360.                 //   and pass in ' ' as the terminator because there is no special terminator
  361.                 szCur = EatNonWhiteSpace(szCur, ' ');
  362.  
  363.                 m_rgcchValues[iOptionalArg] = (DWORD)(szCur - m_rgszValues[iOptionalArg]);
  364.             }
  365.  
  366.         }
  367.         else
  368.         {
  369.             m_rgszValues[iOptionalArg] = NULL;
  370.             m_rgcchValues[iOptionalArg] = 0;
  371.         }
  372.     }
  373.  
  374. e_Exit:
  375.     return hr;
  376. }
  377.  
  378. bool
  379. CParseOptionalArgs::BCompareArg(UINT iOptionalArg, const char *szPossibleArg)
  380. {
  381.     GXASSERT(iOptionalArg < m_cOptionalArgs);
  382.     return strncmp(szPossibleArg, m_rgszArgs[iOptionalArg], m_rgcchArgs[iOptionalArg]) == 0;
  383. }
  384.  
  385. HRESULT
  386. CParseOptionalArgs::GetDWORD(UINT iOptionalArg, DWORD *piArg)
  387. {
  388.     GXASSERT(iOptionalArg < m_cOptionalArgs);
  389.  
  390.     *piArg = atoi(m_rgszValues[iOptionalArg]);
  391.  
  392.     return S_OK;
  393. }
  394.  
  395. HRESULT
  396. CParseOptionalArgs::GetColorRGB(UINT iOptionalArg, D3DXCOLOR *pcolor)
  397. {
  398.     GXASSERT(iOptionalArg < m_cOptionalArgs);
  399.  
  400.     HRESULT hr = S_OK;
  401.     char *szCur;
  402.  
  403.     szCur = m_rgszValues[iOptionalArg];
  404.  
  405.     GXASSERT(*szCur == '(');
  406.     szCur++;
  407.  
  408.     // convert the three numbers into a color
  409.     pcolor->r = (float)strtod(szCur, &szCur);
  410.     pcolor->g = (float)strtod(szCur, &szCur);
  411.     pcolor->b = (float)strtod(szCur, &szCur);
  412.     pcolor->a = 0.0f;
  413.  
  414.     return hr;
  415. }
  416.  
  417. HRESULT
  418. CParseOptionalArgs::GetPoint2(UINT iOptionalArg, D3DXVECTOR2 *puvPoint)
  419. {
  420.     GXASSERT(iOptionalArg < m_cOptionalArgs);
  421.  
  422.     HRESULT hr = S_OK;
  423.     char *szCur;
  424.  
  425.     szCur = m_rgszValues[iOptionalArg];
  426.  
  427.     GXASSERT(*szCur == '(');
  428.     szCur++;
  429.  
  430.     // find and convert the first number
  431.     puvPoint->x = (float)strtod(szCur, &szCur);
  432.     puvPoint->y = (float)strtod(szCur, &szCur);
  433.  
  434.     return hr;
  435. }
  436.  
  437. HRESULT
  438. CParseOptionalArgs::GetVector3(UINT iOptionalArg, D3DXVECTOR3 *pvVector)
  439. {
  440.     GXASSERT(iOptionalArg < m_cOptionalArgs);
  441.  
  442.     HRESULT hr = S_OK;
  443.     char *szCur;
  444.  
  445.     szCur = m_rgszValues[iOptionalArg];
  446.  
  447.     GXASSERT(*szCur == '(');
  448.     szCur++;
  449.  
  450.     // find and convert the first number
  451.     pvVector->x = (float)strtod(szCur, &szCur);
  452.     pvVector->y = (float)strtod(szCur, &szCur);
  453.     pvVector->z = (float)strtod(szCur, &szCur);
  454.  
  455.     return hr;
  456. }
  457.  
  458. HRESULT
  459. CParseOptionalArgs::GetCoVector3(UINT iOptionalArg, D3DXVECTOR3 *pvVector)
  460. {
  461.     HRESULT hr;
  462.  
  463.     D3DXVECTOR3 vTemp;
  464.     hr = GetVector3(iOptionalArg, &vTemp);
  465.     if (FAILED(hr))
  466.         return hr;
  467.  
  468.     *pvVector = vTemp;
  469.  
  470.     return S_OK;
  471. }
  472.  
  473.  
  474. HRESULT
  475. LoadCounts(CFileContext *pfc, UINT *pcVertices, UINT *pcFaces, UINT *pcCorners)
  476. {
  477.     HRESULT hr = S_OK;
  478.     char rgchBuf[20];
  479.     char *szHeader;
  480.     UINT cFaces;
  481.     UINT cVertices;
  482.     UINT cCorners;
  483.     char *szValue;
  484.     UINT cNewValue;
  485.     bool bEOF;
  486.  
  487.     GXASSERT((pcVertices != NULL) && (pcFaces != NULL) && (pcCorners != NULL));
  488.  
  489.     // initialize the counters
  490.     *pcVertices = UINT_MAX;
  491.     *pcFaces = UINT_MAX;
  492.     *pcCorners = UINT_MAX;
  493.  
  494.  
  495.     cFaces = 0;
  496.     cVertices = 0;
  497.     cCorners = 0;
  498.  
  499.     // get the counts of the faces, vertices, etc
  500.     while ( 1 )
  501.     {
  502.         hr = pfc->GetLine(rgchBuf, sizeof(rgchBuf), bEOF);
  503.         if (FAILED(hr))
  504.         {
  505.             goto e_Exit;
  506.         }
  507.  
  508.         if (bEOF)
  509.         {
  510.             break;  // EOF, break out of loop
  511.         }
  512.  
  513.         szHeader = strtok( rgchBuf, x_szSeparators );
  514.  
  515.         // if the token is NULL, go onto the next line
  516.         if (szHeader != NULL)
  517.         {
  518.             // add the line to the proper count if it fits the profile
  519.             if (strcmp(szHeader, x_szVertex) == 0)
  520.             {
  521.                 szValue = strtok( NULL, x_szSeparators );
  522.                 if (szValue == NULL)
  523.                 {
  524.                     hr = E_FAIL;
  525.                     goto e_Exit;
  526.                 }
  527.  
  528.                 cNewValue = atol(szValue);
  529.                 if (cVertices < cNewValue)
  530.                     cVertices = cNewValue;
  531.             }
  532.             else if (strcmp(szHeader, x_szFace) == 0)
  533.             {
  534.                 szValue = strtok( NULL, x_szSeparators );
  535.                 if (szValue == NULL)
  536.                 {
  537.                     hr = E_FAIL;
  538.                     goto e_Exit;
  539.                 }
  540.  
  541.                 cNewValue = atol(szValue);
  542.                 if (cFaces < cNewValue)
  543.                     cFaces = cNewValue;
  544.             }
  545.             else if (strcmp(szHeader, x_szCorner) == 0)
  546.             {
  547.                 cCorners += 1;
  548.             }
  549.  
  550.         }
  551.     }
  552.  
  553.     *pcFaces = cFaces;
  554.     *pcVertices = cVertices;
  555.     *pcCorners = cCorners;
  556.  
  557.     // rewind
  558.     hr = pfc->Rewind();
  559.     if (FAILED(hr))
  560.         goto e_Exit;
  561.  
  562. e_Exit:
  563.     return hr;
  564. }
  565.  
  566.  
  567. HRESULT
  568. LoadVertex(char *szLineBuf, SLoadVertex *rglvVertices, UINT cVertices, bool &bNormalFound)
  569. {
  570.     HRESULT hr = S_OK;
  571.     char *szToken;
  572.     char *szPointId;
  573.     char *szPointX;
  574.     char *szPointY;
  575.     char *szPointZ;
  576.     char *szHeader;
  577.     UINT ulPointId;
  578.     UINT iOptionalArg;
  579.  
  580.  
  581.     // the header should always be present, checked before calling this function
  582.     szHeader = strtok( szLineBuf, x_szSeparators );
  583.     GXASSERT((szHeader != NULL) && strcmp(szHeader, x_szVertex) == 0);
  584.  
  585.     // get the number for the count
  586.     szPointId = strtok( NULL, x_szSeparators );
  587.     if (szPointId == NULL)
  588.     {
  589.         hr = E_FAIL;
  590.         goto e_Exit;
  591.     }
  592.  
  593.     // load the various parts of the vertex from the strings
  594.     szPointX = strtok( NULL, x_szSeparators );
  595.     if (szPointX == NULL)
  596.     {
  597.         hr = E_FAIL;
  598.         goto e_Exit;
  599.     }
  600.  
  601.     szPointY = strtok( NULL, x_szSeparators );
  602.     if (szPointY == NULL)
  603.     {
  604.         hr = E_FAIL;
  605.         goto e_Exit;
  606.     }
  607.  
  608.     szPointZ = strtok( NULL, x_szSeparators );
  609.     if (szPointZ == NULL)
  610.     {
  611.         hr = E_FAIL;
  612.         goto e_Exit;
  613.     }
  614.  
  615.     ulPointId = atoi(szPointId);
  616.     if ((ulPointId == 0) || (ulPointId > cVertices))
  617.     {
  618.         hr = E_FAIL;
  619.         goto e_Exit;
  620.     }
  621.  
  622.     // convert from one based to zero based
  623.     ulPointId -= 1;
  624.  
  625.     // UNDONE - handle errors by not using atof
  626.     rglvVertices[ulPointId].m_vPos = D3DXVECTOR3((float)atof(szPointX), (float)atof(szPointY), (float)atof(szPointZ));
  627.  
  628.     // look optional information
  629.     szToken = strtok( NULL, "}" );
  630.     if (szToken != NULL)
  631.     {
  632.         CParseOptionalArgs ParseArgs;
  633.  
  634.         // parse the optional information, into an wonder of all wonders, a readable form
  635.         hr = ParseArgs.Parse(szToken);
  636.         if (FAILED(hr))
  637.         {
  638.             goto e_Exit;
  639.         }
  640.  
  641.         // loop over all the args, getting the info for the understood items
  642.         for (iOptionalArg = 0; iOptionalArg < ParseArgs.COptionalArgs(); iOptionalArg++)
  643.         {
  644.             if (ParseArgs.BCompareArg(iOptionalArg, x_szNormal))
  645.             {
  646.                 hr = ParseArgs.GetCoVector3(iOptionalArg, &rglvVertices[ulPointId].m_vNormal);
  647.                 if (FAILED(hr))
  648.                     goto e_Exit;
  649.  
  650.                 bNormalFound = NotZero(rglvVertices[ulPointId].m_vNormal);
  651.             }
  652.             else if (ParseArgs.BCompareArg(iOptionalArg, x_szUv))
  653.             {
  654.                 hr = ParseArgs.GetPoint2(iOptionalArg, &rglvVertices[ulPointId].m_uvTex1);
  655.                 if (FAILED(hr))
  656.                     goto e_Exit;
  657.             }
  658.         }
  659.     }
  660.  
  661. e_Exit:
  662.     return hr;
  663. }
  664.  
  665. HRESULT
  666. LoadFace(char *szLineBuf, UINT cFacesMax, SLoadedFace *rgFaces)
  667. {
  668.     HRESULT hr = S_OK;
  669.     char *szToken;
  670.     char *szFaceId;
  671.     char *szPoint1;
  672.     char *szPoint2;
  673.     char *szPoint3;
  674.     char *szHeader;
  675.     UINT ulFaceId;
  676.     UINT iOptionalArg;
  677.  
  678.     szHeader = strtok( szLineBuf, x_szSeparators );
  679.     GXASSERT((szHeader != NULL) && strcmp(szHeader, x_szFace) == 0);
  680.  
  681.  
  682.     // get the number for the count
  683.     szFaceId = strtok( NULL, x_szSeparators );
  684.     if (szFaceId == NULL)
  685.     {
  686.         hr = E_FAIL;
  687.         goto e_Exit;
  688.     }
  689.  
  690.     ulFaceId = atoi(szFaceId) - 1;
  691.  
  692.     // if the face id is too high, and/or the face is already in use (specified twice in file)
  693.     if ((ulFaceId >= cFacesMax) || (rgFaces[ulFaceId].m_wIndices[0] != UNUSED32))
  694.     {
  695.         hr = E_INVALIDARG;
  696.         goto e_Exit;
  697.     }
  698.  
  699.     // load the various parts of the vertex from the strings
  700.     szPoint1 = strtok( NULL, x_szSeparators );
  701.     if (szPoint1 == NULL)
  702.     {
  703.         hr = E_FAIL;
  704.         goto e_Exit;
  705.     }
  706.  
  707.     szPoint2 = strtok( NULL, x_szSeparators );
  708.     if (szPoint2 == NULL)
  709.     {
  710.         hr = E_FAIL;
  711.         goto e_Exit;
  712.     }
  713.  
  714.     szPoint3 = strtok( NULL, x_szSeparators );
  715.     if (szPoint3 == NULL)
  716.     {
  717.         hr = E_FAIL;
  718.         goto e_Exit;
  719.     }
  720.  
  721.     // UNDONE - handle errors by not using atoi
  722.     // NOTE: reverse the ordering of the indices... otherwise CCW ordering becomes CW ordering
  723.     //          when -z applied to change from right hand to left hand coordinate system
  724.     rgFaces[ulFaceId] = SLoadedFace(atoi(szPoint1)-1, atoi(szPoint2)-1, atoi(szPoint3)-1);
  725.  
  726.  
  727.     // look optional information
  728.     szToken = strtok( NULL, "}\n" );
  729.     if (szToken != NULL)
  730.     {
  731.         CParseOptionalArgs ParseArgs;
  732.  
  733.         // parse the optional information, into an wonder of all wonders, a readable form
  734.         hr = ParseArgs.Parse(szToken);
  735.         if (FAILED(hr))
  736.         {
  737.             goto e_Exit;
  738.         }
  739.  
  740.         // loop over all the args, getting the info for the understood items
  741.         for (iOptionalArg = 0; iOptionalArg < ParseArgs.COptionalArgs(); iOptionalArg++)
  742.         {
  743.             if (ParseArgs.BCompareArg(iOptionalArg, x_szMatId))
  744.             {
  745.                 rgFaces[ulFaceId].m_bMaterialSpecified = true;
  746.  
  747.                 hr = ParseArgs.GetDWORD(iOptionalArg, &rgFaces[ulFaceId].m_matid);
  748.                 if (FAILED(hr))
  749.                     goto e_Exit;
  750.             }
  751.             else if (ParseArgs.BCompareArg(iOptionalArg, x_szRGB))
  752.             {
  753.                 rgFaces[ulFaceId].m_bColorSpecified = true;
  754.  
  755.                 hr = ParseArgs.GetColorRGB(iOptionalArg, &rgFaces[ulFaceId].m_colorFace);
  756.                 if (FAILED(hr))
  757.                     goto e_Exit;
  758.             }
  759.         }
  760.     }
  761.  
  762. e_Exit:
  763.  
  764.     return hr;
  765. }
  766.  
  767. HRESULT
  768. LoadCorner(char *szLineBuf, UINT iCorner, UINT cVertices, UINT cFaces, SCorner *rgCorners, bool &bNormalFound)
  769. {
  770.     HRESULT hr = S_OK;
  771.     char *szToken;
  772.     char *szFaceId;
  773.     char *szPointId;
  774.     char *szHeader;
  775.     UINT ulFaceId;
  776.     UINT ulPointId;
  777.     UINT iOptionalArg;
  778.  
  779.     szHeader = strtok( szLineBuf, x_szSeparators );
  780.     GXASSERT((szHeader != NULL) && strcmp(szHeader, x_szCorner) == 0);
  781.  
  782.  
  783.     // get the number for the count
  784.     szPointId = strtok( NULL, x_szSeparators );
  785.     if (szPointId == NULL)
  786.     {
  787.         hr = E_FAIL;
  788.         goto e_Exit;
  789.     }
  790.  
  791.     szFaceId = strtok( NULL, x_szSeparators );
  792.     if (szFaceId == NULL)
  793.     {
  794.         hr = E_FAIL;
  795.         goto e_Exit;
  796.     }
  797.  
  798.     ulFaceId = atoi(szFaceId) - 1;
  799.     ulPointId = atoi(szPointId) - 1;
  800.  
  801.     if ((ulFaceId >= cFaces) || (ulPointId > cVertices))
  802.     {
  803.         hr = E_INVALIDARG;
  804.         goto e_Exit;
  805.     }
  806.  
  807.     rgCorners[iCorner].m_wFace = ulFaceId;
  808.     rgCorners[iCorner].m_wPoint = ulPointId;
  809.  
  810.  
  811.     // look optional information
  812.     szToken = strtok( NULL, "}\n" );
  813.     if (szToken != NULL)
  814.     {
  815.         CParseOptionalArgs ParseArgs;
  816.  
  817.         // parse the optional information, into an wonder of all wonders, a readable form
  818.         hr = ParseArgs.Parse(szToken);
  819.         if (FAILED(hr))
  820.         {
  821.             goto e_Exit;
  822.         }
  823.  
  824.         // loop over all the args, getting the info for the understood items
  825.         for (iOptionalArg = 0; iOptionalArg < ParseArgs.COptionalArgs(); iOptionalArg++)
  826.         {
  827.  
  828.             if (ParseArgs.BCompareArg(iOptionalArg, x_szNormal))
  829.             {
  830.                 rgCorners[iCorner].m_bNormalSpecified = true;
  831.  
  832.                 hr = ParseArgs.GetCoVector3(iOptionalArg, &rgCorners[iCorner].m_vNormal);
  833.                 if (FAILED(hr))
  834.                     goto e_Exit;
  835.  
  836.                 bNormalFound = NotZero(rgCorners[iCorner].m_vNormal);
  837.             }
  838.             else if (ParseArgs.BCompareArg(iOptionalArg, x_szUv))
  839.             {
  840.                 rgCorners[iCorner].m_bUvSpecified = true;
  841.  
  842.                 hr = ParseArgs.GetPoint2(iOptionalArg, &rgCorners[iCorner].m_uvTex1);
  843.                 if (FAILED(hr))
  844.                     goto e_Exit;
  845.             }
  846.         }
  847.     }
  848.  
  849. e_Exit:
  850.  
  851.     return hr;
  852. }
  853.  
  854. HRESULT WINAPI
  855. LoadMeshFromM(IStream *pstream, DWORD options, DWORD fvf,
  856.               LPDIRECT3DDEVICE9 pD3DDevice,
  857.               LPD3DXMESH *ppMesh, LPD3DXBUFFER *ppbufAdjacency)
  858. {
  859.     HRESULT hr = S_OK;
  860.     UINT cVertices;
  861.     UINT cCorners;
  862.     UINT cFaces;
  863.     UINT iVert;
  864.     bool bNormalFound = false;
  865.     UINT iFace;
  866.  
  867.     SLoadedFace        *rglfFaces = NULL;
  868.     SLoadVertex *rglvLoaded = NULL;
  869.     SCorner *rgCorners = NULL;
  870.  
  871.     bool bEOF;
  872.     UINT iCorner = 0;
  873.     CFileContext fc(pstream);
  874.  
  875.     char rgchBuf[256];
  876.  
  877. #if 0 // color attribute bundle testing
  878.     //IGXAttributeBundle *pattrColor;
  879.     //IGXAttributeBundle **rgBundles = NULL;
  880.     UINT cBundles = 0;
  881.     UINT cBundlesMax = 0;
  882.     D3DXCOLOR *rgColors = NULL;
  883.     UINT cColors = 0;
  884.     UINT cColorsMax = 0;
  885.     UINT iColor;
  886.     const D3DXCOLOR colorGrey(0.5f, 0.5f, 0.5f, 0.0f);
  887. #endif
  888.  
  889.     if ((ppMesh == NULL) || (pstream == NULL))
  890.     {
  891.         hr = E_INVALIDARG;
  892.         goto e_Exit;
  893.     }
  894.  
  895.     hr = LoadCounts(&fc, &cVertices, &cFaces, &cCorners);
  896.     if (FAILED(hr))
  897.         goto e_Exit;
  898.  
  899.     if ((cVertices == 0) || (cFaces == 0))
  900.     {
  901.         hr = E_INVALIDARG;
  902.         goto e_Exit;
  903.     }
  904.  
  905.     // allocate memory to load data into
  906.  
  907.     hr = InitVertices(rglvLoaded, cVertices);
  908.     if (FAILED(hr))
  909.         goto e_Exit;
  910.  
  911.     hr = InitFaces(rglfFaces, cFaces);
  912.     if (FAILED(hr))
  913.         goto e_Exit;
  914.  
  915.     hr = InitCorners(rgCorners, cCorners);
  916.     if (FAILED(hr))
  917.         goto e_Exit;
  918.  
  919.     // initialize the colors of the vertices to a reasonable default
  920.     for (iVert = 0; iVert < cVertices; iVert++)
  921.     {
  922.         rglvLoaded[iVert].m_color = D3DXCOLOR(0.9f, 0.6f, 0.4f, 0.0f);
  923.     }
  924.  
  925.     while ( 1 )
  926.     {
  927.         hr = fc.GetLine(rgchBuf, sizeof(rgchBuf), bEOF);
  928.         if (FAILED(hr))
  929.         {
  930.             goto e_Exit;
  931.         }
  932.  
  933.         if (bEOF)
  934.         {
  935.             break;  // EOF, break out of loop
  936.         }
  937.  
  938.         // load the various face and vertices, ignore unrecognized lines
  939.  
  940.         if (strncmp(rgchBuf, x_szVertex, x_cchVertex) == 0)
  941.         {
  942.             hr = LoadVertex(rgchBuf, rglvLoaded, cVertices, bNormalFound);
  943.             if (FAILED(hr))
  944.                 goto e_Exit;
  945.         }
  946.         else if (strncmp(rgchBuf, x_szFace, x_cchFace) == 0)
  947.         {
  948.             hr = LoadFace(rgchBuf, cFaces, rglfFaces);
  949.             if (FAILED(hr))
  950.                 goto e_Exit;
  951.         }
  952.         else if (strncmp(rgchBuf, x_szCorner, x_cchCorner) == 0)
  953.         {
  954.             hr = LoadCorner(rgchBuf, iCorner, cVertices, cFaces, rgCorners, bNormalFound);
  955.             if (FAILED(hr))
  956.                 goto e_Exit;
  957.  
  958.             iCorner++;
  959.         }
  960.     }
  961.  
  962.     GXASSERT(iCorner == cCorners);
  963.  
  964.     if (!bNormalFound)
  965.     {
  966.         for (iFace = 0; iFace < cFaces; iFace++)
  967.         {
  968.             if (rglfFaces[iFace].m_wIndices[0] != UNUSED32)
  969.             {
  970.                 rglfFaces[iFace].m_bSmoothingGroupSpecified = true;
  971.                 rglfFaces[iFace].m_iSmoothingGroup = 1;
  972.             }
  973.         }
  974.     }
  975.  
  976.     // test materials by generating materials for colors
  977.  
  978. #if 0
  979.     for (iFace = 0; iFace < cFaces; iFace++)
  980.     {
  981.         if (rglfFaces[iFace].m_bColorSpecified)
  982.         {
  983.             for (iColor = 0; iColor < cColors; iColor++)
  984.             {
  985.                 if (rgColors[iColor] == rglfFaces[iFace].m_colorFace)
  986.                     break;
  987.             }
  988.  
  989.             if (iColor == cColors)
  990.             {
  991.                 if ( ! AddToDynamicArray( &rgColors, rglfFaces[iFace].m_colorFace, &cColors, &cColorsMax ) )
  992.                 {
  993.                     hr = E_OUTOFMEMORY;
  994.                     goto e_Exit;
  995.                 }
  996.             }
  997.  
  998. #if 0
  999.             if (iColor < cColors)
  1000.             {
  1001.                 pattrColor = rgBundles[iColor];
  1002.             }
  1003.             else
  1004.             {
  1005.                 if ( ! AddToDynamicArray( &rgColors, rglfFaces[iFace].m_colorFace, &cColors, &cColorsMax ) )
  1006.                 {
  1007.                     hr = E_OUTOFMEMORY;
  1008.                     goto e_Exit;
  1009.                 }
  1010.  
  1011.                 pattrColor = new GXColorAttributeBundle(rglfFaces[iFace].m_colorFace);
  1012.                 if (pattrColor == NULL)
  1013.                 {
  1014.                     hr = E_OUTOFMEMORY;
  1015.                     goto e_Exit;
  1016.                 }
  1017.  
  1018.                 if ( ! AddToDynamicArray( &rgBundles, pattrColor, &cBundles, &cBundlesMax ) )
  1019.                 {
  1020.                     hr = E_OUTOFMEMORY;
  1021.                     goto e_Exit;
  1022.                 }
  1023.             }
  1024. #endif
  1025.  
  1026.             //rglfFaces[iFace].m_pattr = pattrColor;
  1027.             rglfFaces[iFace].m_attr = iColor;
  1028.             rglfFaces[iFace].m_bAttributeSpecified = true;
  1029.  
  1030.             rglfFaces[iFace].m_colorFace = colorGrey;
  1031.             //rglfFaces[iFace].m_bColorSpecified = false;
  1032.         }
  1033.     }
  1034. #endif
  1035.  
  1036.  
  1037.     hr = SetMesh(rglfFaces, cFaces, rglvLoaded, cVertices, rgCorners, cCorners, NULL, FALSE, NULL,
  1038.                         options, fvf, pD3DDevice, ppMesh, ppbufAdjacency);
  1039.     if (FAILED(hr))
  1040.         goto e_Exit;
  1041.  
  1042. e_Exit:
  1043.  
  1044.     delete []rglfFaces;
  1045.     delete []rglvLoaded;
  1046.     delete []rgCorners;
  1047.  
  1048.     return hr;
  1049. }
  1050.  
  1051. }
  1052.