virtual bool importerTest() {
     Assimp::Importer importer;
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", 0 );
     return nullptr != scene;
 }
Exemple #2
0
IndexedMesh * MeshLoader::LoadMesh(const std::string &path)
{
	// Load the file
	Assimp::Importer importer;
	const aiScene* scene = importer.ReadFile(
		path, 
		aiProcess_Triangulate
		| aiProcess_JoinIdenticalVertices
		| aiProcess_OptimizeGraph
		| aiProcess_OptimizeMeshes
		| aiProcess_RemoveRedundantMaterials
		| aiProcess_GenSmoothNormals
		);

	if (scene->HasMeshes())
	{
		// Get the model mesh
		aiMesh &mesh = *scene->mMeshes[0];

		if (!mesh.HasPositions() || !mesh.HasFaces()) 
			return NULL;

		// Initialize the model
		vector<glm::vec3> vertices;
		vector<GLuint> indices;
		vector<glm::vec4> colors;
		vector<glm::vec3> normals;

		// Get mesh properties 
		for (unsigned int i=0; i<mesh.mNumVertices; ++i) 
		{
			// Get vertices
			vertices.push_back(glm::vec3(mesh.mVertices[i].x, mesh.mVertices[i].y, mesh.mVertices[i].z));

			// Get colors
			if(mesh.HasVertexColors(0))
			{
				colors.push_back(glm::vec4(mesh.mColors[0][i].r, mesh.mColors[0][i].g, mesh.mColors[0][i].b, mesh.mColors[0][i].a));
			}
			else
			{
				colors.push_back(glm::vec4(1,1,1,1));
			}

			// Get normals
			normals.push_back(glm::vec3(mesh.mNormals[i].x, mesh.mNormals[i].y, mesh.mNormals[i].z));
		}

		// Normalize vertices
		normalizeVertices(vertices);

		// Get indices
		for (unsigned int i=0; i<mesh.mNumFaces; ++i) 
		{
			aiFace face = mesh.mFaces[i];

			indices.push_back(face.mIndices[0]);
			indices.push_back(face.mIndices[1]);
			indices.push_back(face.mIndices[2]);
		}

		return new IndexedMesh(vertices, indices, colors, normals);
	}

	return NULL;
}
 virtual bool importerTest() {
     Assimp::Importer importer;
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure);
     return nullptr != scene;
 }
Exemple #4
0
Mesh::Mesh(const std::string& fileName) :
	m_fileName(fileName),
	m_meshData(0)
{
	std::map<std::string, MeshData*>::const_iterator it = s_resourceMap.find(fileName);
	if(it != s_resourceMap.end())
	{
		m_meshData = it->second;
		m_meshData->AddReference();
	}
	else
	{
		Assimp::Importer importer;
		
		const aiScene* scene = importer.ReadFile(("./res/models/" + fileName).c_str(), 
		                                         aiProcess_Triangulate |
		                                         aiProcess_GenSmoothNormals | 
		                                         aiProcess_FlipUVs |
		                                         aiProcess_CalcTangentSpace);
		
		if(!scene)
		{
			std::cout << "Mesh load failed!: " << fileName << std::endl;
			assert(0 == 0);
		}
		
		const aiMesh* model = scene->mMeshes[0];
		
		std::vector<Vector3f> positions;
		std::vector<Vector2f> texCoords;
		std::vector<Vector3f> normals;
		std::vector<Vector3f> tangents;
		std::vector<unsigned int> indices;

		const aiVector3D aiZeroVector(0.0f, 0.0f, 0.0f);
		for(unsigned int i = 0; i < model->mNumVertices; i++) 
		{
			const aiVector3D pos = model->mVertices[i];
			const aiVector3D normal = model->mNormals[i];
			const aiVector3D texCoord = model->HasTextureCoords(0) ? model->mTextureCoords[0][i] : aiZeroVector;
			const aiVector3D tangent = model->mTangents[i];

			positions.push_back(Vector3f(pos.x, pos.y, pos.z));
			texCoords.push_back(Vector2f(texCoord.x, texCoord.y));
			normals.push_back(Vector3f(normal.x, normal.y, normal.z));
			tangents.push_back(Vector3f(tangent.x, tangent.y, tangent.z));
		}

		for(unsigned int i = 0; i < model->mNumFaces; i++)
		{
			const aiFace& face = model->mFaces[i];
			assert(face.mNumIndices == 3);
			indices.push_back(face.mIndices[0]);
			indices.push_back(face.mIndices[1]);
			indices.push_back(face.mIndices[2]);
		}
		
		m_meshData = new MeshData(IndexedModel(indices, positions, texCoords, normals, tangents));
		s_resourceMap.insert(std::pair<std::string, MeshData*>(fileName, m_meshData));
	}
}
Exemple #5
0
S3DModel* CAssParser::Load(const std::string& modelFilePath)
{
	LOG_SL(LOG_SECTION_MODEL, L_INFO, "Loading model: %s", modelFilePath.c_str());

	const std::string& modelPath = FileSystem::GetDirectory(modelFilePath);
	const std::string& modelName = FileSystem::GetBasename(modelFilePath);

	// Load the lua metafile. This contains properties unique to Spring models and must return a table
	std::string metaFileName = modelFilePath + ".lua";

	if (!CFileHandler::FileExists(metaFileName, SPRING_VFS_ZIP)) {
		// Try again without the model file extension
		metaFileName = modelPath + '/' + modelName + ".lua";
	}
	if (!CFileHandler::FileExists(metaFileName, SPRING_VFS_ZIP)) {
		LOG_SL(LOG_SECTION_MODEL, L_INFO, "No meta-file '%s'. Using defaults.", metaFileName.c_str());
	}

	LuaParser metaFileParser(metaFileName, SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP);

	if (!metaFileParser.Execute()) {
		LOG_SL(LOG_SECTION_MODEL, L_INFO, "'%s': %s. Using defaults.", metaFileName.c_str(), metaFileParser.GetErrorLog().c_str());
	}

	// Get the (root-level) model table
	const LuaTable& modelTable = metaFileParser.GetRoot();

	if (!modelTable.IsValid()) {
		LOG_SL(LOG_SECTION_MODEL, L_INFO, "No valid model metadata in '%s' or no meta-file", metaFileName.c_str());
	}


	// Create a model importer instance
	Assimp::Importer importer;


	// Give the importer an IO class that handles Spring's VFS
	importer.SetIOHandler(new AssVFSSystem());
	// Speed-up processing by skipping things we don't need
	importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, ASS_IMPORTER_OPTIONS);

#ifndef BITMAP_NO_OPENGL
	{
		importer.SetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,   maxVertices);
		importer.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, maxIndices / 3);
	}
#endif

	// Read the model file to build a scene object
	LOG_SL(LOG_SECTION_MODEL, L_INFO, "Importing model file: %s", modelFilePath.c_str());

	const aiScene* scene = nullptr;

	{
		// ASSIMP spams many SIGFPEs atm in normal & tangent generation
		ScopedDisableFpuExceptions fe;
		scene = importer.ReadFile(modelFilePath, ASS_POSTPROCESS_OPTIONS);
	}

	if (scene != nullptr) {
		LOG_SL(LOG_SECTION_MODEL, L_INFO,
			"Processing scene for model: %s (%d meshes / %d materials / %d textures)",
			modelFilePath.c_str(), scene->mNumMeshes, scene->mNumMaterials,
			scene->mNumTextures);
	} else {
		throw content_error("[AssimpParser] Model Import: " + std::string(importer.GetErrorString()));
	}

	ModelPieceMap pieceMap;
	ParentNameMap parentMap;

	S3DModel* model = new S3DModel();
	model->name = modelFilePath;
	model->type = MODELTYPE_ASS;

	// Load textures
	FindTextures(model, scene, modelTable, modelPath, modelName);
	LOG_SL(LOG_SECTION_MODEL, L_INFO, "Loading textures. Tex1: '%s' Tex2: '%s'", model->texs[0].c_str(), model->texs[1].c_str());

	texturehandlerS3O->PreloadTexture(model, modelTable.GetBool("fliptextures", true), modelTable.GetBool("invertteamcolor", true));

	// Load all pieces in the model
	LOG_SL(LOG_SECTION_MODEL, L_INFO, "Loading pieces from root node '%s'", scene->mRootNode->mName.data);
	LoadPiece(model, scene->mRootNode, scene, modelTable, pieceMap, parentMap);

	// Update piece hierarchy based on metadata
	BuildPieceHierarchy(model, pieceMap, parentMap);
	CalculateModelProperties(model, modelTable);

	// Verbose logging of model properties
	LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->name: %s", model->name.c_str());
	LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->numobjects: %d", model->numPieces);
	LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->radius: %f", model->radius);
	LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->height: %f", model->height);
	LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->mins: (%f,%f,%f)", model->mins[0], model->mins[1], model->mins[2]);
	LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->maxs: (%f,%f,%f)", model->maxs[0], model->maxs[1], model->maxs[2]);
	LOG_SL(LOG_SECTION_MODEL, L_INFO, "Model %s Imported.", model->name.c_str());
	return model;
}
Exemple #6
0
 virtual bool importerTest() {
     Assimp::Importer importer;
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/X3D/ComputerKeyboard.x3d", aiProcess_ValidateDataStructure );
     return nullptr != scene;
 }
