LIB3MFMETHODIMP CCOMModelTexture2D::WriteToCallback(_In_ void * pWriteCallback, _In_opt_ void * pUserData)
	{
		try {
			if (pWriteCallback == nullptr)
				throw CNMRException(NMR_ERROR_INVALIDPOINTER);

			CModelTexture2DResource * pTextureResource = getTexture2D();
			__NMRASSERT(pTextureResource);

			PImportStream pTextureAttachment = pTextureResource->getTextureStream();
			ExportStream_WriteCallbackType pTypedWriteCallback = (ExportStream_WriteCallbackType)pWriteCallback;

			if (pTextureAttachment.get() != nullptr) {
				PExportStream pExportStream = std::make_shared<CExportStream_Callback>(pTypedWriteCallback, nullptr, pUserData);
				pExportStream->copyFrom(pTextureAttachment.get(), pTextureAttachment->retrieveSize(), MODELTEXTURE2D_BUFFERSIZE);
			}
			else {
				throw CNMRException(NMR_ERROR_NOTEXTURESTREAM);
			}

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

	}
	void CModelWriter_3MF_Native::addAttachments(_In_ CModel * pModel, _In_ POpcPackageWriter pPackageWriter, _In_ POpcPackagePart pModelPart)
	{
		__NMRASSERT(pModel != nullptr);
		__NMRASSERT(pModelPart.get() != nullptr);
		__NMRASSERT(pPackageWriter.get() != nullptr);

		nfUint32 nCount = pModel->getAttachmentCount();
		nfUint32 nIndex;

		if (nCount > 0) {
			for (nIndex = 0; nIndex < nCount; nIndex++) {
				PModelAttachment pAttachment = pModel->getModelAttachment(nIndex);
				PImportStream pStream = pAttachment->getStream();
				
				std::wstring sPath = fnIncludeLeadingPathDelimiter(pAttachment->getPathURI());
				std::wstring sRelationShipType = pAttachment->getRelationShipType();

				if (pStream.get() == nullptr)
					throw CNMRException(NMR_ERROR_INVALIDPARAM);

				// create Texture Part
				POpcPackagePart pAttachmentPart = pPackageWriter->addPart(sPath);
				PExportStream pExportStream = pAttachmentPart->getExportStream();

				// Copy data
				pStream->seekPosition(0, true);
				pExportStream->copyFrom(pStream.get(), pStream->retrieveSize(), MODELWRITER_NATIVE_BUFFERSIZE);

				// add relationships
				pModelPart->addRelationship(generateRelationShipID(), sRelationShipType.c_str(), pAttachmentPart->getURI());
			}
		}
	}
	void CModelWriter_3MF_Native::addTextureParts(_In_ CModel * pModel, _In_ POpcPackageWriter pPackageWriter, _In_ POpcPackagePart pModelPart)
	{
		__NMRASSERT(pModel != nullptr);
		__NMRASSERT(pModelPart.get() != nullptr);
		__NMRASSERT(pPackageWriter.get() != nullptr);

		nfUint32 nCount = pModel->getTextureStreamCount();
		nfUint32 nIndex;

		if (nCount > 0) {


			for (nIndex = 0; nIndex < nCount; nIndex++) {
				PImportStream pStream = pModel->getTextureStream(nIndex);
				std::wstring sPath = fnIncludeLeadingPathDelimiter (pModel->getTextureStreamPath(nIndex));

				if (pStream.get() == nullptr)
					throw CNMRException(NMR_ERROR_INVALIDPARAM);

				// create Texture Part
				POpcPackagePart pTexturePart = pPackageWriter->addPart(sPath);
				PExportStream pExportStream = pTexturePart->getExportStream();

				// Copy data
				pStream->seekPosition(0, true);
				pExportStream->copyFrom(pStream.get(), pStream->retrieveSize(), MODELWRITER_NATIVE_BUFFERSIZE);

				// add relationships
				pModelPart->addRelationship(generateRelationShipID(), PACKAGE_TEXTURE_RELATIONSHIP_TYPE, pTexturePart.get());

			}
		}
	}
	void CModelWriter_3MF_Native::writePackageToStream(_In_ PExportStream pStream)
	{
		if (pStream.get() == nullptr)
			throw CNMRException(NMR_ERROR_INVALIDPARAM);
		if (m_pModel == nullptr)
			throw CNMRException(NMR_ERROR_NOMODELTOWRITE);

		// Write Model Stream
		POpcPackageWriter pPackageWriter = std::make_shared<COpcPackageWriter>(pStream);
		POpcPackagePart pModelPart = pPackageWriter->addPart(PACKAGE_3D_MODEL_URI);
		PXmlWriter_Native pXMLWriter = std::make_shared<CXmlWriter_Native>(pModelPart->getExportStream());
		writeModelStream(pXMLWriter.get(), m_pModel);

		// add Root relationships
		pPackageWriter->addRootRelationship(generateRelationShipID(), PACKAGE_START_PART_RELATIONSHIP_TYPE, pModelPart.get());

		PModelAttachment pPackageThumbnail = m_pModel->getPackageThumbnail();
		if (pPackageThumbnail.get() != nullptr)
		{
			// create Package Thumbnail Part
			POpcPackagePart pThumbnailPart = pPackageWriter->addPart(pPackageThumbnail->getPathURI());
			PExportStream pExportStream = pThumbnailPart->getExportStream();
			// Copy data
			PImportStream pPackageThumbnailStream = pPackageThumbnail->getStream();
			pPackageThumbnailStream->seekPosition(0, true);
			pExportStream->copyFrom(pPackageThumbnailStream.get(), pPackageThumbnailStream->retrieveSize(), MODELWRITER_NATIVE_BUFFERSIZE);
			// add root relationship
			pPackageWriter->addRootRelationship(generateRelationShipID(), pPackageThumbnail->getRelationShipType(), pThumbnailPart.get());
		}

		// add slicestacks that reference other files
		addSlicerefAttachments(m_pModel);
		
		// add Attachments
		addAttachments(m_pModel, pPackageWriter, pModelPart);

		// add Content Types
		pPackageWriter->addContentType(PACKAGE_3D_RELS_EXTENSION, PACKAGE_3D_RELS_CONTENT_TYPE);
		pPackageWriter->addContentType(PACKAGE_3D_MODEL_EXTENSION, PACKAGE_3D_MODEL_CONTENT_TYPE);
		pPackageWriter->addContentType(PACKAGE_3D_TEXTURE_EXTENSION, PACKAGE_TEXTURE_CONTENT_TYPE);
		pPackageWriter->addContentType(PACKAGE_3D_PNG_EXTENSION, PACKAGE_PNG_CONTENT_TYPE);
		pPackageWriter->addContentType(PACKAGE_3D_JPEG_EXTENSION, PACKAGE_JPG_CONTENT_TYPE);
		pPackageWriter->addContentType(PACKAGE_3D_JPG_EXTENSION, PACKAGE_JPG_CONTENT_TYPE);

		std::map<std::wstring, std::wstring> CustomContentTypes = m_pModel->getCustomContentTypes();
		std::map<std::wstring, std::wstring>::iterator iContentTypeIterator;

		for (iContentTypeIterator = CustomContentTypes.begin(); iContentTypeIterator != CustomContentTypes.end(); iContentTypeIterator++) {
			if (!m_pModel->contentTypeIsDefault(iContentTypeIterator->first)) {
				pPackageWriter->addContentType(iContentTypeIterator->first, iContentTypeIterator->second);
			}
		}

			
	}