Ejemplo n.º 1
0
//! Loads and returns a skinned model from a file.
SkinnedModel* ModelImporter::LoadSkinnedModel(string filename)
{
	// Is the model already loaded?
	if(mSkinnedModelMap.find(filename) != mSkinnedModelMap.end())
		return mSkinnedModelMap[filename];

	Assimp::Importer importer;
	mFilename =	filename;
	SkinnedModel* model = NULL;

	// Important! Makes sure that if the angle between two face normals is > 80 they are not smoothed together.
	// Since the angle between a cubes face normals is 90 the lighting looks very bad if we don't specify this.
	importer.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, 80.0f);	
	importer.SetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS, 1);
	importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE);

	// Load scene from the file.
	const aiScene* scene = importer.ReadFile(filename, 
		aiProcess_CalcTangentSpace | 
		aiProcess_Triangulate | 
		aiProcess_GenSmoothNormals | 
		aiProcess_SplitLargeMeshes | 
		aiProcess_ConvertToLeftHanded | 
		aiProcess_SortByPType);

	if(scene)
	{
		// Create the model that is getting filled out.
		model = new SkinnedModel();

		// Create the animator.
		SceneAnimator* animator = new SceneAnimator();
		animator->Init(scene);
		model->SetAnimator(animator);

		// Loop through all meshes.
		for(int j = 0; j < scene->mNumMeshes; j++)
		{
			aiMesh* assimpMesh = scene->mMeshes[j];

			// Calculate vertex weight and bone indices.
			vector<Weights> weights = CalculateWeights(assimpMesh, animator);

			vector<SkinnedVertex> vertices;
			vector<UINT> indices;

			// Add vertices to the vertex list.
			for(int i = 0; i < assimpMesh->mNumVertices; i++) 
			{
				aiVector3D v = assimpMesh->mVertices[i];
				aiVector3D n = assimpMesh->mNormals[i];
				aiVector3D t = aiVector3D(0, 0, 0);
				if(assimpMesh->HasTextureCoords(0))
					t = assimpMesh->mTextureCoords[0][i];

				n = n.Normalize();

				// Pos, normal and texture coordinates.
				SkinnedVertex vertex(v.x, v.y, v.z, n.x, n.y, n.z, 0, 0, 1, t.x, t.y);

				// Bone indices and weights.
				for(int k = 0; k < weights[i].boneIndices.size(); k++) 
					vertex.BoneIndices[k] = weights[i].boneIndices[k];

				vertex.Weights.x = weights[i].weights.size() >= 1 ? weights[i].weights[0] : 0;
				vertex.Weights.y = weights[i].weights.size() >= 2 ? weights[i].weights[1] : 0;
				vertex.Weights.z = weights[i].weights.size() >= 3 ? weights[i].weights[2] : 0;

				vertices.push_back(vertex);
			}

			// Add indices to the index list.
			for(int i = 0; i < assimpMesh->mNumFaces; i++) 
				for(int k = 0; k < assimpMesh->mFaces[i].mNumIndices; k++) 
					indices.push_back(assimpMesh->mFaces[i].mIndices[k]);

			// Get the path to the texture in the directory.
			aiString path;
			aiMaterial* material = scene->mMaterials[assimpMesh->mMaterialIndex];
			material->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path);
			FindValidPath(&path);

			// Extract all the ambient, diffuse and specular colors.
			aiColor4D ambient, diffuse, specular;
			material->Get(AI_MATKEY_COLOR_AMBIENT, ambient);
			material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
			material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
				
			// Create the mesh and its primitive.
			SkinnedMesh* mesh = new SkinnedMesh();

			Primitive* primitive = new Primitive(GlobalApp::GetD3DDevice(), vertices, indices);
			mesh->SetPrimitive(primitive);
			mesh->SetVertices(vertices);
			mesh->SetIndices(indices);
			mPrimtiveFactory->AddPrimitive(path.C_Str(), primitive);

			// Replace .tga with .bmp [HACK].
			string texturePath = path.C_Str();
			int tgaPos = texturePath.find_first_of(".tga");
			if(tgaPos != string::npos) {
				texturePath.replace(texturePath.size()-4, 4, ".bmp");
				path = texturePath;
			}

			// Any texture?
			if(_stricmp(path.C_Str(), "") != 0)
				mesh->LoadTexture(path.C_Str());

			// Any normal map?
			aiString nmap;
			material->Get(AI_MATKEY_TEXTURE_HEIGHT(0), nmap);
			FindValidPath(&nmap);
			if(_stricmp(nmap.C_Str(), "") != 0)	
				mesh->SetNormalMap(GlobalApp::GetGraphics()->LoadTexture(nmap.C_Str()));

			// [NOTE] The material is set to white.
			mesh->SetMaterial(Material(Colors::White));
			//mesh->SetMaterial(Material(diffuse, diffuse, diffuse));

			model->SetFilename(filename);

			// Add the mesh to the model.
			model->AddMesh(mesh);
		}

		// Pre-calculate the bounding box.
		model->CalculateAABB();

		// Add the newly created mesh to the map and return it.
		mSkinnedModelMap[filename] = model;
		return mSkinnedModelMap[filename];
	}
	else {
		char buffer[246];
		sprintf(buffer, "Error loading model: %s", filename.c_str());
		MessageBox(0, buffer, "Error!", 0);
		mSkinnedModelMap[filename] = LoadSkinnedModel("models/box.obj");
		return mSkinnedModelMap[filename];
	}
}
Ejemplo n.º 2
0
void
Mesh::bind()
{
    Assimp::Importer importer;    

    unsigned int flags = aiProcess_Triangulate | aiProcess_JoinIdenticalVertices;
    
    if (generateVertexNormals) {
	importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, aiComponent_NORMALS);
	importer.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, 30.0f);
	// ignore normals in file and generate per vertex normals
	flags |= aiProcess_RemoveComponent | aiProcess_GenSmoothNormals;
    } else {
	// generate face normals if not already present in the file
	flags |= aiProcess_GenNormals;
    }
    
    const aiScene* scene = importer.ReadFile(fileName, flags);
    
    if (!scene) {
	return;
    }

    std::vector<float> vertices;
    std::vector<float> normals;
    std::vector<float> textureCoordinates;
    
    min.x = 1e38;
    min.y = 1e38;
    min.z = 1e38;
    max.x = -1e38;
    max.y = -1e38;
    max.z = -1e38;

    const struct aiNode* nd = scene->mRootNode;
    for (unsigned int n = 0; n < nd->mNumMeshes; ++n) {
	const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
	
	std::cout << "vertices: " << mesh->mNumVertices << ", faces: " << mesh->mNumFaces << std::endl;
	
	for (unsigned int t = 0; t < mesh->mNumFaces; ++t) {
	    const struct aiFace* face = &mesh->mFaces[t];
	    switch (face->mNumIndices) {
	    case 3:
		break;
	    default:
		std::cout << "ignored" << std::endl;
		continue;
	    }
	    for (unsigned int idx= 0;idx < face->mNumIndices;idx++) {
		float x = mesh->mVertices[face->mIndices[idx]].x;
		float y = mesh->mVertices[face->mIndices[idx]].y;
		float z = mesh->mVertices[face->mIndices[idx]].z;
		float nx = mesh->mNormals[face->mIndices[idx]].x;
		float ny = mesh->mNormals[face->mIndices[idx]].y;
		float nz = mesh->mNormals[face->mIndices[idx]].z;

		if (x < min.x) {
		    min.x = x;
		}
		if (y < min.y) {
		    min.y = y;
		}
		if (z < min.z) {
		    min.z = z;
		}
		if (x > max.x) {
		    max.x = x;
		}
		if (y > max.y) {
		    max.y = y;
		}
		if (z > max.z) {
		    max.z = z;
		}
		vertices.push_back(x);
		vertices.push_back(y);
		vertices.push_back(z);
		vertices.push_back(1.0f);
		normals.push_back(nx);
		normals.push_back(ny);
		normals.push_back(nz);
		normals.push_back(0.0f);
		textureCoordinates.push_back(x / 8);
		textureCoordinates.push_back(z / 8);
	    }
	}
    }

    std::cout << "bounding box: min = "
	    << min.x << ", " << min.y << ", " << min.z
	    << " - max = "
	    << max.x << ", " << max.y << ", " << max.z
	    << std::endl;
 