TEST_F( utSTLImporterExporter, test_with_two_solids ) {
    Assimp::Importer importer;
    const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", aiProcess_ValidateDataStructure );
    EXPECT_NE( nullptr, scene );
}
Exemple #8
0
int main(int argc, char** argv)
{
	if ( argc < 2 )
	{
		fprintf(stderr, "Usage: %s filename format\n"
			"  format = minimal|simple\n",
			argv[0]);
		return 42;
	}

	VertexType format = VERTEXTYPE_SIMPLE;
	if ( argc >= 3 )
	{
		static const u32 nbFormats = sizeof(formats)/sizeof(formats[0]);
		u32 i = 0;
		for ( ; i < nbFormats ; i++ )
		{
			if ( strcmp(formats[i], argv[2]) == 0 )
			{
				format = (VertexType)i;
				break;
			}
		}
		if ( i == nbFormats )
		{
			fprintf(stderr, "Unknown format %s\n", argv[2]);
			return 42;
		}
	}

	Assimp::Importer importer;
	importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,
		aiPrimitiveType_POINT
		| aiPrimitiveType_LINE);

	static u32 removeComponents[VERTEXTYPE_COUNT] =
	{
		// VERTEXTYPE_MINIMAL
		aiComponent_COLORS
		| aiComponent_TEXCOORDS
		| aiComponent_NORMALS
		| aiComponent_TANGENTS_AND_BITANGENTS
		| aiComponent_BONEWEIGHTS
		| aiComponent_ANIMATIONS
		| aiComponent_TEXTURES
		| aiComponent_LIGHTS
		| aiComponent_CAMERAS
		| aiComponent_MATERIALS,

		// VERTEXTYPE_SIMPLE
		aiComponent_COLORS
		| aiComponent_TEXCOORDSn(1)
		| aiComponent_TEXCOORDSn(2)
		| aiComponent_TEXCOORDSn(3)
		| aiComponent_BONEWEIGHTS
		| aiComponent_ANIMATIONS
		| aiComponent_TEXTURES
		| aiComponent_LIGHTS
		| aiComponent_CAMERAS
		| aiComponent_MATERIALS,
	};

	importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, removeComponents[format]);

	static u32 preProcess[VERTEXTYPE_COUNT] =
	{
		// VERTEXTYPE_MINIMAL
		aiProcess_Triangulate
		| aiProcess_RemoveComponent
		| aiProcess_JoinIdenticalVertices
		| aiProcess_ImproveCacheLocality
		| aiProcess_OptimizeMeshes
		| aiProcess_FindInstances
		| aiProcess_FindInvalidData
		| aiProcess_RemoveRedundantMaterials
		| aiProcess_FindDegenerates
		| aiProcess_ValidateDataStructure,

		// VERTEXTYPE_SIMPLE
		aiProcess_CalcTangentSpace
		| aiProcess_GenNormals
		| aiProcess_Triangulate
		| aiProcess_RemoveComponent
		| aiProcess_JoinIdenticalVertices
		| aiProcess_ImproveCacheLocality
		| aiProcess_OptimizeMeshes
		| aiProcess_FindInstances
		| aiProcess_FindInvalidData
		| aiProcess_RemoveRedundantMaterials
		| aiProcess_FindDegenerates
		| aiProcess_ValidateDataStructure,

		// VERTEXTYPE_SPRITE
		aiProcess_Triangulate
		| aiProcess_RemoveComponent
		| aiProcess_JoinIdenticalVertices
		| aiProcess_ImproveCacheLocality
		| aiProcess_OptimizeMeshes
		| aiProcess_FindInstances
		| aiProcess_FindInvalidData
		| aiProcess_RemoveRedundantMaterials
		| aiProcess_FindDegenerates
		| aiProcess_ValidateDataStructure,
	};

	const aiScene* scene = importer.ReadFile(argv[1], preProcess[format]);

	if ( scene == 0 )
	{
		fprintf(stderr, "Couldn't load %s.\n", argv[1]);
		fprintf(stderr, importer.GetErrorString());
		return 42;
	}

	RemoveExtension(argv[1]);

	for ( u32 i = 0 ; i < scene->mNumMeshes ; i++ )
	{
		aiMesh* mesh = scene->mMeshes[i];

		static char filename[4096];
		if ( mesh->mName.length != 0 )
		{
			sprintf(filename, "%s-%s.mesh", argv[1], mesh->mName.data);
		}
		else
		{
			sprintf(filename, "%s-%d.mesh", argv[1], i + 1);
		}

		printf("Exporting %d:\"%s\" to %s...\n", i + 1, mesh->mName.data, filename);
		ExportMesh(mesh, filename, format);
	}	

	return 0;
}
void MultiLightDemo::Initialize()
{
	glEnable(GL_DEPTH_TEST);
	glClearColor(0.3f, 0.2f, 0.7f, 1.0f);
	program.AddShaderFile(ShaderType::Vertex, "Assets/Shaders/Vertex/multiLight.vert");
	program.AddShaderFile(ShaderType::Fragment, "Assets/Shaders/Fragment/multiLight.frag");
	program.Build();

	program.AddUniformBlock({ "TransformBlock",{
		{ "TransformBlock.view",&camera->GetView()[0][0], sizeof(camera->GetView()) },
		{ "TransformBlock.projection",&camera->GetProjection()[0][0], sizeof(camera->GetProjection()) },
		{ "TransformBlock.eyePosition",&camera->GetPosition()[0], sizeof(camera->GetPosition()) },
	} });

	lights[0].position = glm::vec3(0.0f, 0.0f, -2.0f);
	lights[1].position = glm::vec3(-2.0f, -3.0f, -2.0f);
	lights[2].position = glm::vec3(4.0f, 7.0f, -2.0f);

	lights[0].color = glm::vec3(0.9f,0.5f,0.3f);
	lights[1].color = glm::vec3(0.2f,0.9f,0.2f);
	lights[2].color = glm::vec3(0.2f,0.4f,0.9f);
	
	program.AddUniform("lights[0].position", &lights[0].position[0], UniformType::VEC3);
	program.AddUniform("lights[0].color", &lights[0].color[0], UniformType::VEC3);
	program.AddUniform("lights[1].position", &lights[1].position[0], UniformType::VEC3);
	program.AddUniform("lights[1].color", &lights[1].color[0], UniformType::VEC3);
	program.AddUniform("lights[2].position", &lights[2].position[0], UniformType::VEC3);
	program.AddUniform("lights[2].color", &lights[2].color[0], UniformType::VEC3);

	input->addBinding(GLFW_KEY_LEFT, [this](InputInfo info) {
		camera->MoveLeft();
		program.UpdateUniformBlock("TransformBlock");
	});

	input->addBinding(GLFW_KEY_RIGHT, [this](InputInfo info) {
		camera->MoveRight();
		program.UpdateUniformBlock("TransformBlock");
	});


	input->addBinding(GLFW_KEY_UP, [this](InputInfo info) {
		camera->MoveForward();
		program.UpdateUniformBlock("TransformBlock");
	});

	input->addBinding(GLFW_KEY_DOWN, [this](InputInfo info) {
		camera->MoveBack();
		program.UpdateUniformBlock("TransformBlock");
	});


	//program.AddUniform("light[0].position", &lights[0].position[0], UniformType::VEC3);
	//program.AddUniform("light[0].color", &lights[0].color[0], UniformType::VEC3);
	//program.AddUniform("light[1].position", &lights[1].position[0], UniformType::VEC3);
	//program.AddUniform("light[1].color", &lights[1].color[0], UniformType::VEC3);
	//program.AddUniform("light[2].position", &lights[2].position[0], UniformType::VEC3);
	//program.AddUniform("light[2].color", &lights[2].color[0], UniformType::VEC3);

	using std::unique_ptr;
	monkey = unique_ptr<GameObject>(new GameObject());
	monkey->GetTransform()->SetPosition({ 0.0f,0.0f,-5.0f });
	monkey->Update();
	Assimp::Importer importer;
	auto scene = importer.ReadFile("Assets/Models/Obj/monkey.obj", aiProcess_Triangulate);
	if (scene && scene->HasMeshes())
	{
		mesh = unique_ptr<MeshComponent>(new MeshComponent(monkey.get()));
		mesh->Initialize(scene->mMeshes[0], program, {
			{ "world", UniformType::MAT4, &monkey->GetWorld()[0][0] },
			{ "material.ambient", UniformType::VEC3, &mesh->GetMaterial().ambient[0] },
			{ "material.diffuse", UniformType::VEC3, &mesh->GetMaterial().diffuse[0] },
			{ "material.specular", UniformType::VEC4, &mesh->GetMaterial().specular[0] },
		});
		monkey->AddComponent(mesh.get());
	}

	mesh->GetMaterial().ambient = glm::vec3(0.6f, 0.7f, 0.1f);
	mesh->GetMaterial().diffuse = glm::vec3(0.5f, 0.2f, 0.8f);
	mesh->GetMaterial().specular = glm::vec4(0.3f, 0.2f, 0.2f, 10.0f);
	importer.FreeScene();

}
Exemple #10
0
 virtual bool importerTest() {
     Assimp::Importer importer;
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", aiProcess_ValidateDataStructure );
     return nullptr != scene;
 }
    std::shared_ptr<gameplay::Model> OBJWriter::readModel(const boost::filesystem::path& path, const std::shared_ptr<gameplay::ShaderProgram>& shaderProgram, const glm::vec3& ambientColor) const
    {
        Assimp::Importer importer;
        const aiScene* scene = importer.ReadFile((m_basePath / path).string(), aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_ValidateDataStructure | aiProcess_FlipUVs);
        BOOST_ASSERT(scene != nullptr);

        auto renderModel = std::make_shared<gameplay::Model>();

        for( unsigned int mi = 0; mi < scene->mNumMeshes; ++mi )
        {
            BOOST_LOG_TRIVIAL(info) << "Converting mesh " << mi + 1 << " of " << scene->mNumMeshes << " from " << m_basePath / path;

            const aiMesh* mesh = scene->mMeshes[mi];
            if( mesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE )
            BOOST_THROW_EXCEPTION(std::runtime_error("Mesh does not consist of triangles only"));
            if( !mesh->HasTextureCoords(0) )
            BOOST_THROW_EXCEPTION(std::runtime_error("Mesh does not have UV coordinates"));
            if( mesh->mNumUVComponents[0] != 2 )
            BOOST_THROW_EXCEPTION(std::runtime_error("Mesh does not have a 2D UV channel"));
            if( !mesh->HasFaces() )
            BOOST_THROW_EXCEPTION(std::runtime_error("Mesh does not have faces"));
            if( !mesh->HasPositions() )
            BOOST_THROW_EXCEPTION(std::runtime_error("Mesh does not have positions"));

            std::shared_ptr<gameplay::Mesh> renderMesh;

            if( mesh->HasNormals() )
            {
                std::vector<VDataNormal> vbuf(mesh->mNumVertices);
                for( unsigned int i = 0; i < mesh->mNumVertices; ++i )
                {
                    vbuf[i].position = glm::vec3{mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z} * static_cast<float>(SectorSize);
                    vbuf[i].normal = glm::vec3{mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z};
                    vbuf[i].uv = glm::vec2{mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y};
                    if( mesh->HasVertexColors(0) )
                        vbuf[i].color = glm::vec4(mesh->mColors[0][i].r, mesh->mColors[0][i].g, mesh->mColors[0][i].b, mesh->mColors[0][i].a);
                    else
                        vbuf[i].color = glm::vec4(ambientColor, 1);
                }

                renderMesh = std::make_shared<gameplay::Mesh>(VDataNormal::getFormat(), mesh->mNumVertices, false);
                renderMesh->rebuild(reinterpret_cast<const float*>(vbuf.data()), mesh->mNumVertices);
            }
            else
            {
                std::vector<VData> vbuf(mesh->mNumVertices);
                for( unsigned int i = 0; i < mesh->mNumVertices; ++i )
                {
                    vbuf[i].position = glm::vec3{mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z} * static_cast<float>(SectorSize);
                    vbuf[i].uv = glm::vec2{mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y};
                    if( mesh->HasVertexColors(0) )
                        vbuf[i].color = glm::vec4(mesh->mColors[0][i].r, mesh->mColors[0][i].g, mesh->mColors[0][i].b, mesh->mColors[0][i].a);
                    else
                        vbuf[i].color = glm::vec4(ambientColor, 1);
                }

                renderMesh = std::make_shared<gameplay::Mesh>(VData::getFormat(), mesh->mNumVertices, false);
                renderMesh->rebuild(reinterpret_cast<const float*>(vbuf.data()), mesh->mNumVertices);
            }

            std::vector<uint32_t> faces;
            for( const aiFace& face : gsl::span<aiFace>(mesh->mFaces, mesh->mNumFaces) )
            {
                BOOST_ASSERT(face.mNumIndices == 3);
                faces.push_back(face.mIndices[0]);
                faces.push_back(face.mIndices[1]);
                faces.push_back(face.mIndices[2]);
            }

            auto part = renderMesh->addPart(gameplay::Mesh::TRIANGLES, gameplay::Mesh::INDEX32, mesh->mNumFaces * 3, false);
            part->setIndexData(faces.data(), 0, faces.size());

            const aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
            aiString textureName;
            if( material->GetTexture(aiTextureType_DIFFUSE, 0, &textureName) != aiReturn_SUCCESS )
            BOOST_THROW_EXCEPTION(std::runtime_error("Failed to get diffuse texture path from mesh"));

            part->setMaterial(readMaterial(textureName.C_Str(), shaderProgram));

            renderModel->addMesh(renderMesh);
        }

        return renderModel;
    }
