Beispiel #1
0
void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {

    this->mScene = pScene;

    // read the asset file
    glTF2::Asset asset(pIOHandler);
    asset.Load(pFile, GetExtension(pFile) == "glb");

    //
    // Copy the data out
    //

    ImportEmbeddedTextures(asset);
    ImportMaterials(asset);

    ImportMeshes(asset);

    ImportCameras(asset);

    ImportNodes(asset);

    // TODO: it does not split the loaded vertices, should it?
    //pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
    MakeVerboseFormatProcess process;
    process.Execute(pScene);


    if (pScene->mNumMeshes == 0) {
        pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
    }
}
Beispiel #2
0
// ------------------------------------------------------------------------------------------------
aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing )
{
	ASSIMP_BEGIN_EXCEPTION_REGION();

	pimpl->mError = "";
	for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
		const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
		if (!strcmp(exp.mDescription.id,pFormatId)) {

			try {

				// Always create a full copy of the scene. We might optimize this one day, 
				// but for now it is the most pragmatic way.
				aiScene* scenecopy_tmp;
				SceneCombiner::CopyScene(&scenecopy_tmp,pScene);

				std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
				const ScenePrivateData* const priv = ScenePriv(pScene);

				// steps that are not idempotent, i.e. we might need to run them again, usually to get back to the
				// original state before the step was applied first. When checking which steps we don't need
				// to run, those are excluded.
				const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;

				// Erase all pp steps that were already applied to this scene
				unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv 
					? (priv->mPPStepsApplied & ~nonIdempotentSteps)
					: 0u);

				// If no extra postprocessing was specified, and we obtained this scene from an
				// Assimp importer, apply the reverse steps automatically.
				if (!pPreprocessing && priv) {
					pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
				}

				// If the input scene is not in verbose format, but there is at least postprocessing step that relies on it,
				// we need to run the MakeVerboseFormat step first.
				if (scenecopy->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
					
					bool verbosify = false;
					for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
						BaseProcess* const p = pimpl->mPostProcessingSteps[a];

						if (p->IsActive(pp) && p->RequireVerboseFormat()) {
							verbosify = true;
							break;
						}
					}

					if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
						DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");

						MakeVerboseFormatProcess proc;
						proc.Execute(scenecopy.get());
					}
				}

				if (pp) {
					// the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout
					{
						FlipWindingOrderProcess step;
						if (step.IsActive(pp)) {
							step.Execute(scenecopy.get());
						}
					}
					
					{
						FlipUVsProcess step;
						if (step.IsActive(pp)) {
							step.Execute(scenecopy.get());
						}
					}

					{
						MakeLeftHandedProcess step;
						if (step.IsActive(pp)) {
							step.Execute(scenecopy.get());
						}
					}

					// dispatch other processes
					for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
						BaseProcess* const p = pimpl->mPostProcessingSteps[a];

						if (p->IsActive(pp) 
							&& !dynamic_cast<FlipUVsProcess*>(p) 
							&& !dynamic_cast<FlipWindingOrderProcess*>(p) 
							&& !dynamic_cast<MakeLeftHandedProcess*>(p)) {

							p->Execute(scenecopy.get());
						}
					}
					ScenePrivateData* const privOut = ScenePriv(scenecopy.get());
					ai_assert(privOut);

					privOut->mPPStepsApplied |= pp;
				}

				exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
			}
			catch (DeadlyExportError& err) {
				pimpl->mError = err.what();
				return AI_FAILURE;
			}
			return AI_SUCCESS;
		}
	}

	pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
	ASSIMP_END_EXCEPTION_REGION(aiReturn);
	return AI_FAILURE;
}
//-------------------------------------------------------------------------------
// Set the normal set of the scene
//-------------------------------------------------------------------------------
void AssetHelper::SetNormalSet(unsigned int iSet)
{
	// we need to build an unique set of vertices for this ...
	{
		MakeVerboseFormatProcess* pcProcess = new MakeVerboseFormatProcess();
		pcProcess->Execute(pcScene);
		delete pcProcess;

		for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
		{
			if (!apcMeshes[i]->pvOriginalNormals)
			{
				apcMeshes[i]->pvOriginalNormals = new aiVector3D[pcScene->mMeshes[i]->mNumVertices];
				memcpy( apcMeshes[i]->pvOriginalNormals,pcScene->mMeshes[i]->mNormals,
					pcScene->mMeshes[i]->mNumVertices * sizeof(aiVector3D));
			}
			delete[] pcScene->mMeshes[i]->mNormals;
			pcScene->mMeshes[i]->mNormals = NULL;
		}
	}


	// now we can start to calculate a new set of normals
	if (HARD == iSet)
	{
		GenFaceNormalsProcess* pcProcess = new GenFaceNormalsProcess();
		pcProcess->Execute(pcScene);
		FlipNormalsInt();
		delete pcProcess;
	}
	else if (SMOOTH == iSet)
	{
		GenVertexNormalsProcess* pcProcess = new GenVertexNormalsProcess();
		pcProcess->SetMaxSmoothAngle((float)AI_DEG_TO_RAD(g_smoothAngle));
		pcProcess->Execute(pcScene);
		FlipNormalsInt();
		delete pcProcess;
	}
	else if (ORIGINAL == iSet)
	{
		for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
		{
			if (apcMeshes[i]->pvOriginalNormals)
			{
				delete[] pcScene->mMeshes[i]->mNormals;
				pcScene->mMeshes[i]->mNormals = apcMeshes[i]->pvOriginalNormals;
				apcMeshes[i]->pvOriginalNormals = NULL;
			}
		}
	}

	// recalculate tangents and bitangents
	Assimp::BaseProcess* pcProcess = new CalcTangentsProcess();
	pcProcess->Execute(pcScene);
	delete pcProcess;

	// join the mesh vertices again
	pcProcess = new JoinVerticesProcess();
	pcProcess->Execute(pcScene);
	delete pcProcess;

	iNormalSet = iSet;

	if (g_bWasFlipped)
	{
		// invert all normal vectors
		for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
		{
			aiMesh* pcMesh = pcScene->mMeshes[i];
			for (unsigned int a = 0; a < pcMesh->mNumVertices;++a)
			{
				pcMesh->mNormals[a] *= -1.0f;
			}
		}
	}

	// recreate native data
	DeleteAssetData(true);
	CreateAssetData();
	return;
}
Beispiel #4
0
// ------------------------------------------------------------------------------------------------
aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
        unsigned int pPreprocessing, const ExportProperties* pProperties) {
    ASSIMP_BEGIN_EXCEPTION_REGION();

    // when they create scenes from scratch, users will likely create them not in verbose
    // format. They will likely not be aware that there is a flag in the scene to indicate
    // this, however. To avoid surprises and bug reports, we check for duplicates in
    // meshes upfront.
    const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);

    pimpl->mProgressHandler->UpdateFileWrite(0, 4);

    pimpl->mError = "";
    for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
        const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
        if (!strcmp(exp.mDescription.id,pFormatId)) {
            try {
                // Always create a full copy of the scene. We might optimize this one day,
                // but for now it is the most pragmatic way.
                aiScene* scenecopy_tmp = nullptr;
                SceneCombiner::CopyScene(&scenecopy_tmp,pScene);

                pimpl->mProgressHandler->UpdateFileWrite(1, 4);

                std::unique_ptr<aiScene> scenecopy(scenecopy_tmp);
                const ScenePrivateData* const priv = ScenePriv(pScene);

                // steps that are not idempotent, i.e. we might need to run them again, usually to get back to the
                // original state before the step was applied first. When checking which steps we don't need
                // to run, those are excluded.
                const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;

                // Erase all pp steps that were already applied to this scene
                const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy
                    ? (priv->mPPStepsApplied & ~nonIdempotentSteps)
                    : 0u);

                // If no extra post-processing was specified, and we obtained this scene from an
                // Assimp importer, apply the reverse steps automatically.
                // TODO: either drop this, or document it. Otherwise it is just a bad surprise.
                //if (!pPreprocessing && priv) {
                //  pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
                //}

                // If the input scene is not in verbose format, but there is at least post-processing step that relies on it,
                // we need to run the MakeVerboseFormat step first.
                bool must_join_again = false;
                if (!is_verbose_format) {
                    bool verbosify = false;
                    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
                        BaseProcess* const p = pimpl->mPostProcessingSteps[a];

                        if (p->IsActive(pp) && p->RequireVerboseFormat()) {
                            verbosify = true;
                            break;
                        }
                    }

                    if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
                        ASSIMP_LOG_DEBUG("export: Scene data not in verbose format, applying MakeVerboseFormat step first");

                        MakeVerboseFormatProcess proc;
                        proc.Execute(scenecopy.get());

                        if(!(exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
                            must_join_again = true;
                        }
                    }
                }

                pimpl->mProgressHandler->UpdateFileWrite(2, 4);

                if (pp) {
                    // the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout
                    {
                        FlipWindingOrderProcess step;
                        if (step.IsActive(pp)) {
                            step.Execute(scenecopy.get());
                        }
                    }

                    {
                        FlipUVsProcess step;
                        if (step.IsActive(pp)) {
                            step.Execute(scenecopy.get());
                        }
                    }

                    {
                        MakeLeftHandedProcess step;
                        if (step.IsActive(pp)) {
                            step.Execute(scenecopy.get());
                        }
                    }

                    bool exportPointCloud(false);
                    if (nullptr != pProperties) {
                        exportPointCloud = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
                    }

                    // dispatch other processes
                    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
                        BaseProcess* const p = pimpl->mPostProcessingSteps[a];

                        if (p->IsActive(pp)
                            && !dynamic_cast<FlipUVsProcess*>(p)
                            && !dynamic_cast<FlipWindingOrderProcess*>(p)
                            && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
                            if (dynamic_cast<PretransformVertices*>(p) && exportPointCloud) {
                                continue;
                            }
                            p->Execute(scenecopy.get());
                        }
                    }
                    ScenePrivateData* const privOut = ScenePriv(scenecopy.get());
                    ai_assert(nullptr != privOut);

                    privOut->mPPStepsApplied |= pp;
                }

                pimpl->mProgressHandler->UpdateFileWrite(3, 4);

                if(must_join_again) {
                    JoinVerticesProcess proc;
                    proc.Execute(scenecopy.get());
                }

                ExportProperties emptyProperties;  // Never pass NULL ExportProperties so Exporters don't have to worry.
                exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties);

                pimpl->mProgressHandler->UpdateFileWrite(4, 4);
            } catch (DeadlyExportError& err) {
                pimpl->mError = err.what();
                return AI_FAILURE;
            }
            return AI_SUCCESS;
        }
    }

    pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
    ASSIMP_END_EXCEPTION_REGION(aiReturn);

    return AI_FAILURE;
}