TEST_F(utObjImportExport, homogeneous_coordinates_divide_by_zero_Test) {
  static const std::string ObjModel =
    "v -0.500000 0.000000 0.400000 0.\n"
    "v -0.500000 0.000000 -0.800000 1.00000\n"
    "v 0.500000 1.000000 -0.800000 0.5000\n"
    "f 1 2 3\nB";

  Assimp::Importer myimporter;
  const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure);
  EXPECT_EQ(nullptr, scene);
}
Exemple #2
0
bool KeOpenSceneFromMemory( void* ptr, uint32_t size )
{
    /* Import this mesh from disk */
    scene = importer.ReadFileFromMemory( ptr, size, aiProcessPreset_TargetRealtime_MaxQuality );
    if( !scene )
	{
		DISPDBG( KE_ERROR, "Error reading mesh file!\nReason: " << importer.GetErrorString() );
        return false;
	}
    
    return true;
}
Exemple #3
0
CParaXModel* FBXParser::ParseParaXModel(const char* buffer, int nSize)
{
	CParaXModel* pMesh = NULL;
	Assimp::Importer importer;
	Reset();
	SetAnimSplitterFilename();
	// aiProcess_MakeLeftHanded | 
	const aiScene* pFbxScene = importer.ReadFileFromMemory(buffer, nSize, aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs, "fbx");
	if (pFbxScene) {
		ParaXHeaderDef m_xheader;
		m_xheader.IsAnimated = pFbxScene->HasAnimations() ? 1 : 0;
		pMesh = new CParaXModel(m_xheader);

		if (pFbxScene->HasMaterials())
		{
			int materials_num = pFbxScene->mNumMaterials;
			for (int i = 0; i < materials_num; i++)
			{
				ProcessFBXMaterial(pFbxScene, i, pMesh);
			}
		}
		// get root node
		//m_nRootNodeIndex = CreateGetBoneIndex(pFbxScene->mRootNode->mName.C_Str());

		// must be called before ProcessFBXBoneNodes
		if (pFbxScene->HasAnimations())
		{
			int animations_num = pFbxScene->mNumAnimations;
			for (int i = 0; i < animations_num; i++)
			{
				ProcessFBXAnimation(pFbxScene, i, pMesh);
			}
		}

		// building the parent-child relationship of the bones, and add meshes if any;
		ProcessFBXBoneNodes(pFbxScene, pFbxScene->mRootNode, -1, pMesh);

		// MakeAxisY_UP();

		FillParaXModelData(pMesh, pFbxScene);

		PostProcessParaXModelData(pMesh);

#ifdef _DEBUG
		//PrintDebug(pFbxScene);
#endif
	}
	else {
		OUTPUT_LOG("Error parsing '%s': '%s'\n", m_sFilename.c_str(), importer.GetErrorString());
	}
	return pMesh;
}
TEST_F( utObjImportExport, issue1453_segfault ) {
    static const std::string ObjModel =
        "v  0.0  0.0  0.0\n"
        "v  0.0  0.0  1.0\n"
        "v  0.0  1.0  0.0\n"
        "v  0.0  1.0  1.0\n"
        "v  1.0  0.0  0.0\n"
        "v  1.0  0.0  1.0\n"
        "v  1.0  1.0  0.0\n"
        "v  1.0  1.0  1.0\nB";

    Assimp::Importer myimporter;
    const aiScene *scene = myimporter.ReadFileFromMemory( ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure );
    EXPECT_EQ( nullptr, scene );
}
Mesh* createMeshFromResource(const std::string& resource, const Eigen::Vector3d &scale)
{
  resource_retriever::Retriever retriever;
  resource_retriever::MemoryResource res;
  try
  {
    res = retriever.get(resource);
  } 
  catch (resource_retriever::Exception& e)
  {
    ROS_ERROR("%s", e.what());
    return NULL;
  }

  if (res.size == 0)
  {
    ROS_WARN("Retrieved empty mesh for resource '%s'", resource.c_str());
    return NULL;
  }
  
  // Create an instance of the Importer class
  Assimp::Importer importer;
  
  // try to get a file extension
  std::string hint;
  std::size_t pos = resource.find_last_of(".");
  if (pos != std::string::npos)
  {
    hint = resource.substr(pos + 1);
    std::transform(hint.begin(), hint.end(), hint.begin(), ::tolower);
    if (hint.find("stl") != std::string::npos)
      hint = "stl";
  }
  
  // And have it read the given file with some postprocessing
  const aiScene* scene = importer.ReadFileFromMemory(reinterpret_cast<void*>(res.data.get()), res.size,
                                                     aiProcess_Triangulate            |
                                                     aiProcess_JoinIdenticalVertices  |
                                                     aiProcess_SortByPType            |
                                                     aiProcess_OptimizeGraph          |
                                                     aiProcess_OptimizeMeshes, hint.c_str());
  if (!scene)
  {
    ROS_WARN_STREAM("Assimp reports no scene in " << resource);
    return NULL;
  }
  return createMeshFromAsset(scene, scale, resource);
}
Exemple #6
0
	void _loadModel( const char * xPath )
	{
		std::string path( xPath );

		Assimp::Importer importer;

#if 0
        	const aiScene* scene = importer.ReadFile(path
							, aiProcess_Triangulate      |
							  aiProcess_FlipUVs          |
							  aiProcess_CalcTangentSpace |
							  aiProcess_GenNormals       |
                                                          aiProcess_SplitLargeMeshes |
							  aiProcess_OptimizeMeshes );


#else
		size_t out;

		char * buffer = fileToBuffer( xPath, &out );

        	const aiScene* scene = importer.ReadFileFromMemory( buffer
								  , out
								  , aiProcess_Triangulate      |
	 							    aiProcess_FlipUVs          |
	 							    aiProcess_CalcTangentSpace |
								    aiProcess_GenNormals       |
	                                                            aiProcess_SplitLargeMeshes |
		  						    aiProcess_OptimizeMeshes
								  , "" );

		free ( buffer );
#endif


 	       // Check for errors
	        if(!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero
	        {
        	    std::cerr << "ERROR::ASSIMP:: " << importer.GetErrorString() << std::endl;
	            return;
	        }
	        // Retrieve the directory path of the filepath
        	mDirectory = path.substr(0, path.find_last_of('/'));

	        // Process ASSIMP's root node recursively
       		_processNode(scene->mRootNode, scene);
	}
	/** 
	* Load a scene from a supported 3D file format
	*
	* @param filename Name of the file (or asset) to load
	* @param flags (Optional) Set of ASSIMP processing flags
	*
	* @return Returns true if the scene has been loaded
	*/
	bool LoadMesh(const std::string& filename, int flags = defaultFlags)
	{
#if defined(__ANDROID__)
		// Meshes are stored inside the apk on Android (compressed)
		// So they need to be loaded via the asset manager

		AAsset* asset = AAssetManager_open(assetManager, filename.c_str(), AASSET_MODE_STREAMING);
		assert(asset);
		size_t size = AAsset_getLength(asset);

		assert(size > 0);
		
		void *meshData = malloc(size);
		AAsset_read(asset, meshData, size);
		AAsset_close(asset);

		pScene = Importer.ReadFileFromMemory(meshData, size, flags);

		free(meshData);
#else
		pScene = Importer.ReadFile(filename.c_str(), flags);
#endif

		if (pScene)
		{
			m_Entries.clear();
			m_Entries.resize(pScene->mNumMeshes);
			// Read in all meshes in the scene
			for (auto i = 0; i < m_Entries.size(); i++)
			{
				m_Entries[i].vertexBase = numVertices;
				numVertices += pScene->mMeshes[i]->mNumVertices;
				const aiMesh* paiMesh = pScene->mMeshes[i];
				InitMesh(&m_Entries[i], paiMesh, pScene);
			}
			return true;
		}
		else 
		{
			printf("Error parsing '%s': '%s'\n", filename.c_str(), Importer.GetErrorString());
#if defined(__ANDROID__)
			LOGE("Error parsing '%s': '%s'", filename.c_str(), Importer.GetErrorString());
#endif
			return false;
		}
	}
Exemple #8
0
// ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileFromMemory(
    const char* pBuffer,
    unsigned int pLength,
    unsigned int pFlags,
    const char* pHint)
{
    ai_assert(NULL != pBuffer && 0 != pLength);

    const aiScene* scene = NULL;
    ASSIMP_BEGIN_EXCEPTION_REGION();

    // create an Importer for this file
    Assimp::Importer* imp = new Assimp::Importer();

#ifdef AI_C_THREADSAFE
    boost::mutex::scoped_lock lock(gMutex);
#endif
    // copy the global property lists to the Importer instance
    imp->pimpl->mIntProperties = gIntProperties;
    imp->pimpl->mFloatProperties = gFloatProperties;
    imp->pimpl->mStringProperties = gStringProperties;

#ifdef AI_C_THREADSAFE
    lock.unlock();
#endif

    // and have it read the file from the memory buffer
    scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);

    // if succeeded, place it in the collection of active processes
    if ( scene) {
#ifdef AI_C_THREADSAFE
        lock.lock();
#endif
        gActiveImports[scene] = imp;
    }
    else {
        // if failed, extract error code and destroy the import
        gLastErrorString = imp->GetErrorString();
        delete imp;
    }
    // return imported data. If the import failed the pointer is NULL anyways
    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
    return scene;
}
Exemple #9
0
// ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileFromMemoryWithProperties(
    const char* pBuffer,
    unsigned int pLength,
    unsigned int pFlags,
    const char* pHint,
    const aiPropertyStore* props)
{
    ai_assert( NULL != pBuffer );
    ai_assert( 0 != pLength );

    const aiScene* scene = NULL;
    ASSIMP_BEGIN_EXCEPTION_REGION();

    // create an Importer for this file
    Assimp::Importer* imp = new Assimp::Importer();

    // copy properties
    if(props) {
        const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
        ImporterPimpl* pimpl = imp->Pimpl();
        pimpl->mIntProperties = pp->ints;
        pimpl->mFloatProperties = pp->floats;
        pimpl->mStringProperties = pp->strings;
        pimpl->mMatrixProperties = pp->matrices;
    }

    // and have it read the file from the memory buffer
    scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);

    // if succeeded, store the importer in the scene and keep it alive
    if( scene)  {
         ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
         priv->mOrigImporter = imp;
    }
    else    {
        // if failed, extract error code and destroy the import
        gLastErrorString = imp->GetErrorString();
        delete imp;
    }
    // return imported data. If the import failed the pointer is NULL anyways
    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
    return scene;
}
Exemple #10
0
XFile::Scene* ParaEngine::FBXParser::ParseFBXFile(const char* buffer, int nSize)
{
	Assimp::Importer importer;
	Reset();
	const aiScene* pFbxScene = importer.ReadFileFromMemory(buffer, nSize, aiProcess_Triangulate | aiProcess_GenSmoothNormals, "fbx");
	if (pFbxScene) {
		if (pFbxScene->HasMeshes())
		{
			m_pScene = new Scene;
			int numMeshes = pFbxScene->mNumMeshes;
			for (int i = 0; i < numMeshes; i++)
			{
				Mesh* mesh = new Mesh;
				aiMesh* test = pFbxScene->mMeshes[i];
				int numVertices = (pFbxScene->mMeshes[i])->mNumVertices;
				ProcessStaticFBXMesh(pFbxScene->mMeshes[i], mesh);
				m_pScene->mGlobalMeshes.push_back(mesh);

				if (i == 0)
				{
					Vector3 vMin, vMax;
					ParaComputeBoundingBox((Vector3*)(&mesh->mPositions[0]), mesh->mPositions.size(), sizeof(Vector3), &vMin, &vMax);
					m_pScene->m_header.minExtent = vMin;
					m_pScene->m_header.maxExtent = vMax;
				}
			}
			// OUTPUT_LOG("Successful parsing '%s' numMeshes:%d numMaterials:%d\n", m_sFilename.c_str(), numMeshes, pFbxScene->mNumMaterials);
		}
		if (pFbxScene->HasMaterials())
		{
			int materials_num = pFbxScene->mNumMaterials;
			for (int i = 0; i < materials_num; i++)
			{
				ProcessStaticFBXMaterial(pFbxScene, i);
			}
		}
	}
	else {
		OUTPUT_LOG("Error parsing '%s': '%s'\n", m_sFilename.c_str(), importer.GetErrorString());
	}
	return m_pScene;
}
Exemple #11
0
TEST_F(utObjImportExport, homogeneous_coordinates_Test) {
    static const std::string ObjModel =
        "v -0.500000 0.000000 0.400000 0.50000\n"
        "v -0.500000 0.000000 -0.800000 1.00000\n"
        "v 0.500000 1.000000 -0.800000 0.5000\n"
        "f 1 2 3\nB";

    Assimp::Importer myimporter;
    const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure);
    EXPECT_NE(nullptr, scene);

    EXPECT_EQ(scene->mNumMeshes, 1U);
    const aiMesh *mesh = scene->mMeshes[0];
    EXPECT_EQ(mesh->mNumVertices, 3U);
    EXPECT_EQ(mesh->mNumFaces, 1U);
    const aiFace face = mesh->mFaces[0];
    EXPECT_EQ(face.mNumIndices, 3U);
    const aiVector3D vertice = mesh->mVertices[0];
    EXPECT_EQ(vertice.x, -1.0f);
    EXPECT_EQ(vertice.y, 0.0f);
    EXPECT_EQ(vertice.z, 0.8f);
}
Exemple #12
0
TEST_F(utObjImportExport, relative_indices_Test) {
    static const std::string ObjModel =
        "v -0.500000 0.000000 0.400000\n"
        "v -0.500000 0.000000 -0.800000\n"
        "v -0.500000 1.000000 -0.800000\n"
        "v -0.500000 1.000000 0.400000\n"
        "f -4 -3 -2 -1\nB";

    Assimp::Importer myimporter;
    const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure);
    EXPECT_NE(nullptr, scene);

    EXPECT_EQ(scene->mNumMeshes, 1U);
    const aiMesh *mesh = scene->mMeshes[0];
    EXPECT_EQ(mesh->mNumVertices, 4U);
    EXPECT_EQ(mesh->mNumFaces, 1U);
    const aiFace face = mesh->mFaces[0];
    EXPECT_EQ(face.mNumIndices, 4U);
    for (unsigned int i = 0; i < face.mNumIndices; ++i)
    {
        EXPECT_EQ(face.mIndices[i], i);
    }

}
Mesh* createMeshFromBinary(const char *buffer, std::size_t size, const Eigen::Vector3d &scale,
                           const std::string &assimp_hint)
{
  if (!buffer || size < 1)
  {
    logWarn("Cannot construct mesh from empty binary buffer");
    return NULL;
  }
  
  // try to get a file extension
  std::string hint;
  std::size_t pos = assimp_hint.find_last_of(".");
  if (pos != std::string::npos)
  {
    hint = assimp_hint.substr(pos + 1);
    std::transform(hint.begin(), hint.end(), hint.begin(), ::tolower);
    if (hint.find("stl") != std::string::npos)
      hint = "stl";
  }
  
  // Create an instance of the Importer class
  Assimp::Importer importer;
  

  // And have it read the given file with some postprocessing
  const aiScene* scene = importer.ReadFileFromMemory(reinterpret_cast<const void*>(buffer), size,
                                                     aiProcess_Triangulate            |
                                                     aiProcess_JoinIdenticalVertices  |
                                                     aiProcess_SortByPType            |
                                                     aiProcess_OptimizeGraph          |
                                                     aiProcess_OptimizeMeshes, assimp_hint.c_str());
  if (scene)
    return createMeshFromAsset(scene, scale, assimp_hint);
  else
    return NULL;
}
Exemple #14
0
std::shared_ptr<Scene> Scene::loadColladaFromMemory(
    const char *buf, int length, const string& fileName) {
    MeasureDuration importDuration;
    Assimp::Importer importer;
    const aiScene *scene(importer.ReadFileFromMemory(
        buf, length,
        aiProcess_Triangulate |
        aiProcess_JoinIdenticalVertices |
        aiProcess_SortByPType));
    if (!scene) {
        ALOGE("assimp failed to load %s: %s", fileName.c_str(),
            importer.GetErrorString());
        return nullptr;
    }

    if (scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE) {
        ALOGE("%s: incomplete scene data loaded", fileName.c_str());
        return nullptr;
    }
    if (scene->mRootNode == NULL) {
        ALOGE("%s: root node null", fileName.c_str());
        return nullptr;
    }

    shared_ptr<Scene> s(new Scene);
    long long importTime = importDuration.getMilliSeconds();

    DUMP(Log::F_MODEL, "assimp load %s: %u meshes, %u materials, %u animations, %u textures, %u lights, %u cameras",
        fileName.c_str(), scene->mNumMeshes, scene->mNumMaterials, scene->mNumAnimations,
        scene->mNumTextures, scene->mNumLights, scene->mNumCameras);

    MeasureDuration cvtDuration;
    for (int i=0; i<scene->mNumCameras; i++) {
        shared_ptr<Camera> camera(AIAdapter::typeCast(scene->mCameras[i]));
        s->mCameras.push_back(camera);
    }
    for (int i=0; i<scene->mNumLights; i++) {
        shared_ptr<Light> light(AIAdapter::typeCast(scene->mLights[i]));
        s->mLights.push_back(light);
    }
    for (int i=0; i<scene->mNumTextures; i++) {
        shared_ptr<Texture> texture(AIAdapter::typeCast(scene->mTextures[i]));
        s->mTextures.push_back(texture);
    }
    for (int i=0; i<scene->mNumAnimations; i++) {
        shared_ptr<Animation> animation(AIAdapter::typeCast(scene->mAnimations[i]));
        s->mAnimations.push_back(animation);
    }
    for (int i=0; i<scene->mNumMaterials; i++) {
        shared_ptr<Material> material(AIAdapter::typeCast(scene->mMaterials[i]));
        s->mMaterials.push_back(material);
    }
    for (int i=0; i<scene->mNumMeshes; i++) {
        shared_ptr<Mesh> mesh(AIAdapter::typeCast(scene->mMeshes[i]));
        s->mMeshes.push_back(mesh);
        DUMP(Log::F_MODEL,
            "%s: "
            "vtx# %d, indices# %d, face#: %d, bone# %d, "
            "color channel#: %d, tex coord channel#: %d, "
            "normal: %s, {bi}tagent: %s",
            mesh->getName().c_str(),
            mesh->getNumVertices(), mesh->getNumIndices(), mesh->getNumFaces(), mesh->getNumBones(),
            mesh->getNumColorChannels(), mesh->getNumTextureCoordChannels(),
            mesh->hasVertexNormals() ? "true" : "false",
            mesh->hasVertexTangentsAndBitangents() ? "true" : "false");
    }

    AIAdapter::buildSceneGraph(s, scene->mRootNode);
    AIAdapter::postProcess(s);

    long long cvtTime = cvtDuration.getMicroSeconds();

    DUMP(Log::F_MODEL, "after conversion %s: %u meshes, %u materials, %u animations, %u textures, %u lights, %u cameras",
        fileName.c_str(),
        s->getNumMeshes(), s->getNumMaterials(), s->getNumAnimations(),
        s->getNumTextures(), s->getNumLights(), s->getNumCameras());
    DUMP(Log::F_MODEL, "model load: %lld ms, conversion: %lld us", importTime, cvtTime);

    return s;
}
Exemple #15
0
    "f 1 2 3\nB";

  Assimp::Importer myimporter;
  const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure);
  EXPECT_EQ(nullptr, scene);
}