Exemple #12
0
void ObjLoader::LoadAssimp( const std::string &FileName )
{
    auto t0 = std::chrono::high_resolution_clock::now();
    Assimp::Importer Importer;
    const aiScene *scene = Importer.ReadFile( FileName,
                           aiProcessPreset_TargetRealtime_Quality );
    if( !scene )
    {
        std::cout << "ASSIMP cos poszlo nie tak\n";
        std::cout << "ASSIMP ERROR: " << Importer.GetErrorString() << std::endl;
    }

    //w petli przez wszystkie meshe
    const aiMesh * mesh = scene->mMeshes[0];
    for( uint t = 0; t < mesh->mNumFaces ; t++ )
    {
        const aiFace *face = &mesh->mFaces[ t ] ;
        mGpuIndices.push_back( face->mIndices[ 0 ] );
        mGpuIndices.push_back( face->mIndices[ 1 ] );
        mGpuIndices.push_back( face->mIndices[ 2 ] );
    }

    // verteksy
    if( mesh->HasPositions() )
    {
        mVertex.resize( mesh->mNumVertices );
        memcpy( &mVertex[0], mesh->mVertices, 3*4* mesh->mNumVertices );
    }
    if( mesh->HasNormals() )
    {
        mNormals.resize( mesh->mNumVertices  );
        memcpy(  &mNormals[0], mesh->mNormals, 3*4* mesh->mNumVertices );
    }
    if( mesh->HasTextureCoords(0) )
    {
        for( uint k = 0; k < mesh->mNumVertices; ++k )
        {
            glm::vec2 tmp;
            tmp.x =	mesh->mTextureCoords[0][k].x;
            tmp.y = mesh->mTextureCoords[0][k].y;
            mTexcoords.push_back( tmp );
        }
    }
    mGpuBuffer.resize( mesh->mNumVertices*8);

    for( uint i = 0; i < mesh->mNumVertices; ++i )
    {
        mGpuBuffer[ i*8 ] = mVertex[ i ].x;
        mGpuBuffer[ i*8 +1 ] = mVertex[ i ].y;
        mGpuBuffer[ i*8 +2] = mVertex[ i ].z;
        mGpuBuffer[ i*8 +3] = mNormals[ i ].x;
        mGpuBuffer[ i*8 +4] = mNormals[ i ].y;
        mGpuBuffer[ i*8 +5] = mNormals[ i ].z;
        if( mesh->HasTextureCoords(0) ) {
            mGpuBuffer[i * 8 + 6] = mTexcoords[i].s;
            mGpuBuffer[i * 8 + 7] = mTexcoords[i].t;
        }
    }
    auto t1 = std::chrono::high_resolution_clock::now();
    std::chrono::milliseconds total_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0);
    std::cout << "Time: " << total_ms.count() << " ms " << std::endl;
    Surface *pSurface = new Surface();
    VertexBufferManager &VBOMan = VertexBufferManager::GetSingleton();
    IndexBuffer *pIndex = VBOMan.CreateIndexBuffer();
    pIndex->SetIndexData( mGpuIndices );
    pIndex->Prepare();
    VertexDeclaration *pDecl = VBOMan.GetVertexDeclaration( "Default" );
    VertexSettings( PT_TRIANGLE, UT_STATIC_DRAW, pIndex, pDecl );
    VertexBuffer *pVertex = VBOMan.CreateVertexBuffer(
                                VertexSettings( PT_TRIANGLE, UT_STATIC_DRAW, pIndex, pDecl ) );
    pVertex->SetVertexData( mGpuBuffer );
    pVertex->Prepare();
    pSurface->SetVertexBuffer( pVertex );
    mSurfaces.push_back( pSurface );


}
Exemple #13
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()));
		}
	}