//    vertices.clear();
//    normals.clear();
//    quad(vertices, normals, 0, 1, 2, 3);
//    quad(vertices, normals, 0, 4, 5, 1);
//    quad(vertices, normals, 1, 5, 6, 2);
//    quad(vertices, normals, 2, 6, 7, 3);
//    quad(vertices, normals, 3, 7, 4, 0);
//    quad(vertices, normals, 4, 7, 6, 5);
    
    count = vertices.size();

    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), &vertices[0], GL_STATIC_DRAW);

    glGenBuffers(1, &normalBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, normalBuffer);
    glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(float), &normals[0], GL_STATIC_DRAW);

    glGenBuffers(1, &textureBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, textureBuffer);
    glBufferData(GL_ARRAY_BUFFER, textureCoordinates.size() * sizeof(float), &textureCoordinates[0], GL_STATIC_DRAW);
}
Ejemplo n.º 3
0
//! Loads and returns a static model from a file.
StaticModel* ModelImporter::LoadStaticModel(string filename)
{
	// Is the model already loaded?
	if(mStaticModelMap.find(filename) != mStaticModelMap.end())
		return mStaticModelMap[filename];

	Assimp::Importer importer;
	mFilename =	filename;
	StaticModel* model = NULL;

	// Important! Makes sure that if the angle between two face normals is > 80 they are not smoothed together.
	// Since the angle between a cubes face normals is 90 the lighting looks very bad if we don't specify this.
	importer.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, 80.0f);	
	importer.SetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS, 1);
	importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE);

	// Load scene from the file.
	const aiScene* scene = importer.ReadFile(filename, 
		aiProcess_CalcTangentSpace		| 
		aiProcess_Triangulate			| 
		aiProcess_GenSmoothNormals		|
		aiProcess_SplitLargeMeshes		|
		aiProcess_ConvertToLeftHanded	|
		aiProcess_SortByPType);

	// Successfully loaded the scene.
	if(scene)
	{
		// Create the model that is getting filled out.
		model = new StaticModel();

		// Loop through all meshes.
		for(int i = 0; i < scene->mNumMeshes; i++)
		{
			aiMesh* assimpMesh = scene->mMeshes[i];
			vector<Vertex>	vertices;
			vector<UINT>	indices;

			// Add vertices to the vertex list.
			for(int i = 0; i < assimpMesh->mNumVertices; i++) 
			{
				aiVector3D v = assimpMesh->mVertices[i];
				aiVector3D n = assimpMesh->mNormals[i];
				aiVector3D t = aiVector3D(0, 0, 0);
				if(assimpMesh->HasTextureCoords(0))
					t = assimpMesh->mTextureCoords[0][i];

				n = n.Normalize();
				Vertex vertex(v.x, v.y, v.z, n.x, n.y, n.z, 0, 0, 0, t.x, t.y);
				vertices.push_back(vertex);
			}

			// Add indices to the index list.
			for(int i = 0; i < assimpMesh->mNumFaces; i++) 
				for(int j = 0; j < assimpMesh->mFaces[i].mNumIndices; j++) 
					indices.push_back(assimpMesh->mFaces[i].mIndices[j]);

			// Get the path to the texture in the directory.
			aiString path;
			aiMaterial* material = scene->mMaterials[assimpMesh->mMaterialIndex];
			material->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path);
			FindValidPath(&path);

			// Extract all the ambient, diffuse and specular colors.
			aiColor4D ambient, diffuse, specular;
			material->Get(AI_MATKEY_COLOR_AMBIENT, ambient);
			material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
			material->Get(AI_MATKEY_COLOR_SPECULAR, specular);

			// Create the mesh and its primitive.
			StaticMesh* mesh = new StaticMesh();
			Primitive* primitive = new Primitive(GlobalApp::GetD3DDevice(), vertices, indices);
			mesh->SetPrimitive(primitive);
			mesh->SetVertices(vertices);
			mesh->SetIndices(indices);
			mPrimtiveFactory->AddPrimitive(path.C_Str(), primitive);

			// Any texture?
			if(_stricmp(path.C_Str(), "") != 0)
				mesh->LoadTexture(path.C_Str());

			// Any normal map?
			aiString nmap;
			material->Get(AI_MATKEY_TEXTURE_HEIGHT(0), nmap);
			FindValidPath(&nmap);
			if(_stricmp(nmap.C_Str(), "") != 0)	
				mesh->SetNormalMap(GlobalApp::GetGraphics()->LoadTexture(nmap.C_Str()));

			// [NOTE] The material is set to white.
			mesh->SetMaterial(Material(Colors::White)); // Was  before [NOTE]

			model->SetFilename(filename);

			// Add the mesh to the model.
			model->AddMesh(mesh);
		}

		// Add to the model map and return it.
		mStaticModelMap[filename] = model;
		return mStaticModelMap[filename];
	}
	else {
		char buffer[246];
		sprintf(buffer, "Error loading model: %s", filename.c_str());
		MessageBox(0, buffer, "Error!", 0);
		mStaticModelMap[filename] = LoadStaticModel("models/box.obj");
		return mStaticModelMap[filename];
	}
}