TEST_F(utObjImportExport, 0based_array_Test) {
    static const std::string ObjModel =
        "v -0.500000 0.000000 0.400000\n"
        "v -0.500000 0.000000 -0.800000\n"
        "v -0.500000 1.000000 -0.800000\n"
        "f 0 1 2\nB";

    Assimp::Importer myimporter;
    const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), 0);
    EXPECT_EQ(nullptr, scene);
}

TEST_F( utObjImportExport, mtllib_after_g ) {
    ::Assimp::Importer importer;
    const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_mtllib_after_g.obj", aiProcess_ValidateDataStructure );
    ASSERT_NE( nullptr, scene );

    EXPECT_EQ(scene->mNumMeshes, 1U);
    const aiMesh *mesh = scene->mMeshes[0];
    const aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
    aiString name;
    ASSERT_EQ(aiReturn_SUCCESS, mat->Get(AI_MATKEY_NAME, name));
    EXPECT_STREQ("MyMaterial", name.C_Str());
}
Exemple #16
0
/**
* Load the model.
* Return true on success, false on failure.
**/
bool AssimpModel::load(Render3D* render, bool meshdata, AssimpLoadFlags flags)
{
	Assimp::Importer importer;

	importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_POINT | aiPrimitiveType_LINE);
	importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, aiComponent_COLORS | aiComponent_LIGHTS | aiComponent_CAMERAS);
	importer.SetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT, 65535);
	importer.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, 65535);

	unsigned int assflags = aiProcess_CalcTangentSpace
		| aiProcess_Triangulate
		| aiProcess_JoinIdenticalVertices
		| aiProcess_SortByPType
		| aiProcess_FlipUVs
		| aiProcess_FindDegenerates
		| aiProcess_ImproveCacheLocality
		| aiProcess_RemoveComponent;

	// For map meshes we flatten geometry
	if (flags & ALM_FlattenGeometry) {
		assflags |= aiProcess_PreTransformVertices;
		assflags |= aiProcess_RemoveRedundantMaterials;
		assflags |= aiProcess_OptimizeMeshes;
		assflags |= aiProcess_FindInvalidData;
		assflags |= aiProcess_SplitLargeMeshes;
	}

	// Normally models are re-centered; this isn't always deisred.
	if (flags & ALF_NoRecenter) {
		this->recenter = false;
	}

	// Read the file from the mod
	Sint64 len;
	Uint8 * data = this->mod->loadBinary("models/" + this->name, &len);
	if (! data) {
		this->mod->setLoadErr("Failed to load %s; file read failed", this->name.c_str());
		return false;
	}

	// Check we aren't larger than size_t
	if (len > MAX_FILE_SIZE) {
		this->mod->setLoadErr("Failed to load %s; file too large", this->name.c_str());
		return false;
	}

	// Do the import
	const struct aiScene* sc = importer.ReadFileFromMemory((const void*) data, (size_t)len, assflags, this->name.c_str());
	if (!sc) {
		this->mod->setLoadErr("Failed to load %s; file read failed; %s", this->name.c_str(), importer.GetErrorString());
		return false;
	}

	free(data);

	if (debug_enabled("loadbones")) {
		cout << endl << this->name << endl;
	}

	if (render != NULL && render->is3D()) {
		this->loadMeshes(true, sc);
		this->loadMaterials(render, sc);
	} else {
		this->loadMeshes(false, sc);
	}

	if (meshdata) {
		this->loadMeshdata(render != NULL, sc);
	}

	this->loadNodes(sc);
	this->loadAnimations(sc);
	this->calcBoundingBox(sc);
	this->setBoneNodes();

	return true;
}
Exemple #17
0
ptr<ImportedScene> AssimpSceneImporter::Import(ptr<File> file)
{
	BEGIN_TRY();

	Assimp::Importer importer;

	const aiScene* aScene = importer.ReadFileFromMemory(file->GetData(), file->GetSize(),
		// calculate tangents and binormals
		aiProcess_CalcTangentSpace |
		// this flag is required for index buffer
		aiProcess_JoinIdenticalVertices |
		// only 3-vertex faces
		aiProcess_Triangulate |
		// optimize order of vertices
		aiProcess_ImproveCacheLocality |
		// sort by primitive type
		aiProcess_SortByPType |
		// get right Y uv coord
		aiProcess_FlipUVs |
		// CW order
		aiProcess_FlipWindingOrder
	);
	if(!aScene)
		THROW(String("Assimp failed: ") + importer.GetErrorString());

	ptr<ImportedScene> scene = NEW(ImportedScene());
	ImportedScene::Models& models = scene->GetModels();

	// assimp calls models "meshes"
	// so assimp's "mesh" is really a mesh + material, i.e. model

	models.resize(aScene->mNumMeshes);
	for(size_t i = 0; i < models.size(); ++i)
	{
		const aiMesh* aMesh = aScene->mMeshes[i];

		// convert vertices

		size_t verticesCount = aMesh->mNumVertices;
		const aiVector3D* positions = aMesh->mVertices;
		const aiVector3D* tangents = aMesh->mTangents;
		const aiVector3D* bitangents = aMesh->mBitangents;
		const aiVector3D* normals = aMesh->mNormals;
		const aiVector3D* textureCoords = aMesh->mTextureCoords[0];

		struct Vertex
		{
			vec3 position;
			vec3 tangent;
			vec3 binormal;
			vec3 normal;
			vec2 texcoord;
		};

		auto c3 = [](const aiVector3D& v) { return vec3(v.x, v.y, v.z); };
		auto c2 = [](const aiVector3D& v) { return vec2(v.x, v.y); };

		ptr<MemoryFile> verticesFile = NEW(MemoryFile(verticesCount * sizeof(Vertex)));
		Vertex* vertices = (Vertex*)verticesFile->GetData();
		for(size_t i = 0; i < verticesCount; ++i)
		{
			Vertex& vertex = vertices[i];
			vertex.position = c3(positions[i]);
			vertex.tangent = c3(tangents[i]);
			vertex.binormal = c3(bitangents[i]);
			vertex.normal = c3(normals[i]);
			vertex.texcoord = c2(textureCoords[i]);
		}

		// convert indices

		size_t facesCount = aMesh->mNumFaces;
		const aiFace* faces = aMesh->mFaces;

		size_t indicesCount = facesCount * 3;
		ptr<MemoryFile> indicesFile;
		// if we have to use big indices
		if(indicesCount > 0x10000)
		{
			indicesFile = NEW(MemoryFile(facesCount * 3 * sizeof(unsigned int)));
			unsigned int* indices = (unsigned int*)indicesFile->GetData();
			for(size_t i = 0; i < facesCount; ++i)
			{
				const aiFace& face = faces[i];
				for(size_t j = 0; j < 3; ++j)
					indices[i * 3 + j] = face.mIndices[j];
			}
		}
		// else we can use small indices
		else
		{
			indicesFile = NEW(MemoryFile(facesCount * 3 * sizeof(unsigned short)));
			unsigned short* indices = (unsigned short*)indicesFile->GetData();
			for(size_t i = 0; i < facesCount; ++i)
			{
				const aiFace& face = faces[i];
				for(size_t j = 0; j < 3; ++j)
					indices[i * 3 + j] = (unsigned short)face.mIndices[j];
			}
		}

		models.push_back(NEW(Model(NEW(RawMesh(verticesFile, nullptr, indicesFile)), nullptr)));
	}

	return scene;

	END_TRY("Can't import scene with assimp");
}
Exemple #18
0
	// Load a model from file using the ASSIMP model loader and generate all resources required to render the model
	void loadModel(std::string filename)
	{
		// Load the model from file using ASSIMP

		const aiScene* scene;
		Assimp::Importer Importer;		

		// Flags for loading the mesh
		static const int assimpFlags = aiProcess_FlipWindingOrder | aiProcess_Triangulate | aiProcess_PreTransformVertices;

#if defined(__ANDROID__)
		// Meshes are stored inside the apk on Android (compressed)
		// So they need to be loaded via the asset manager

		AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
		assert(asset);
		size_t size = AAsset_getLength(asset);

		assert(size > 0);

		void *meshData = malloc(size);
		AAsset_read(asset, meshData, size);
		AAsset_close(asset);

		scene = Importer.ReadFileFromMemory(meshData, size, assimpFlags);

		free(meshData);
#else
		scene = Importer.ReadFile(filename.c_str(), assimpFlags);
#endif

		// Generate vertex buffer from ASSIMP scene data
		float scale = 1.0f;
		std::vector<Vertex> vertexBuffer;

		// Iterate through all meshes in the file and extract the vertex components
		for (uint32_t m = 0; m < scene->mNumMeshes; m++)
		{
			for (uint32_t v = 0; v < scene->mMeshes[m]->mNumVertices; v++)
			{
				Vertex vertex;

				// Use glm make_* functions to convert ASSIMP vectors to glm vectors
				vertex.pos = glm::make_vec3(&scene->mMeshes[m]->mVertices[v].x) * scale;
				vertex.normal = glm::make_vec3(&scene->mMeshes[m]->mNormals[v].x);
				// Texture coordinates and colors may have multiple channels, we only use the first [0] one
				vertex.uv = glm::make_vec2(&scene->mMeshes[m]->mTextureCoords[0][v].x);
				// Mesh may not have vertex colors
				vertex.color = (scene->mMeshes[m]->HasVertexColors(0)) ? glm::make_vec3(&scene->mMeshes[m]->mColors[0][v].r) : glm::vec3(1.0f);

				// Vulkan uses a right-handed NDC (contrary to OpenGL), so simply flip Y-Axis
				vertex.pos.y *= -1.0f;

				vertexBuffer.push_back(vertex);
			}
		}
		size_t vertexBufferSize = vertexBuffer.size() * sizeof(Vertex);

		// Generate index buffer from ASSIMP scene data
		std::vector<uint32_t> indexBuffer;
		for (uint32_t m = 0; m < scene->mNumMeshes; m++)
		{
			uint32_t indexBase = static_cast<uint32_t>(indexBuffer.size());
			for (uint32_t f = 0; f < scene->mMeshes[m]->mNumFaces; f++)
			{
				// We assume that all faces are triangulated
				for (uint32_t i = 0; i < 3; i++)
				{
					indexBuffer.push_back(scene->mMeshes[m]->mFaces[f].mIndices[i] + indexBase);
				}
			}
		}
		size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t);
		model.indices.count = static_cast<uint32_t>(indexBuffer.size());

		// Static mesh should always be device local

		bool useStaging = true;

		if (useStaging)
		{
			struct {
				VkBuffer buffer;
				VkDeviceMemory memory;
			} vertexStaging, indexStaging;

			// Create staging buffers
			// Vertex data
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
				vertexBufferSize,
				&vertexStaging.buffer,
				&vertexStaging.memory,
				vertexBuffer.data()));
			// Index data
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
				indexBufferSize,
				&indexStaging.buffer,
				&indexStaging.memory,
				indexBuffer.data()));

			// Create device local buffers
			// Vertex buffer
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
				VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
				vertexBufferSize,
				&model.vertices.buffer,
				&model.vertices.memory));
			// Index buffer
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
				VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
				indexBufferSize,
				&model.indices.buffer,
				&model.indices.memory));

			// Copy from staging buffers
			VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);

			VkBufferCopy copyRegion = {};

			copyRegion.size = vertexBufferSize;
			vkCmdCopyBuffer(
				copyCmd,
				vertexStaging.buffer,
				model.vertices.buffer,
				1,
				&copyRegion);

			copyRegion.size = indexBufferSize;
			vkCmdCopyBuffer(
				copyCmd,
				indexStaging.buffer,
				model.indices.buffer,
				1,
				&copyRegion);

			VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);

			vkDestroyBuffer(device, vertexStaging.buffer, nullptr);
			vkFreeMemory(device, vertexStaging.memory, nullptr);
			vkDestroyBuffer(device, indexStaging.buffer, nullptr);
			vkFreeMemory(device, indexStaging.memory, nullptr);
		}
		else
		{
			// Vertex buffer
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
				vertexBufferSize,
				&model.vertices.buffer,
				&model.vertices.memory,
				vertexBuffer.data()));
			// Index buffer
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
				indexBufferSize,
				&model.indices.buffer,
				&model.indices.memory,
				indexBuffer.data()));
		}
	}