Exemple #14
0
BumpedTexturedMesh * MeshLoader::LoadBumpedMesh(const std::string &path, const string &texturePath, const string &normalPath)
{
	// Load the file
	Assimp::Importer importer;
	const aiScene* scene = importer.ReadFile(
		path, 
		aiProcess_Triangulate
		| aiProcess_JoinIdenticalVertices
		| aiProcess_OptimizeGraph
		| aiProcess_OptimizeMeshes
		| aiProcess_RemoveRedundantMaterials
		| aiProcess_GenSmoothNormals
		| aiProcess_CalcTangentSpace
		);

	if (scene->HasMeshes())
	{
		// Get the model mesh
		aiMesh &mesh = *scene->mMeshes[0];

		if (!mesh.HasPositions() || !mesh.HasFaces()) 
			return NULL;

		// Initialize the model
		vector<glm::vec3> vertices;
		vector<GLuint> indices;
		vector<glm::vec3> normals;
		vector<glm::vec2> uvs;
		vector<glm::vec4> tangents;

		// Get mesh properties 
		for (unsigned int i=0; i<mesh.mNumVertices; ++i) 
		{
			// Get vertices
			vertices.push_back(glm::vec3(mesh.mVertices[i].x, mesh.mVertices[i].y, mesh.mVertices[i].z));
			//vertices[vertices.size()-1] /= 38;

			// Get normals
			normals.push_back(glm::vec3(mesh.mNormals[i].x, mesh.mNormals[i].y, mesh.mNormals[i].z));

			// Get UVs
			uvs.push_back(glm::vec2(mesh.mTextureCoords[0][i].x, mesh.mTextureCoords[0][i].y));

			if (mesh.HasTangentsAndBitangents()) 
			{
				const aiVector3D tangent = mesh.mTangents[i];
				const aiVector3D bitangent = mesh.mBitangents[i];

				// put the three vectors into my vec3 struct format for doing maths
				vec3 t (tangent.x, tangent.y, tangent.z);
				vec3 b (bitangent.x, bitangent.y, bitangent.z);
				// orthogonalise and normalise the tangent so we can use it in something
				// approximating a T,N,B inverse matrix
				vec3 t_i = t - normals[i] * dot (normals[i], t);
				//5std::cout << i << ": " << t_i.x << " " << t_i.y << " " << t_i.z << std::endl;
				if(!isnan(t_i.x)) t_i = normalize(t_i);

				// get determinant of T,B,N 3x3 matrix by dot*cross method
				float det = (dot (cross (normals[i], t), b));
				if (det < 0.0f) {
					det = -1.0f;
				} else {
					det = 1.0f;
				}

				tangents.push_back(vec4(t_i, det));
			}
		}		

		// Normalize vertices
		normalizeVertices(vertices);

		// Get indices
		for (unsigned int i=0; i<mesh.mNumFaces; ++i) 
		{
			aiFace face = mesh.mFaces[i];

			indices.push_back(face.mIndices[0]);
			indices.push_back(face.mIndices[1]);
			indices.push_back(face.mIndices[2]);
		}

		BumpedTexturedMesh * modelMesh =  new BumpedTexturedMesh(vertices, indices, normals, uvs, tangents);
		modelMesh->SetTexture(loadTexture(texturePath));
		modelMesh->SetNormalTexture(loadTexture(normalPath));

		return modelMesh;
	}

	return NULL;
}
Exemple #15
0
bool Mesh::Load ( const char* filePath )
{
	Assimp::Importer importer;
	const aiScene* scene = importer.ReadFile ( filePath, 
		aiProcess_Triangulate |
		aiProcess_JoinIdenticalVertices | 
		aiProcess_FlipWindingOrder |
		aiProcess_CalcTangentSpace );

	if ( !scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode )
	{
		return false;
	}

	for ( unsigned int i = 0; i < scene->mNumMeshes; ++i )
	{
		SubMesh* submesh = new SubMesh;

		const aiMesh* aimesh = scene->mMeshes[i];

		///// VERTEX BUFFER /////

		submesh->m_vertexCount = aimesh->mNumVertices;
		submesh->m_verts = malloc( sizeof( Vertex ) * submesh->m_vertexCount );
		Vertex* vertBuffer = ( Vertex* )submesh->m_verts;
		for ( unsigned int j = 0; j < aimesh->mNumVertices; ++j )
		{
			Vertex v;
			v.pos[0] = aimesh->mVertices[j].x;
			v.pos[1] = aimesh->mVertices[j].y;
			v.pos[2] = aimesh->mVertices[j].z;
			if ( aimesh->mNormals )
			{
				v.norm[0] = aimesh->mNormals[j].x;
				v.norm[1] = aimesh->mNormals[j].y;
				v.norm[2] = aimesh->mNormals[j].z;
			}
			else
			{
				v.norm[0] = 0;
				v.norm[1] = 0;
				v.norm[2] = 0;
			}
			if ( aimesh->mTextureCoords[0] )
			{
				v.uv[0] = aimesh->mTextureCoords[0][j].x;
				v.uv[1] = aimesh->mTextureCoords[0][j].y;
			}
			else
			{
				v.uv[0] = 0;
				v.uv[1] = 0;
			}
			if ( aimesh->mTangents )
			{
				v.tanget[0] = aimesh->mTangents[j].x;
				v.tanget[1] = aimesh->mTangents[j].y;
				v.tanget[2] = aimesh->mTangents[j].z;
			}
			else
			{
				v.tanget[0] = 0;
				v.tanget[1] = 0;
				v.tanget[2] = 0;
			}
			if ( aimesh->mBitangents )
			{
				v.bitangent[0] = aimesh->mBitangents[j].x;
				v.bitangent[1] = aimesh->mBitangents[j].y;
				v.bitangent[2] = aimesh->mBitangents[j].z;
			}
			else
			{
				v.bitangent[0] = 0;
				v.bitangent[1] = 0;
				v.bitangent[2] = 0;
			}

			vertBuffer[j] = v;
		}

		submesh->m_vertexHandle = GraphicsManager::Instance().CreateVertexBuffer( submesh->m_verts, sizeof( Vertex ) * submesh->m_vertexCount );

		///// INDEX BUFFER /////

		submesh->m_indexCount = aimesh->mNumFaces * 3; // 3 verts per face
		submesh->m_indices = ( uint16_t* )malloc( submesh->m_indexCount * sizeof( uint16_t ) );
		uint16_t idx = 0;
		for ( unsigned int j = 0; j < aimesh->mNumFaces; ++j )
		{
			const aiFace& face = aimesh->mFaces[j];
			if ( face.mNumIndices != 3 )
				return false;
			for ( uint8_t k = 0; k < 3; ++k )
			{
				dDAssert( idx < aimesh->mNumFaces * 3 );
				submesh->m_indices[idx++] = face.mIndices[k];
			}
		}

		submesh->m_indexBufferHandle = GraphicsManager::Instance().CreateIndexBuffer( submesh->m_indices, ( uint16_t )sizeof( uint16_t ) * submesh->m_indexCount );

		//// DECLARATION ////
		submesh->m_decl = *VertexDeclaration::GetDefaultDeclaration();

		m_subMeshes.push_back ( submesh );
	}

	return true;
}
Exemple #16
0
TexturedIndexedMesh * MeshLoader::LoadMesh(const std::string &path, const string &texturePath)
{
	// Load the file
	Assimp::Importer importer;
	const aiScene* scene = importer.ReadFile(
		path, 
		aiProcess_Triangulate
		| aiProcess_JoinIdenticalVertices
		| aiProcess_OptimizeGraph
		| aiProcess_OptimizeMeshes
		| aiProcess_RemoveRedundantMaterials
		| aiProcess_GenSmoothNormals
		);

	if (scene->HasMeshes())
	{
		// Get the model mesh
		aiMesh &mesh = *scene->mMeshes[0];

		if (!mesh.HasPositions() || !mesh.HasFaces()) 
			return NULL;

		// Initialize the model
		vector<glm::vec3> vertices;
		vector<GLuint> indices;
		vector<glm::vec3> normals;
		vector<glm::vec2> uvs; 

		// Get mesh properties 
		for (unsigned int i=0; i<mesh.mNumVertices; ++i) 
		{
			// Get vertices
			vertices.push_back(glm::vec3(mesh.mVertices[i].x, mesh.mVertices[i].y, mesh.mVertices[i].z));
			//vertices[vertices.size()-1] /= 38;

			// Get normals
			normals.push_back(glm::vec3(mesh.mNormals[i].x, mesh.mNormals[i].y, mesh.mNormals[i].z));

			// Get UVs
			uvs.push_back(glm::vec2(mesh.mTextureCoords[0][i].x, mesh.mTextureCoords[0][i].y));
		}		

		// Normalize vertices
		normalizeVertices(vertices);

		// Get indices
		for (unsigned int i=0; i<mesh.mNumFaces; ++i) 
		{
			aiFace face = mesh.mFaces[i];

			indices.push_back(face.mIndices[0]);
			indices.push_back(face.mIndices[1]);
			indices.push_back(face.mIndices[2]);
		}

		TexturedIndexedMesh * modelMesh =  new TexturedIndexedMesh(vertices, indices, normals, uvs);
		modelMesh->SetTexture(loadTexture(texturePath));

		return modelMesh;
	}

	return NULL;
}
Exemple #17
0
/** load the mesh from file 
 * \param model_name is the model file name 
 */
