LIB3MFMETHODIMP CCOMModelMeshObject::SetGeometry(_In_ MODELMESHVERTEX * pVertices, _In_ DWORD nVertexCount, _In_ MODELMESHTRIANGLE * pTriangles, _In_ DWORD nTriangleCount)
	{
		UINT j, nIndex;


		try {
			if ((!pVertices) || (!pTriangles))
				throw CNMRException(NMR_ERROR_INVALIDPOINTER);

			CMesh * pMesh = getMesh();
			__NMRASSERT(pMesh);

			// Clear old mesh
			pMesh->clear();

			// Rebuild Mesh Coordinates
			MODELMESHVERTEX * pVertex = pVertices;
			for (nIndex = 0; nIndex < nVertexCount; nIndex++) {
				NVEC3 vPosition;
				for (j = 0; j < 3; j++) {
					FLOAT fCoord = pVertex->m_fPosition[j];
					if (fabs(fCoord) > NMR_MESH_MAXCOORDINATE)
						throw CNMRException_Windows(NMR_ERROR_INVALIDCOORDINATES, LIB3MF_INVALIDARG);
					vPosition.m_fields[j] = fCoord;
				}
				pMesh->addNode(vPosition);

				pVertex++;
			}

			// Rebuild Mesh Faces
			MODELMESHTRIANGLE * pTriangle = pTriangles;
			for (nIndex = 0; nIndex < nTriangleCount; nIndex++) {
				MESHNODE * pNodes[3];

				for (j = 0; j < 3; j++) {
					if (pTriangle->m_nIndices[j] >= nVertexCount)
						throw CNMRException_Windows(NMR_ERROR_INVALIDINDEX, LIB3MF_INVALIDARG);
					pNodes[j] = pMesh->getNode(pTriangle->m_nIndices[j]);
				}

				if ((pTriangle->m_nIndices[0] == pTriangle->m_nIndices[1]) ||
					(pTriangle->m_nIndices[0] == pTriangle->m_nIndices[2]) ||
					(pTriangle->m_nIndices[1] == pTriangle->m_nIndices[2]))
					throw CNMRException_Windows(NMR_ERROR_INVALIDINDEX, LIB3MF_INVALIDARG);

				pMesh->addFace(pNodes[0], pNodes[1], pNodes[2]);

				pTriangle++;
			}

			return handleSuccess();
		}
		catch (CNMRException & Exception) {
			return handleNMRException(&Exception);
		}
		catch (...) {
			return handleGenericException();
		}
	}
	LIB3MFMETHODIMP CCOMModelMeshObject::SetVertex(_In_ DWORD nIndex, _In_ MODELMESHVERTEX * pVertex)
	{
		UINT j;


		try {
			if (!pVertex)
				throw CNMRException(NMR_ERROR_INVALIDPOINTER);

			CMesh * pMesh = getMesh();
			__NMRASSERT(pMesh);

			// Create Position Vector and check input
			NVEC3 vPosition;
			for (j = 0; j < 3; j++) {
				FLOAT fCoord = pVertex->m_fPosition[j];
				if (fabs(fCoord) > NMR_MESH_MAXCOORDINATE)
					throw CNMRException_Windows(NMR_ERROR_INVALIDCOORDINATES, LIB3MF_INVALIDARG);
				vPosition.m_fields[j] = fCoord;
			}

			// Set position to node
			MESHNODE * pNode = pMesh->getNode(nIndex);
			pNode->m_position = vPosition;

			return handleSuccess();
		}
		catch (CNMRException & Exception) {
			return handleNMRException(&Exception);
		}
		catch (...) {
			return handleGenericException();
		}
	}
	LIB3MFMETHODIMP CCOMModelMeshObject::GetVertex(_In_ DWORD nIndex, _Out_ MODELMESHVERTEX * pVertex)
	{
		UINT j;

		try {
			if (!pVertex)
				throw CNMRException(NMR_ERROR_INVALIDPOINTER);

			CMesh * pMesh = getMesh();
			__NMRASSERT(pMesh);

			// retrieve node and return position
			MESHNODE * pNode = pMesh->getNode(nIndex);
			for (j = 0; j < 3; j++)
				pVertex->m_fPosition[j] = pNode->m_position.m_fields[j];

			return handleSuccess();
		}
		catch (CNMRException & Exception) {
			return handleNMRException(&Exception);
		}
		catch (...) {
			return handleGenericException();
		}
	}
	LIB3MFMETHODIMP CCOMModelMeshObject::AddTriangle(_In_ MODELMESHTRIANGLE * pTriangle, _Out_opt_ DWORD * pnIndex)
	{
		UINT j;

		try {
			if (!pTriangle)
				throw CNMRException(NMR_ERROR_INVALIDPOINTER);

			CMesh * pMesh = getMesh();
			__NMRASSERT(pMesh);

			// Check for input validity
			UINT nNodeCount = pMesh->getNodeCount();
			for (j = 0; j < 3; j++)
				if (pTriangle->m_nIndices[j] >= nNodeCount)
					throw CNMRException_Windows(NMR_ERROR_INVALIDINDEX, LIB3MF_INVALIDARG);
			if ((pTriangle->m_nIndices[0] == pTriangle->m_nIndices[1]) ||
				(pTriangle->m_nIndices[0] == pTriangle->m_nIndices[2]) ||
				(pTriangle->m_nIndices[1] == pTriangle->m_nIndices[2]))
				throw CNMRException_Windows(NMR_ERROR_INVALIDINDEX, LIB3MF_INVALIDARG);

			MESHNODE * pNodes[3];
			for (j = 0; j < 3; j++)
				pNodes[j] = pMesh->getNode(pTriangle->m_nIndices[j]);

			// retrieve node and return position
			MESHFACE * pFace = pMesh->addFace(pNodes[0], pNodes[1], pNodes[2]);
			if (pnIndex) {
				*pnIndex = pFace->m_index;
			}

			return handleSuccess();
		}
		catch (CNMRException & Exception) {
			return handleNMRException(&Exception);
		}
		catch (...) {
			return handleGenericException();
		}
	}
	LIB3MFMETHODIMP CCOMModelMeshObject::GetVertices(_Out_ MODELMESHVERTEX * pVertices, _In_ DWORD nBufferSize, _Out_opt_ DWORD * pnVertexCount)
	{
		UINT j, nIndex;

		try {
			if (!pVertices)
				throw CNMRException(NMR_ERROR_INVALIDPOINTER);

			CMesh * pMesh = getMesh();
			__NMRASSERT(pMesh);

			// Check Buffer size
			UINT nNodeCount = pMesh->getNodeCount();
			if (pnVertexCount)
				*pnVertexCount = nNodeCount;

			if (nBufferSize < nNodeCount)
				throw CNMRException(NMR_ERROR_INVALIDBUFFERSIZE);

			MODELMESHVERTEX * pVertex = pVertices;
			for (nIndex = 0; nIndex < nNodeCount; nIndex++) {
				// retrieve node and return position
				MESHNODE * pNode = pMesh->getNode(nIndex);
				for (j = 0; j < 3; j++)
					pVertex->m_fPosition[j] = pNode->m_position.m_fields[j];
				pVertex++;
			}

			return handleSuccess();
		}
		catch (CNMRException & Exception) {
			return handleNMRException(&Exception);
		}
		catch (...) {
			return handleGenericException();
		}
	}