ModelData ModelLoader::Load(const std::vector<std::uint8_t>& fileData, const char* type)
{
    Assimp::Importer importer;
    const aiScene* scene = importer.ReadFileFromMemory(
                                        fileData.data(),
                                        fileData.size(),
                                        aiProcess_Triangulate |
                                        aiProcess_FlipUVs |
                                        aiProcess_GenNormals |
                                        aiProcess_CalcTangentSpace |
                                        aiProcess_SortByPType |
                                        aiProcess_JoinIdenticalVertices |
                                        aiProcess_ImproveCacheLocality,
                                        type);

    if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
        return ModelData();

    // Used for creating the boundingBox
    glm::vec3 minPoint, maxPoint;

    auto processMesh = [&minPoint, &maxPoint](aiMesh* mesh, const aiScene* scene) -> MeshData
    {
        (void) scene;

        MeshData mData;

        for (std::uint32_t i = 0; i < mesh->mNumVertices; ++i)
        {
            VertexData vertexData;

            // Vertices
            const aiVector3D& vert = mesh->mVertices[i];
            vertexData.vx = vert.x;
            vertexData.vy = vert.y;
            vertexData.vz = vert.z;

            // Normals
            const aiVector3D& norm = mesh->mNormals[i];
            vertexData.nx = norm.x;
            vertexData.ny = norm.y;
            vertexData.nz = norm.z;

            if(mesh->HasTangentsAndBitangents())
            {
                // Tangents
                const aiVector3D& tan = mesh->mTangents[i];
                vertexData.tnx = tan.x;
                vertexData.tny = tan.y;
                vertexData.tnz = tan.z;
            }
            // TODO: think if we need the 'else' part
            //else {}

            // Texture coordinates
            if (mesh->mTextureCoords[0])
            {
                const aiVector3D& texCoord = mesh->mTextureCoords[0][i];
                vertexData.tx = texCoord.x;
                vertexData.ty = texCoord.y;
            }
            else
            {
                vertexData.tx = 0;
                vertexData.ty = 0;
            }

            // AABB minPoint
            if (vert.x < minPoint.x)
                minPoint.x = vert.x;
            if (vert.y < minPoint.y)
                minPoint.y = vert.y;
            if (vert.z < minPoint.z)
                minPoint.z = vert.z;
            // AABB maxPoint
            if (vert.x > maxPoint.x)
                maxPoint.x = vert.x;
            if (vert.y > maxPoint.y)
                maxPoint.y = vert.y;
            if (vert.z > maxPoint.z)
                maxPoint.z = vert.z;

            // Material index
            mData.meshIndex = mesh->mMaterialIndex;

            mData.data.push_back(vertexData);
        }

        // Indices
        for (std::uint32_t i = 0; i < mesh->mNumFaces; ++i)
        {
            aiFace face = mesh->mFaces[i];
            for (std::uint32_t j = 0; j < face.mNumIndices; ++j)
                mData.indices.push_back(face.mIndices[j]);
        }

        // Material
        if (scene->HasMaterials())
        {
            aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
            if (material)
            {
                auto texTypes = {aiTextureType_DIFFUSE, aiTextureType_SPECULAR, aiTextureType_NORMALS, aiTextureType_NONE};
                for (auto type : texTypes)
                {
                    std::uint32_t texCount = material->GetTextureCount(type);
                    for (std::uint32_t i = 0; i < texCount; ++i)
                    {
                        aiString str;
                        material->GetTexture(type, i, &str);
                        // TODO
                    }
                }
            }
        }

        return mData;
    };

    std::function<ModelData(aiNode*, const aiScene*)> processNode =
    [&processMesh, &processNode](aiNode* node, const aiScene* scene) -> ModelData
    {
        ModelData model;

        // Process all the node's meshes
        for (std::uint32_t i = 0; i < node->mNumMeshes; ++i)
        {
            aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
            model.meshes.push_back(processMesh(mesh, scene));
        }

        // Same for its children
        for (std::uint32_t i = 0; i < node->mNumChildren; ++i)
        {
            ModelData childModel = processNode(node->mChildren[i], scene);
            for (auto& mesh : childModel.meshes)
                model.meshes.push_back(std::move(mesh));
        }

        return model;
    };

    ModelData model = processNode(scene->mRootNode, scene);
    model.boundingBox = AABB(minPoint, maxPoint);
    return model;
}
TEST_F( utPLYImportExport, parseErrorTest ) {
    Assimp::Importer importer;
    const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), 0 );
    EXPECT_NE( nullptr, scene );
}
Exemple #21
0
TEST_F( utPLYImportExport, parseErrorTest ) {
    Assimp::Importer importer;
    //Could not use aiProcess_ValidateDataStructure since it's missing faces.
    const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), 0);
    EXPECT_NE( nullptr, scene );
}