bool CLoadedObject::loadMesh( std::string model_name )
{
  //m_model_name = model_name;

  Assimp::Importer imp;

  const aiScene * scn = imp.ReadFile(model_name.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_GenUVCoords);

  if(!scn)
  {
    std::cerr << imp.GetErrorString() << std::endl;
    return false;
  }

  if(scn->mNumMeshes < 1)
  {
    std::cerr << "no meshes found in scene " << model_name << std::endl;
    return false;
  }

  std::cout << "loaded " << scn->mNumMeshes << " meshes" << std::endl;

  // merge all sub-meshes to one big mesh
  m_nVertices = 0;
  for(unsigned m = 0; m < scn->mNumMeshes; ++m)
    m_nVertices += scn->mMeshes[m]->mNumVertices;

  float * vertices = new float[7 * m_nVertices]; // 7 floats per vertex (xyz + RGBA)
  float * cur_vert = vertices;                   // all vertices first
  float * cur_col = vertices + 3 * m_nVertices;  // than all colors

  for(unsigned m = 0; m < scn->mNumMeshes; ++m)
  {
    aiMesh * mesh = scn->mMeshes[m];
    memcpy(cur_vert, mesh->mVertices, mesh->mNumVertices * sizeof(float) * 3);

    aiMaterial * material = scn->mMaterials[mesh->mMaterialIndex];
    // copy mesh material color to all mesh vertices
    for(unsigned v = 0; v < mesh->mNumVertices; ++v)
    {
      aiColor4D color;
      material->Get<aiColor4D>(AI_MATKEY_COLOR_DIFFUSE, color);
      *cur_col++ = color.r;
      *cur_col++ = color.g;
      *cur_col++ = color.b;
      *cur_col++ = color.a;
    }

    cur_vert += mesh->mNumVertices * 3;
  }

  // create vertex buffer
  glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferObject);
  //glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  glBufferData(GL_ARRAY_BUFFER, m_nVertices * sizeof(float) * 7, vertices, GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  delete [] vertices;

  // create VAO
  glBindVertexArray( m_vertexArrayObject );
  glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferObject);
  glEnableVertexAttribArray(m_posLoc);
  glEnableVertexAttribArray(m_colLoc);
  glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
  glVertexAttribPointer(m_colLoc, 4, GL_FLOAT, GL_FALSE, 0, (void*)(3 * sizeof(float) * m_nVertices));

  glBindVertexArray( 0 );

  return true;
}
allocated_memory_handle LoadModel(const char* path, model_definition* outModelDefinition) {
	Assimp::Importer importer;

	ZeroMemory(outModelDefinition, sizeof(*outModelDefinition));

	const aiScene* scene = importer.ReadFile(path, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType
		| aiProcess_ImproveCacheLocality | aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph | aiProcess_ValidateDataStructure 
		| aiProcess_ConvertToLeftHanded
		| aiProcess_LimitBoneWeights | aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals
		);

	if (!scene) {
		outModelDefinition->loadResult = IMPORT_ERROR;
		outModelDefinition->loadErrorMessage = importer.GetErrorString();
		return nullptr;
	}

	ModelMemory *modelData = new ModelMemory();
	auto& imported = *modelData;

	// submeshes

	uint32_t baseVertex = 0;
	uint32_t startIndex = 0;
	for (auto i = 0u; i< scene->mNumMeshes; ++i) {
		auto mesh = scene->mMeshes[i];

		auto submesh = submesh_definition();
		sprintf_s(submesh.name, mesh->mName.C_Str());
		submesh.baseVertex = baseVertex;
		submesh.indexCount = mesh->mNumFaces * 3;
		submesh.startIndex = startIndex;
		submesh.materialId = mesh->mMaterialIndex;

		imported.submeshes.push_back(submesh);

		startIndex += mesh->mNumFaces * 3;
		baseVertex += mesh->mNumVertices;
	}

	// materials

	for (auto i = 0u; i < scene->mNumMaterials; ++i) {
		auto material = scene->mMaterials[i];

		material_definition mat_def = {};
		aiString str;
		if (material->GetTextureCount(aiTextureType_DIFFUSE)) {
			
			material->GetTexture(aiTextureType_DIFFUSE, 0, &str);
			sprintf_s(mat_def.diffuseTexture, "%s", str.C_Str());
		}
		if (material->GetTextureCount(aiTextureType_AMBIENT)) {

			material->GetTexture(aiTextureType_AMBIENT, 0, &str);
			sprintf_s(mat_def.metallicnessTexture, "%s", str.C_Str());
		}
		if (material->GetTextureCount(aiTextureType_HEIGHT)) {

			material->GetTexture(aiTextureType_HEIGHT, 0, &str);
			sprintf_s(mat_def.normalmapTexture, "%s", str.C_Str());
		}
		if (material->GetTextureCount(aiTextureType_SHININESS)) {

			material->GetTexture(aiTextureType_SHININESS, 0, &str);
			sprintf_s(mat_def.roughnessTexture, "%s", str.C_Str());
		}
		if (material->GetTextureCount(aiTextureType_OPACITY)) {

			material->GetTexture(aiTextureType_OPACITY, 0, &str);
			sprintf_s(mat_def.alphaTexture, "%s", str.C_Str());
		}
	}

	// bones, collect phase

	std::unordered_map<u64, aiNode*> nodeByBoneNameHash;

	for (auto i = 0u; i < scene->mNumMeshes; ++i) {
		auto mesh = scene->mMeshes[i];
		if (mesh->HasBones()) {
			auto B = mesh->mNumBones;
			for (auto b = 0u; b < B;++b) {
				auto bone = mesh->mBones[b];
				auto name_hash = Hash::MurmurHash2_64(bone->mName.C_Str(), bone->mName.length, 0);
				nodeByBoneNameHash[name_hash] = scene->mRootNode->FindNode(bone->mName.C_Str());
			}
		}
	}

	// animations, channels

	std::unordered_map<u64, u32> channelIndexByNameHash;

	u32 positionsKeys = 0;
	u32 rotationKeys = 0;

	using namespace DirectX;

	// if any animations, collect channels
	if (scene->mNumAnimations) {
		auto sceneAnimation = scene->mAnimations[0];
		for (auto c = 0u; c < sceneAnimation->mNumChannels; ++c) {
			auto channel = sceneAnimation->mChannels[c];
			auto nameHash = Hash::MurmurHash2_64(channel->mNodeName.C_Str(), channel->mNodeName.length, 0);

			channelIndexByNameHash[nameHash] = c;

			/*animation_channel_t anim_channel = {};
			anim_channel.positions_offset = (u32)imported.animationPositions.size();
			anim_channel.positions_num = channel->mNumPositionKeys;
			anim_channel.rotations_offset = (u32)imported.animationRotations.size();
			anim_channel.rotations_num = channel->mNumRotationKeys;*/
			assert(channel->mNodeName.C_Str());

			/*imported.animationChannels.push_back(anim_channel);

			for (auto k = 0u; k < channel->mNumPositionKeys; ++k) {
				auto v = channel->mPositionKeys[k].mValue;
				
				position_key_t key;
				key.value = XMFLOAT3A((float)v.x, (float)v.y, (float)v.z);
				key.time = (float)channel->mPositionKeys[k].mTime;

				imported.animationPositions.push_back(key);
			}
			for (auto k = 0u; k < channel->mNumRotationKeys; ++k) {
				auto v = channel->mRotationKeys[k].mValue;

				rotation_key_t key;
				key.value = XMFLOAT4((float)v.x, (float)v.y, (float)v.z, (float)v.w);
				key.time = (float)channel->mRotationKeys[k].mTime;

				imported.animationRotations.push_back(key);
			}

			for (auto k = 0u; k < channel->mNumScalingKeys; ++k) {
				auto v = channel->mScalingKeys[k].mValue;
				assert(v.x >= 0.98f && v.y >= 0.98f && v.z >= 0.98f);
			}*/
		}

		// verify channels
		for (auto a = 1u; a < scene->mNumAnimations; ++a) {
			auto sceneAnimation = scene->mAnimations[a];

			for (auto c = 0u; c < sceneAnimation->mNumChannels; ++c) {
				auto channel = sceneAnimation->mChannels[c];
				auto nameHash = Hash::MurmurHash2_64(channel->mNodeName.C_Str(), channel->mNodeName.length, 0);
				auto entry = channelIndexByNameHash.find(nameHash);
				assert(entry != channelIndexByNameHash.end() && entry->second == c);
			}
		}
	}

	auto channelsCounter = 0;
	for (auto i = 0u; i < scene->mNumAnimations; ++i) {
		auto sceneAnimation = scene->mAnimations[i];

		animation_t animation = {};
		sprintf_s(animation.name, "%s", sceneAnimation->mName.C_Str());
		animation.name_hash = Hash::MurmurHash2_64(sceneAnimation->mName.C_Str(), sceneAnimation->mName.length, 0);
		animation.duration = (float)sceneAnimation->mDuration;
		animation.ticks_per_second = sceneAnimation->mTicksPerSecond != 0 ? (float)sceneAnimation->mTicksPerSecond : 25.f;
		animation.channels_offset = channelsCounter;
		animation.channels_num = sceneAnimation->mNumChannels;
		channelsCounter += animation.channels_num;

		auto position_keys_num = (u32)imported.animationPositions.size();
		auto rotation_keys_num = (u32)imported.animationRotations.size();

		for (auto c = 0u; c < sceneAnimation->mNumChannels; ++c) {
			auto channel = sceneAnimation->mChannels[c];

			animation_channel_t anim_channel = {};
			anim_channel.positions_offset = (u32)imported.animationPositions.size();
			anim_channel.positions_num = channel->mNumPositionKeys;
			anim_channel.rotations_offset = (u32)imported.animationRotations.size();
			anim_channel.rotations_num = channel->mNumRotationKeys;
			assert(channel->mNodeName.C_Str());

			imported.animationChannels.push_back(anim_channel);

			for (auto k = 0u; k < channel->mNumPositionKeys; ++k) {
				auto v = channel->mPositionKeys[k].mValue;

				position_key_t key;
				key.value = XMFLOAT3A((float)v.x, (float)v.y, (float)v.z);
				key.time = (float)channel->mPositionKeys[k].mTime;

				imported.animationPositions.push_back(key);
			}
			for (auto k = 0u; k < channel->mNumRotationKeys; ++k) {
				auto v = channel->mRotationKeys[k].mValue;

				rotation_key_t key;
				key.value = XMFLOAT4((float)v.x, (float)v.y, (float)v.z, (float)v.w);
				key.time = (float)channel->mRotationKeys[k].mTime;

				imported.animationRotations.push_back(key);
			}

			for (auto k = 0u; k < channel->mNumScalingKeys; ++k) {
				auto v = channel->mScalingKeys[k].mValue;
				assert(v.x >= 0.98f && v.y >= 0.98f && v.z >= 0.98f);
			}
		}

		animation.position_keys_num = (u32)imported.animationPositions.size() - position_keys_num;
		animation.rotation_keys_num = (u32)imported.animationRotations.size() - rotation_keys_num;

		imported.animations.push_back(animation);
	}

	// nodes, skeleton hierarchy

	auto startNode = scene->mRootNode;
	auto currentNode = scene->mRootNode;

	using namespace DirectX;
	std::unordered_map<u64, u32> nodeIndexBoneNameHash;

	auto make_node = [&](aiNode* inNode, u32 parent_index) {
		animation_node_t node = {};
		node.parent_index = parent_index;
		sprintf_s(node.name, "%s", inNode->mName.C_Str());

		auto localTransform = XMFLOAT4X4(&inNode->mTransformation.a1);
		XMStoreFloat4x4(&node.local_transform, XMMatrixTranspose(XMLoadFloat4x4(&localTransform)));

		auto nameHash = Hash::MurmurHash2_64(inNode->mName.C_Str(), inNode->mName.length, 0);
		node.name_hash = nameHash;
		auto findResult = channelIndexByNameHash.find(nameHash);
		node.channel_index = findResult != channelIndexByNameHash.end() ? findResult->second : NULL_INDEX;

		return node;
	};

	std::queue<decltype(scene->mRootNode)> nodesQueue;
	nodesQueue.push(scene->mRootNode);

	u32 parent_index = NULL_INDEX;
	imported.animationNodes.push_back(make_node(nodesQueue.front(), parent_index));
	nodeIndexBoneNameHash[imported.animationNodes.back().name_hash] = (u32)imported.animationNodes.size() - 1;

	while (!nodesQueue.empty()) {
		auto currentNode = nodesQueue.front();
		nodesQueue.pop();
		++parent_index;

		for (auto c = 0u; c < currentNode->mNumChildren; ++c) {
			auto nodeChild = currentNode->mChildren[c];
			nodesQueue.push(nodeChild);

			imported.animationNodes.push_back(make_node(nodeChild, parent_index));
			nodeIndexBoneNameHash[imported.animationNodes.back().name_hash] = (u32)imported.animationNodes.size() - 1;
		}
	}

	imported.indices.reserve(startIndex);
	imported.positions.resize(baseVertex);
	imported.texcoords.resize(baseVertex);
	imported.normals.resize(baseVertex);
	imported.tangents.resize(baseVertex);
	imported.bitangents.resize(baseVertex);
	imported.boneIndices.resize(baseVertex, XMUINT4(0, 0, 0, 0));
	imported.boneWeights.resize(baseVertex, XMFLOAT4(0, 0, 0, 0));

	using namespace DirectX;

	bool hasPositions = true;
	bool hasNormals = true;
	bool hasTangents = true;
	bool hasTextureCoords = true;

	u32 bone_offset = 0;
	for (auto i = 0u; i< scene->mNumMeshes; ++i) {
		auto mesh = scene->mMeshes[i];

		if (i == 0) {
			hasPositions = mesh->HasPositions();
			hasNormals = mesh->HasNormals();
			hasTangents = mesh->HasTangentsAndBitangents();
			hasTextureCoords = mesh->HasTextureCoords(0);
		}

		auto V = mesh->mNumVertices;
		auto vertex_offset = imported.submeshes[i].baseVertex;

		if (mesh->HasPositions() && hasPositions) {
			for (auto v = 0u; v < V; ++v) {
				imported.positions[vertex_offset + v] = XMFLOAT3(mesh->mVertices[v].x, mesh->mVertices[v].y, mesh->mVertices[v].z);
			}
		}
		if (mesh->HasNormals() && hasNormals) {
			for (auto v = 0u; v < V; ++v) {
				imported.normals[vertex_offset + v] = XMFLOAT3(mesh->mNormals[v].x, mesh->mNormals[v].y, mesh->mNormals[v].z);
			}
		}
		if (mesh->HasTangentsAndBitangents() && hasTangents) {
			for (auto v = 0u; v < V; ++v) {
				imported.tangents[vertex_offset + v] = XMFLOAT3(mesh->mTangents[v].x, mesh->mTangents[v].y, mesh->mTangents[v].z);
				imported.bitangents[vertex_offset + v] = XMFLOAT3(mesh->mBitangents[v].x, mesh->mBitangents[v].y, mesh->mBitangents[v].z);
			}
		}
		if (mesh->HasTextureCoords(0) && hasTextureCoords) {
			for (auto v = 0u; v < V; ++v) {
				imported.texcoords[vertex_offset + v] = XMFLOAT2(mesh->mTextureCoords[0][v].x, mesh->mTextureCoords[0][v].y);
			}
		}

		if (mesh->HasBones()) {
			/*imported.boneIndices.resize(V);
			imported.boneWeights.resize(V);*/
			std::vector<int> vertexBonesCtr(V);
			vertexBonesCtr.resize(V);

			auto vertexOffset = imported.submeshes[i].baseVertex;

			auto B = mesh->mNumBones;
			for (auto b = 0u; b < B;++b) {				
				auto bone = mesh->mBones[b];

				bone_definition bone_def = {};
				sprintf_s(bone_def.name, "%s", bone->mName.C_Str());
				bone_def.name_hash = Hash::MurmurHash2_64(bone_def.name, strlen(bone_def.name), 0);
				auto offsetMatrix = XMFLOAT4X4(&bone->mOffsetMatrix.a1);
				XMStoreFloat4x4(&bone_def.offset_matrix, XMMatrixTranspose(XMLoadFloat4x4(&offsetMatrix)));
				assert(nodeIndexBoneNameHash.find(bone_def.name_hash) != nodeIndexBoneNameHash.end());
				bone_def.node_index = nodeIndexBoneNameHash[bone_def.name_hash];
				imported.bones.push_back(bone_def);

				auto W = bone->mNumWeights;
				for (auto w = 0u; w < W; ++w) {
					auto vertexId = bone->mWeights[w].mVertexId + vertex_offset;
					auto weight = bone->mWeights[w].mWeight;

					auto innerIndex = vertexBonesCtr[bone->mWeights[w].mVertexId]++;
					assert(innerIndex < 4);

					switch (innerIndex) {
					case 0:
						imported.boneIndices[vertexId].x = b + bone_offset;
						imported.boneWeights[vertexId].x = weight;
						break;
					case 1:
						imported.boneIndices[vertexId].y = b + bone_offset;
						imported.boneWeights[vertexId].y = weight;
						break;
					case 2:
						imported.boneIndices[vertexId].z = b + bone_offset;
						imported.boneWeights[vertexId].z = weight;
						break;
					case 3:
						imported.boneIndices[vertexId].w = b + bone_offset;
						imported.boneWeights[vertexId].w = weight;
						break;
					}
					
				}
			}

			bone_offset += B;
		}

		auto F = mesh->mNumFaces;
		for (auto f = 0u; f < F; ++f) {
			for (auto k = 0u; k<mesh->mFaces[f].mNumIndices; ++k) {
				imported.indices.push_back(mesh->mFaces[f].mIndices[k]);
				assert(mesh->mFaces[f].mNumIndices == 3);
			}
		}
	}

	XMVECTOR vmin, vmax;
	vmin = XMLoadFloat3(imported.positions.data() + 0);
	vmax = vmin;
	for (auto i = 0u; i<imported.positions.size(); ++i) {
		vmin = XMVectorMin(vmin, XMLoadFloat3(imported.positions.data() + i));
		vmax = XMVectorMax(vmax, XMLoadFloat3(imported.positions.data() + i));
	}

	outModelDefinition->verticesNum = baseVertex;
	outModelDefinition->indicesNum = startIndex;

	outModelDefinition->trianglesNum = startIndex / 3;

	outModelDefinition->submeshesNum = (uint32_t)imported.submeshes.size();
	outModelDefinition->submeshes = imported.submeshes.data();

	outModelDefinition->indices = imported.indices.data();

	outModelDefinition->positions = imported.positions.data();
	outModelDefinition->normals = imported.normals.data();
	outModelDefinition->tangents = imported.tangents.data();
	outModelDefinition->bitangents = imported.bitangents.data();
	outModelDefinition->texcoords = imported.texcoords.data();
	outModelDefinition->boneIndices = imported.boneIndices.data();
	outModelDefinition->boneWeights = imported.boneWeights.data();

	outModelDefinition->bonesNum = (u32)imported.bones.size();
	outModelDefinition->bones = imported.bones.data();

	outModelDefinition->materialsNum = (u32)imported.materials.size();
	outModelDefinition->materials = imported.materials.data();

	outModelDefinition->animationNodes = imported.animationNodes.data();
	outModelDefinition->animationNodesNum = (u32)imported.animationNodes.size();
	outModelDefinition->animations = imported.animations.data();
	outModelDefinition->animationsNum = (u32)imported.animations.size();
	outModelDefinition->animationChannels = imported.animationChannels.data();
	outModelDefinition->animationPositionKeys = imported.animationPositions.data();
	outModelDefinition->animationRotationKeys = imported.animationRotations.data();

	XMStoreFloat3(&outModelDefinition->boundingBoxMin, vmin);
	XMStoreFloat3(&outModelDefinition->boundingBoxMax, vmax);

	return modelData;
}
Exemple #19
0
bool loadObj(const char *filename, Vertex* &obj, int &vertexCount)
{
	Assimp::Importer importer;
	bool hasColor = false;

	if(obj)
	{
        std::cerr << "[F] loadObj function used incorrectly." << std::endl;
		return false;
	}

	//load the file and make sure all polygons are triangles
	const aiScene *scene = importer.ReadFile(filename,aiProcess_Triangulate | aiProcess_GenNormals);
	
	if(!scene)
		return false;

	//get vertices from assimp
	aiVector3D *vertices = (*scene->mMeshes)->mVertices;
	//get normals from assimp
	aiVector3D *vertexNormals = (*scene->mMeshes)->mNormals;
	//get color information from assimp if exists
	aiColor4t<float> *colors = NULL;
	if((*scene->mMeshes)->HasVertexColors(0))
	{
		hasColor = true;
		colors = (*scene->mMeshes)->mColors[0];
	}

	//get vertex count from assimp
	vertexCount = (*scene->mMeshes)->mNumVertices;

	//allocate memory for obj
	obj = new Vertex[vertexCount];
	
	//add vertex, normals, and UVs to mesh object
	for(int i=0;i<vertexCount;++i)
	{
		obj[i].position[0] = vertices[i].x;
		obj[i].position[1] = vertices[i].y;
		obj[i].position[2] = vertices[i].z;
		
		obj[i].normal[0] = vertexNormals[i].x;
		obj[i].normal[1] = vertexNormals[i].y;
		obj[i].normal[2] = vertexNormals[i].z;

		if(hasColor)
		{
			obj[i].color[0] = colors[i].r;
			obj[i].color[1] = colors[i].g;
			obj[i].color[2] = colors[i].b;
		}
		else
		{
			obj[i].color[0] = 0.0;
			obj[i].color[1] = 1.0;
			obj[i].color[2] = 1.0;
		}
	}

	return true;
}
bool loadMesh_assimp(
	const char * path,
	std::vector<unsigned short> & out_indices,
	std::vector<glm::vec3> & out_vertices, 
	std::vector<glm::vec2> & out_uvs, 
	std::vector<glm::vec3> & out_normals)
{	
	Assimp::Importer importer;

	const aiScene* scene=importer.ReadFile(
		path, 
		aiProcess_GenSmoothNormals | 
		aiProcess_Triangulate | 
		aiProcess_CalcTangentSpace | 
		aiProcess_FlipUVs);

	if(!scene || scene->mFlags==AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
	{
		std::cout << "The file wasn't successfuly opened: " << path << std::endl;
		return false; 
	}

	aiMesh* mesh=scene->mMeshes[0];


	for(int i=0; i<mesh->mNumVertices; ++i)
	{
		glm::vec3 tmpVec;
		
		//position
		tmpVec.x=mesh->mVertices[i].x;
		tmpVec.y=mesh->mVertices[i].y;
		tmpVec.z=mesh->mVertices[i].z;
		out_vertices.push_back(tmpVec);
		
		//normals
		tmpVec.x=mesh->mNormals[i].x;
		tmpVec.y=mesh->mNormals[i].y;
		tmpVec.z=mesh->mNormals[i].z;
		out_normals.push_back(tmpVec);
	/*
		//tangent
		if(mesh->mTangents)
		{
			tmpVec.x=mesh->mTangents[i].x;
			tmpVec.y=mesh->mTangents[i].y;
			tmpVec.z=mesh->mTangents[i].z;
		}else{
			tmpVec.x=1.0;
			tmpVec.y=tmpVec.z=0;
		}			
		
		//colors
		if(mesh->mColors[0])
		{
			//!= material color
			tmpVec.x=mesh->mColors[0][i].r;
			tmpVec.y=mesh->mColors[0][i].g;
			tmpVec.z=mesh->mColors[0][i].b;				
		}else{
			tmpVec=defaultColor;
		}
		tmp.color=tmpVec;
	*/
		//Textures
		if(mesh->mTextureCoords[0])
		{
			tmpVec.x=mesh->mTextureCoords[0][i].x;
			tmpVec.y=mesh->mTextureCoords[0][i].y;				
		}else{
			tmpVec.x=tmpVec.y=tmpVec.z=0.0;
		}

		out_uvs.push_back(glm::vec2(tmpVec.x, tmpVec.y));
	}

	for(int i=0;i<mesh->mNumFaces; ++i)
	{
		aiFace face=mesh->mFaces[i];
		for(int j=0;j<face.mNumIndices;++j) //0..2
		{
			out_indices.push_back(face.mIndices[j]);
		}
	}

	return true;
}
Exemple #21
0
int run(int argc, char* argv[])
{
	Arguments args;

	args.add("help", 'h').description("Shows this help message.").flag(true);
	args.add("input", 'i').description("Input filename").required(true);
	args.add("output", 'o').description("Output filename").required(true);
	args.add("format", 'f').description("Output format. Overrides file extension.");
	args.add("axis", 'x').description("Change axis order of the cordinate system and polarity. (like +x+y+z, +x-z+y, ... )");
	args.add("textures", 't').description("Strip path from texture filenames").flag(true);

	// parse args
	if (!args.evaluate(argc, argv)) {
		cout << args.getErrorMessage() << endl;
		cout << args.getHelpMessage() << endl;
		return 1;
	}

	// print help
	if (argc == 1 || args.get("help").isFound()) {
		cout << args.getHelpMessage() << endl;
		return 0;
	}
 
	string inFileName = args.get("input").value();
	string outFileName = args.get("output").value();
	string outExtension;

	// determine file format
	if (!args.get("format").isFound())
	{
		string::size_type n;
		string s = outFileName;

		n = s.find_last_of('.');
		if (n != string::npos) {
			s = s.substr(n + 1);
		}
		if (s.empty()) {
			outExtension = "assbin";
			cout << "WARNING: No file extension was given. Using assbin format for default." << endl;
		}
		else {
			outExtension = s;
		}
	}
	else {
		outExtension = args.get("format").value();
	}

	// import scene 
	Assimp::Importer aiImporter;
	aiScene const * scene = aiImporter.ReadFile(inFileName.c_str(),
		aiProcessPreset_TargetRealtime_Quality |
		aiProcess_ConvertToLeftHanded |
		0);

	if (scene == nullptr) {
		cout << "Could not load model file" << inFileName << endl;
		cout << aiImporter.GetErrorString() << endl;
		return 1;
	}

	// flip axes
	if (args.get("axis").isFound() && scene->HasMeshes()) {
		string axesOrder = args.get("axis").value();
		if (axesOrder.length() != 6) {
			cout << args.getHelpMessage() << endl;
			return 1;
		}

		char order[3];
		char polarity[3];
		uint k = 3;
		while (k--) {
			char c = axesOrder.at(2*k), b = -1;
			char a = axesOrder.at(2*k+1), d = 1;
			switch (a) {
				case 'x': case 'X': b = 0; break;
				case 'y': case 'Y': b = 1; break;
				case 'z': case 'Z': b = 2; break;
				default:
					cout << args.getHelpMessage() << endl;
					return 1;
			}

			switch (c) {
				case '+': d = +1; break;
				case '-': d = -1; break;
			default:
				cout << args.getHelpMessage() << endl;
				return 1;
			}

			order[k] = b;
			polarity[k] = d;
		}

		for (uint i = 0; i < scene->mNumMeshes; i++) {
			aiMesh * const mesh = scene->mMeshes[i];
			for (uint j = 0; j < mesh->mNumVertices; j++) {
				swap_vertices(&mesh->mVertices[j], order, polarity);
				swap_vertices(&mesh->mNormals[j], order, polarity);
			}
		}
	}

	// strip texture filenames
	if (args.get("textures").isFound() && scene->HasMaterials()) {
		for (uint i = 0; i < scene->mNumMaterials; i++) {
			aiMaterial const * material = scene->mMaterials[i];
			for (uint j = 0; j < sizeof(textureTypes) / sizeof(textureTypes[0]); j++) {
				aiTextureType tt = textureTypes[j];
				for (uint k = 0; k < material->GetTextureCount(tt); k++) {
					aiString aiPath;
					material->GetTexture(tt, k, &aiPath);
					string path = aiPath.C_Str();
					{
						string s = path;
						string::size_type n, m;
						n = s.find_last_of('/');
						m = s.find_last_of('\\');
						if (n != string::npos) {
							s  = s.substr(n + 1);
						}
						else if (m != string::npos) {
							s = s.substr(m + 1);
						}

						if (!s.empty()) {
							path = s;
						}
					}

					// textura filenev vissza
					const aiMaterialProperty* pp = nullptr;
					if (aiGetMaterialProperty(material, AI_MATKEY_TEXTURE(tt, k), &pp) == AI_SUCCESS) {
						aiMaterialProperty* pProp = const_cast<aiMaterialProperty*>(pp);
						if (aiPTI_String == pProp->mType) {
							size_t newLen = path.length() + 4;
							char* newData = (char*)malloc(newLen);
							(*(uint*)(&newData[0])) = path.length();
							memcpy_s(&newData[4], newLen, path.c_str(), path.length());
							free(pProp->mData);
							pProp->mData = newData;
							pProp->mDataLength = newLen;
						}
					}
				}
			}
		}
	}

	// save 
	Assimp::Exporter aiExporter;

	if (aiExporter.Export(scene, outExtension, outFileName) != aiReturn_SUCCESS) {
		cout << "Could not save model file" << endl;
		cout << aiExporter.GetErrorString() << endl;
		return 1;
	}

	return 0;
}
Exemple #22
0
S3DModel* CAssParser::Load(const std::string& modelFilePath)
{
	logOutput.Print (LOG_MODEL, "Loading model: %s\n", modelFilePath.c_str() );
	std::string modelPath = modelFilePath.substr(0, modelFilePath.find_last_of('/'));
	std::string modelFileNameNoPath = modelFilePath.substr(modelPath.length()+1, modelFilePath.length());
	std::string modelName = modelFileNameNoPath.substr(0, modelFileNameNoPath.find_last_of('.'));
	std::string modelExt = modelFileNameNoPath.substr(modelFileNameNoPath.find_last_of('.'), modelFilePath.length());

	//! LOAD METADATA
	//! Load the lua metafile. This contains properties unique to Spring models and must return a table
	std::string metaFileName = modelFilePath + ".lua";
	CFileHandler* metaFile = new CFileHandler(metaFileName);
	if (!metaFile->FileExists()) {
		//! Try again without the model file extension
		metaFileName = modelPath + '/' + modelName + ".lua";
		metaFile = new CFileHandler(metaFileName);
	}
	LuaParser metaFileParser(metaFileName, SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP);
	if (!metaFileParser.Execute()) {
		if (!metaFile->FileExists()) {
			logOutput.Print(LOG_MODEL, "No meta-file '%s'. Using defaults.", metaFileName.c_str());
		} else {
			logOutput.Print(LOG_MODEL, "ERROR in '%s': %s. Using defaults.", metaFileName.c_str(), metaFileParser.GetErrorLog().c_str());
		}
	}
	//! Get the (root-level) model table
	const LuaTable& metaTable = metaFileParser.GetRoot();
	if (metaTable.IsValid()) logOutput.Print(LOG_MODEL, "Found valid model metadata in '%s'", metaFileName.c_str());


	//! LOAD MODEL DATA
	//! Create a model importer instance
	Assimp::Importer importer;

	//! Create a logger for debugging model loading issues
	Assimp::DefaultLogger::create("",Assimp::Logger::VERBOSE);
	const unsigned int severity = Assimp::Logger::Debugging|Assimp::Logger::Info|Assimp::Logger::Err|Assimp::Logger::Warn;
	Assimp::DefaultLogger::get()->attachStream( new AssLogStream(), severity );

	//! Give the importer an IO class that handles Spring's VFS
	importer.SetIOHandler( new AssVFSSystem() );

	//! Speed-up processing by skipping things we don't need
	importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, aiComponent_CAMERAS|aiComponent_LIGHTS|aiComponent_TEXTURES|aiComponent_ANIMATIONS);

#ifndef BITMAP_NO_OPENGL
	//! Optimize VBO-Mesh sizes/ranges
	GLint maxIndices  = 1024;
	GLint maxVertices = 1024;
	glGetIntegerv(GL_MAX_ELEMENTS_INDICES,  &maxIndices);
	glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxVertices); //FIXME returns not optimal data, at best compute it ourself! (pre-TL cache size!)
	importer.SetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,   maxVertices);
	importer.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, maxIndices/3);
