#include "precomp.h" #pragma hdrstop #include "cpmesh.h" #include "pmerrors.h" #include "fileio.h" float (* vdata)[3]; static GLuint LoadTexture (char* file) { return 0; } const short PM_MAX_TEX_STRING_LEN = 1024; // Enforced by the spec. /* * This function currently only works on external files, not on URLs. * It can only load .pmx files and not PM records embedded in X files. * Hence the "pmname" argument is ignored. * It only supports synchronous loads so pPMeshLoadCB is ignored * !!Currently no memory cleanup occurs on error. Must add code to do so. * Could use a local win32 heap!! * See \\anujg\docs\"Progressive Mesh file format.doc" for details on the * file format */ /* * The concept of Materials: * 1) Materials can be "looked up", i.e. textures * 2) Computed using a API specific lighting equation. (pure mat) * 3) Both of above combined. (Modulated/Lit textures) */ STDMETHODIMP CPMeshGL::Load(const TCHAR* const url, const TCHAR* const pmname, DWORD* const minvert, DWORD* const maxvert, LPPMESHLOADCB pPMeshLoadCB) { DWORD i, k; WORD j, ftCurveSize, fmCurveSize; DWORD vAttr, wAttr, fAttr, mAttr, sAttr; DWORD mOffset, vOffset, wOffset, fOffset; DWORD& maxVert = *maxvert; DWORD& minVert = *minvert; HRESULT hr; DWORD vsplit_offset, bmesh_offset; // Estimated number of faces and wedges in the mesh with maxvert vertices DWORD nFacePredict=0, nWedgePredict=0; // A curve is approximated by an array of pairs {(x,y), (x,y),...} typedef struct crvpnt{ DWORD x; float y; } *CURVE; CURVE *ftcurves, *fmcurves; // An array of curves ifstream is(url); if (!is) return PM_E_FOPENERROR; is.setmode(filebuf::binary); #ifdef __DUMP_DATA ofstream dump("dump.pmx"); if (!dump) return PM_E_FOPENERROR; dump.setmode(filebuf::text); #endif //__DUMP_DATA /* * Read PMesh Header */ read_DWORD(is, m_maxVertices); #ifdef __MAT_PREALLOC_OPTIMIZATION maxVert = min(maxVert, m_maxVertices); #else maxVert = m_maxVertices; #endif //__MAT_PREALLOC_OPTIMIZATION *maxvert = maxVert; read_DWORD(is, m_maxWedges); read_DWORD(is, m_maxFaces); read_DWORD(is, m_maxMaterials); read_DWORD(is, m_maxTextures); #ifdef __DUMP_DATA dump << "\nMaxVert = " << m_maxVertices; dump << "\nMaxWedges = " << m_maxWedges; dump << "\nMaxFaces = " << m_maxFaces; dump << "\nMaxMat = " << m_maxMaterials; dump << "\nMaxTex = " << m_maxTextures; #endif //__DUMP_DATA /* * Max Valence */ read_DWORD(is, i); if (i > 65535) return PM_E_BADVALENCE; #ifdef __DUMP_DATA dump << "\nMaxValence = " << i; #endif //__DUMP_DATA /* * Normal Encoding */ read_WORD(is, j); if (((j & NORM_MASK) != NORM_EXPLICIT) || ((j & TEX_MASK) != TEX_EXPLICIT)) return PM_E_BADWEDGEDATA; #ifdef __DUMP_DATA dump << "\nNormal Encoding = " << j; #endif //__DUMP_DATA /* * Integer Encoding */ read_WORD(is, j); // integer encoding type if (j != INTC_MAX) return PM_E_BADINTCODE; #ifdef __DUMP_DATA dump << "\nInteger Encoding = " << j; #endif //__DUMP_DATA /* * Sizes of various user defined attributes */ read_DWORD(is, vAttr); // Vertex attributes read_DWORD(is, wAttr); // Wedge attributes read_DWORD(is, fAttr); // Face attributes read_DWORD(is, mAttr); // Material attributes read_DWORD(is, sAttr); // VSplit attributes #ifdef __DUMP_DATA dump << "\n\nUser defined attribute sizes:"; dump << "\nVertex: " << vAttr; dump << "\nWedge: " << wAttr; dump << "\nFace: " << fAttr; dump << "\nMaterial: " << mAttr; dump << "\nVSplit: " << sAttr; #endif //__DUMP_DATA /* * Allocate material and texture related tables */ WORD *matcnt = new WORD [m_maxMaterials]; #ifdef __MATPOS_IS_A_PTR GLface **matpos = new GLface* [m_maxMaterials]; #else WORD *matpos = new WORD [m_maxMaterials]; #endif GLmaterial *matArray = new GLmaterial [m_maxMaterials]; if (!matArray || !matcnt || !matpos) { return E_OUTOFMEMORY; } else { m_matArray = matArray; m_matcnt = matcnt; m_matpos = matpos; } #ifdef __MATPOS_IS_A_PTR /* * Allocate the vertex and normal arrays. */ GLvertex *varray = new GLvertex [m_maxWedges]; GLnormal *narray = new GLnormal [m_maxWedges]; GLtexCoord *tarray = new GLtexCoord [m_maxWedges]; WORD *wedgelist = new WORD [m_maxWedges]; WORD (*fnei)[3] = new WORD [m_maxFaces][3]; GLface *farray = new GLface [m_maxFaces]; if (!farray || !varray || !narray || !tarray || !wedgelist || !fnei) { return E_OUTOFMEMORY; } else { m_varray = varray; m_narray = narray; m_tarray = tarray; m_farray = farray; m_wedgelist = wedgelist; m_fnei = fnei; } #endif /* * Read face-texture curve */ read_WORD(is, ftCurveSize); // Size of face-texture curve #ifdef __DUMP_DATA dump << "\n\nFace-texture curve:"; dump << "\nFT-curve size: " << ftCurveSize; #endif //__DUMP_DATA ftcurves = new CURVE[m_maxTextures]; // A curve for each texture DWORD* ftmax = new DWORD[m_maxTextures]; if (!ftcurves || !ftmax) return E_OUTOFMEMORY; for (k=0; k maxVert) { m_texcnt[k] = WORD(ftcurves[k][i-1].y + (maxVert - ftcurves[k][i-1].x) * (ftcurves[k][i].y - ftcurves[k][i-1].y) / (ftcurves[k][i].x - ftcurves[k][i-1].x)); m_texcnt[k] = WORD(min(m_texcnt[k], ftmax[k])); break; } } nFacePredict += m_texcnt[k]; delete [] ftcurves[k]; } delete [] ftcurves; delete [] ftmax; /* * Convert m_texcnt to array of offsets into the prim buf where faces of * that texture need to be stored. */ m_texpos[0] = 0; for (i=1; i maxVert) { matcnt[k] = WORD(fmcurves[k][i-1].y + (maxVert - fmcurves[k][i-1].x) * (fmcurves[k][i].y - fmcurves[k][i-1].y) / (fmcurves[k][i].x - fmcurves[k][i-1].x)); matcnt[k] = WORD(min(matcnt[k], fmmax[k])); break; } } nFacePredict += matcnt[k]; delete [] fmcurves[k]; } delete [] fmcurves; delete [] fmmax; #else //__MAT_PREALLOC_OPTIMIZATION /* * Convert m_matcnt to array of offsets into the face buf where faces of * that material need to be stored. */ #ifdef __MATPOS_IS_A_PTR matpos[0] = farray; int cnt = 0; for (i=1; i= m_baseVertices) return -1; #endif if (vidx_arr[vidx] < 0) { /* * New vertex, create entry and initialize the wedge list */ vidx_arr[vidx] = i; wedgelist[i] = WORD(i); // create circular list with one entry } else { /* * Another wedge uses existing vertex, add new wedge to the * existing wedge list. */ wedgelist[i] = wedgelist[vidx_arr[vidx]]; wedgelist[vidx_arr[vidx]] = WORD(i); } read_float(is, narray[i].x); read_float(is, narray[i].y); read_float(is, narray[i].z); read_float(is, tarray[i].s); read_float(is, tarray[i].t); } /* * Read base-mesh vertices */ if (vOffset) skip_bytes(is, vOffset); for (i=0; ielem(i + m_baseVertices - minVert).read(is); } } #ifdef __DUMP_DATA m_vsarr->write(dump); #endif //__DUMP_DATA m_currPos = 0; return S_OK; }