#endif

	//! Read the model file to build a scene object
	logOutput.Print(LOG_MODEL, "Importing model file: %s\n", modelFilePath.c_str() );
	const aiScene* scene = importer.ReadFile( modelFilePath, ASS_POSTPROCESS_OPTIONS );
	if (scene != NULL) {
		logOutput.Print(LOG_MODEL, "Processing scene for model: %s (%d meshes / %d materials / %d textures)", modelFilePath.c_str(), scene->mNumMeshes, scene->mNumMaterials, scene->mNumTextures );
	} else {
		logOutput.Print (LOG_MODEL, "Model Import Error: %s\n",  importer.GetErrorString());
	}

	SAssModel* model = new SAssModel;
	model->name = modelFilePath;
	model->type = MODELTYPE_ASS;
	model->scene = scene;
	//model->meta = &metaTable;

	//! Gather per mesh info
	CalculatePerMeshMinMax(model);

	//! Assign textures
	//! The S3O texture handler uses two textures.
	//! The first contains diffuse color (RGB) and teamcolor (A)
	//! The second contains glow (R), reflectivity (G) and 1-bit Alpha (A).
	if (metaTable.KeyExists("tex1")) {
		model->tex1 = metaTable.GetString("tex1", "default.png");
	} else {
		//! Search for a texture
		std::vector<std::string> files = CFileHandler::FindFiles("unittextures/", modelName + ".*");
		for(std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) {
			std::string texPath = std::string(*fi);
			model->tex1 = texPath.substr(texPath.find('/')+1, texPath.length());
			break; //! there can be only one!
		}
	}
	if (metaTable.KeyExists("tex2")) {
		model->tex2 = metaTable.GetString("tex2", "");
	} else {
		//! Search for a texture
		std::vector<std::string> files = CFileHandler::FindFiles("unittextures/", modelName + "2.*");
		for(std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) {
			std::string texPath = std::string(*fi);
			model->tex2 = texPath.substr(texPath.find('/')+1, texPath.length());
			break; //! there can be only one!
		}
	}
	model->flipTexY = metaTable.GetBool("fliptextures", true); //! Flip texture upside down
	model->invertTexAlpha = metaTable.GetBool("invertteamcolor", true); //! Reverse teamcolor levels

	//! Load textures
	logOutput.Print(LOG_MODEL, "Loading textures. Tex1: '%s' Tex2: '%s'", model->tex1.c_str(), model->tex2.c_str());
	texturehandlerS3O->LoadS3OTexture(model);

	//! Load all pieces in the model
	logOutput.Print(LOG_MODEL, "Loading pieces from root node '%s'", scene->mRootNode->mName.data);
	LoadPiece(model, scene->mRootNode, metaTable);

	//! Update piece hierarchy based on metadata
	BuildPieceHierarchy( model );

	//! Simplified dimensions used for rough calculations
	model->radius = metaTable.GetFloat("radius", model->radius);
	model->height = metaTable.GetFloat("height", model->height);
	model->relMidPos = metaTable.GetFloat3("midpos", model->relMidPos);
	model->mins = metaTable.GetFloat3("mins", model->mins);
	model->maxs = metaTable.GetFloat3("maxs", model->maxs);

	//! Calculate model dimensions if not set
	if (!metaTable.KeyExists("mins") || !metaTable.KeyExists("maxs")) CalculateMinMax( model->rootPiece );
	if (model->radius < 0.0001f) CalculateRadius( model );
	if (model->height < 0.0001f) CalculateHeight( model );

	//! Verbose logging of model properties
	logOutput.Print(LOG_MODEL_DETAIL, "model->name: %s", model->name.c_str());
	logOutput.Print(LOG_MODEL_DETAIL, "model->numobjects: %d", model->numPieces);
	logOutput.Print(LOG_MODEL_DETAIL, "model->radius: %f", model->radius);
	logOutput.Print(LOG_MODEL_DETAIL, "model->height: %f", model->height);
	logOutput.Print(LOG_MODEL_DETAIL, "model->mins: (%f,%f,%f)", model->mins[0], model->mins[1], model->mins[2]);
	logOutput.Print(LOG_MODEL_DETAIL, "model->maxs: (%f,%f,%f)", model->maxs[0], model->maxs[1], model->maxs[2]);

	logOutput.Print (LOG_MODEL, "Model %s Imported.", model->name.c_str());
	return model;
}
Exemple #23
0
bool LoadAssimp( string file, vector <vec3> &vertices, vector <vec2> &uvs, vector <vec3> &normals, vector <GLuint> &indices ){
   /*
      Dane wyjściowe dla wierzchołków
   */
   vertices.clear();
   /*
      Dane wyjściowe dla UV Map
   */
   uvs.clear();
   /*
      Dane wyjściowe dla Normalnych
   */
   normals.clear();
   /*
      Dane wyjściowe dla kolejności trójkątów
   */
   indices.clear();
   /*
      Tworzenie importer dla ładowania danych.
   */
   Assimp::Importer importer;
   /*
      Wczytywanie pliku file (.obj)
   */
   const aiScene* scene = importer.ReadFile( file.c_str(), 0 );
   /*
      Sprawdzenie czy nie ma błedu.
   */
   if( !scene ){
      cout<<"importer.ReadFile ("<<file<<"):  "<<importer.GetErrorString()<<"\n";
      return false;
   }
   /*
      Wczytujemy tylko pierwszą część obiektu, inne pomijamy(występuje w obiektach kilku elementowych/częściowych).
   */
   const aiMesh* mesh = scene->mMeshes[0];
   unsigned int i = 0;
   /*
      Wektor dla pobierania danych.
   */
   aiVector3D tmp;
   //vertices:
   /*
      Wierzchołki obiektu.
   */
   vertices.reserve( mesh->mNumVertices );
   for( i = 0; i < mesh->mNumVertices; ++i ){
      tmp = mesh->mVertices[i];
      vertices.push_back( vec3( tmp.x, tmp.y, tmp.z ) );
   }
   //uvs:
   /*
      UV Mapy
   */
   uvs.reserve( mesh->mNumVertices );
   for( i = 0; i < mesh->mNumVertices; ++i ){
      tmp = mesh->mTextureCoords[0][i];
      //important!
      //This is done because most images have the top y-axis inversed with OpenGL's top y-axis.
      //or conver in shader
      uvs.push_back( glm::vec2( tmp.x, 1.0 - tmp.y ) );
   }
   //normals:
   /*
      Normalne
   */
   normals.reserve( mesh->mNumVertices );
   for( i = 0; i < mesh->mNumVertices; ++i ){
      tmp = mesh->mNormals[i];
      normals.push_back( vec3( tmp.x, tmp.y, tmp.z ) );
   }
   //indices:
   /*
      Kolejność rysowania trójkątów oraz jak każdy jest reprezentowany przez wierzchołki.
   */
   indices.reserve( 3*mesh->mNumFaces );
   for( i = 0; i < mesh->mNumFaces; ++i ){
      indices.push_back( mesh->mFaces[i].mIndices[0] );
      indices.push_back( mesh->mFaces[i].mIndices[1] );
      indices.push_back( mesh->mFaces[i].mIndices[2] );
   }
   return true;
}
 virtual bool binaryImporterTest() {
     Assimp::Importer importer;
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/2CylinderEngine-glTF-Binary/2CylinderEngine.glb", aiProcess_ValidateDataStructure);
     return nullptr != scene;
 }
Exemple #25
0
Mesh::Mesh(string modelPath) : Resource(modelPath, MY_TYPE_INDEX)
{
	Assimp::Importer importer;

	const aiScene* scene = importer.ReadFile(modelPath,
		aiProcess_CalcTangentSpace |
		aiProcess_JoinIdenticalVertices |
		aiProcess_FindInvalidData |
		aiProcess_GenNormals |
		aiProcess_ImproveCacheLocality |
		aiProcess_Triangulate |
		aiProcess_FlipWindingOrder |
		aiProcess_SortByPType);

	size_t vertCount = 0, faceCount = 0;

	for (size_t i = 0; i < scene->mNumMeshes; ++i)
	{
		vertCount += scene->mMeshes[i]->mNumVertices;
		faceCount += scene->mMeshes[i]->mNumFaces * 3;
	}

	vec3 upper, lower;
	size_t vertOffset = 0, faceOffset = 0;
	vertex* verts = new vertex[vertCount];
	unsigned int* faces = new unsigned int[faceCount];

	lower.x = std::min(lower.x, scene->mMeshes[0]->mVertices[0].x);
	lower.y = std::min(lower.y, scene->mMeshes[0]->mVertices[0].y);
	lower.z = std::min(lower.z, scene->mMeshes[0]->mVertices[0].z);
	upper.x = std::max(upper.x, scene->mMeshes[0]->mVertices[0].x);
	upper.y = std::max(upper.y, scene->mMeshes[0]->mVertices[0].y);
	upper.z = std::max(upper.z, scene->mMeshes[0]->mVertices[0].z);

	for (size_t m = 0; m < scene->mNumMeshes; ++m)
	{
		aiMesh* mesh = scene->mMeshes[m];

		for (size_t i = 0; i < mesh->mNumVertices; ++i)
		{
			vertex vert = { DirectX::XMFLOAT3(mesh->mVertices[i].v),
							DirectX::XMFLOAT3(mesh->mNormals[i].v),
							DirectX::XMFLOAT3(mesh->mTangents[i].v),
							DirectX::XMFLOAT2(mesh->mTextureCoords[0][i].x, 1 - mesh->mTextureCoords[0][i].y) };
			verts[vertOffset + i] = vert;

			upper = vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
			lower = upper;
		}

		for (size_t i = 0; i < mesh->mNumFaces; ++i)
		{
			faces[faceOffset + i * 3] = vertOffset + mesh->mFaces[i].mIndices[0];
			faces[faceOffset + i * 3 + 1] = vertOffset + mesh->mFaces[i].mIndices[1];
			faces[faceOffset + i * 3 + 2] = vertOffset + mesh->mFaces[i].mIndices[2];
		}

		vertOffset += mesh->mNumVertices;
		faceOffset += mesh->mNumFaces * 3;
	}

	bounds.halfSize = vec3(upper.x - lower.x, upper.y - lower.y, upper.z - lower.z);
	bounds.halfSize /= 2.0f;
	bounds.center.x = lower.x + bounds.halfSize.x;
	bounds.center.y = lower.y + bounds.halfSize.y;
	bounds.center.z = lower.z + bounds.halfSize.z;

	float dist = 0;
	vec3 furthest;
	for (size_t i = 0; i < vertCount; ++i)
	{
		float distanceCheck = distanceSquared(vec3(verts[i].position.x, verts[i].position.y, verts[i].position.z), bounds.center);
		if (distanceCheck > dist)
		{
			furthest = vec3(verts[i].position.x, verts[i].position.y, verts[i].position.z);
			dist = distanceCheck;
		}
	}

	dist = 0;
	vec3 furthest2;
	for (size_t i = 0; i < vertCount; ++i)
	{
		float distanceCheck = distanceSquared(vec3(verts[i].position.x, verts[i].position.y, verts[i].position.z), furthest);
		if (distanceCheck > dist)
		{
			furthest2 = vec3(verts[i].position.x, verts[i].position.y, verts[i].position.z);
			dist = distanceCheck;
		}
	}

	bounds.sphere = furthest2 - furthest;
	bounds.radius = length(bounds.sphere) / 2.0f;
	bounds.sphere = furthest + normalize(bounds.sphere) * bounds.radius;

	D3D11_BUFFER_DESC vbd;
	vbd.Usage = D3D11_USAGE_IMMUTABLE;
	vbd.ByteWidth = sizeof(vertex) * vertCount;
	vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vbd.CPUAccessFlags = 0;
	vbd.MiscFlags = 0;
	vbd.StructureByteStride = 0;

	D3D11_SUBRESOURCE_DATA initialVertexData;
	initialVertexData.pSysMem = verts;

	HR(DEVICE->CreateBuffer(&vbd, &initialVertexData, &vertexBuffer));

	D3D11_BUFFER_DESC ibd;
	ibd.Usage = D3D11_USAGE_IMMUTABLE;
	ibd.ByteWidth = sizeof(unsigned int) * faceCount;
	ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
	ibd.CPUAccessFlags = 0;
	ibd.MiscFlags = 0;
	ibd.StructureByteStride = 0;

	D3D11_SUBRESOURCE_DATA initialIndexData;
	initialIndexData.pSysMem = faces;

	HR(DEVICE->CreateBuffer(&ibd, &initialIndexData, &indexBuffer));

	elementArraySize = faceCount;
	
	delete[] verts;
	delete[] faces;
}