Add model loader, modify scene to load a car
This commit is contained in:
parent
29defbaba9
commit
50e3b60c28
@ -13,6 +13,7 @@
|
||||
#include <utilities/glfont.h>
|
||||
#include <utilities/glutils.h>
|
||||
#include <utilities/imageLoader.hpp>
|
||||
#include <utilities/modelLoader.hpp>
|
||||
#include <utilities/mesh.h>
|
||||
#include <utilities/shader.hpp>
|
||||
#include <utilities/shapes.h>
|
||||
@ -34,7 +35,9 @@ uint previousKeyFrame = 0;
|
||||
|
||||
SceneNode* rootNode;
|
||||
SceneNode* plainNode;
|
||||
SceneNode* carNode;
|
||||
SceneNode* boxNode;
|
||||
SceneNode* sphereNode;
|
||||
SceneNode* hudNode;
|
||||
SceneNode* textNode;
|
||||
|
||||
@ -113,6 +116,7 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
|
||||
default_shader->makeBasicShader("../res/shaders/simple.vert", "../res/shaders/simple.frag");
|
||||
|
||||
Mesh box = generateBox(50, 50, 50);
|
||||
Mesh sphere = generateSphere(10, 100, 100);
|
||||
Mesh plain = generateSegmentedPlane(1000, 1000, 100, 100, 3);
|
||||
Mesh hello_world = generateTextGeometryBuffer("Skjer'a bagera?", 1.3, 2);
|
||||
t_perlin.repeat_mirrored = true;
|
||||
@ -127,6 +131,28 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
|
||||
rootNode->children.push_back(lightNode[i]);
|
||||
}
|
||||
|
||||
|
||||
carNode = loadModelScene("../res/models/beetle/scene.gltf", {
|
||||
{-1, Material::diffuse({0.3, 0.3, 1.0, 1.0}, 30)},// default
|
||||
//{ 0, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// Blue_Metal
|
||||
//{ 1, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// Metal
|
||||
//{ 2, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// Front_Light_Glass
|
||||
{ 3, Material::diffuse({0.2, 0.2, 0.2, 1.0})},// Black_Rubber
|
||||
//{ 4, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// Mirror
|
||||
//{ 5, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// Black_Metal
|
||||
//{ 6, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// Plastic
|
||||
{ 7, Material::diffuse({0.1, 0.1, 0.1, 1.0})},// Window_Glass
|
||||
//{ 8, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// Material
|
||||
//{ 9, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// Glossy_metal
|
||||
//{10, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// Rogh_Metal
|
||||
//{11, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// License_Plate_Metal
|
||||
//{12, Material::diffuse({1.0, 1.0, 1.0, 1.0})},// License_Plate_Frame
|
||||
//{13, Material::diffuse({1.0, 1.0, 1.0, 1.0})},//
|
||||
});
|
||||
carNode->position = {500, 500, 100};
|
||||
carNode->scale *= 100;
|
||||
rootNode->children.push_back(carNode);
|
||||
|
||||
//create the scene:
|
||||
plainNode = createSceneNode();
|
||||
plainNode->setTexture(&t_plain_diff, &t_plain_normal, &t_perlin);
|
||||
@ -136,6 +162,7 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
|
||||
plainNode->displacementCoefficient = 40;
|
||||
rootNode->children.push_back(plainNode);
|
||||
|
||||
/*
|
||||
boxNode = createSceneNode();
|
||||
boxNode->setTexture(&t_cobble_diff, &t_cobble_normal);
|
||||
boxNode->setMesh(&box);
|
||||
@ -146,6 +173,13 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
|
||||
boxNode->displacementCoefficient = 40;
|
||||
rootNode->children.push_back(boxNode);
|
||||
|
||||
sphereNode = createSceneNode();
|
||||
sphereNode->setTexture(&t_cobble_diff, &t_cobble_normal);
|
||||
sphereNode->setMesh(&sphere);
|
||||
sphereNode->scale *= 2;
|
||||
sphereNode->scale.z *= 20;
|
||||
//lightNode[1]->children.push_back(sphereNode);
|
||||
*/
|
||||
|
||||
lightNode[0]->position = {-600, 1400, 800};
|
||||
lightNode[0]->color_emissive = vec3(0.35);
|
||||
|
180
src/utilities/modelLoader.cpp
Normal file
180
src/utilities/modelLoader.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
#include "modelLoader.hpp"
|
||||
|
||||
#include <assimp/Importer.hpp> // C++ importer interface
|
||||
#include <assimp/postprocess.h> // Post processing flags
|
||||
#include <assimp/scene.h> // aiScene and aiNode
|
||||
#include <assimp/material.h> // aiMaterial
|
||||
#include <assimp/mesh.h> // aiMesh
|
||||
#include <assimp/texture.h> // aiTexture
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include "mesh.h"
|
||||
#include "imageLoader.hpp"
|
||||
|
||||
typedef unsigned int uint;
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
SceneNode* buildSceneNodes(
|
||||
const aiNode* node,
|
||||
const vector<Mesh>& meshes,
|
||||
const vector<PNGImage>& textures,
|
||||
const vector<Material*>& mat_lookup) {
|
||||
if (DEBUG) cout << "Building node from " << node->mName.C_Str() << "..." << endl;
|
||||
|
||||
// filter semantic-only nodes
|
||||
if (node->mTransformation.IsIdentity()
|
||||
&& node->mNumMeshes == 0
|
||||
&& node->mNumChildren == 1)
|
||||
return buildSceneNodes(node->mChildren[0], meshes, textures, mat_lookup);
|
||||
|
||||
SceneNode* out = createSceneNode();
|
||||
|
||||
if (!node->mTransformation.IsIdentity()) {
|
||||
aiQuaterniont<float> rotation;
|
||||
aiVector3t<float> position, scaling;
|
||||
node->mTransformation.Decompose(scaling, rotation, position);
|
||||
for(uint i=0; i<3; i++) out->position[i] = position[i];
|
||||
for(uint i=0; i<3; i++) out->scale[i] = scaling[i];
|
||||
out->rotation = glm::eulerAngles(glm::quat(
|
||||
rotation.w, rotation.x, rotation.y, rotation.z));
|
||||
}
|
||||
|
||||
for (uint i = 0; i < node->mNumMeshes; i++) {
|
||||
SceneNode* mesh_node = createSceneNode();
|
||||
out->children.push_back(mesh_node);
|
||||
uint meshidx = node->mMeshes[i];
|
||||
|
||||
mesh_node->basecolor = mat_lookup[meshidx]->basecolor;
|
||||
mesh_node->shininess = mat_lookup[meshidx]->shininess;
|
||||
|
||||
// mesh_node.setTexture(&meshes[node->mMeshes[i]]);
|
||||
mesh_node->setMesh(&meshes[meshidx]);
|
||||
|
||||
}
|
||||
|
||||
for (uint i=0; i<node->mNumChildren; i++)
|
||||
out->children.push_back(buildSceneNodes(node->mChildren[i], meshes, textures, mat_lookup));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
SceneNode* loadModelScene(const std::string& filename, const map<int, Material>& overrides) {
|
||||
Assimp::Importer importer;
|
||||
|
||||
const aiScene* scene = importer.ReadFile(filename,
|
||||
aiProcess_CalcTangentSpace
|
||||
//| aiProcess_FlipWindingOrder
|
||||
| aiProcess_Triangulate
|
||||
| aiProcess_GenNormals
|
||||
| aiProcess_ImproveCacheLocality
|
||||
//| aiProcess_JoinIdenticalVertices
|
||||
| aiProcess_SortByPType
|
||||
);
|
||||
if (!scene) {
|
||||
cerr << importer.GetErrorString() << endl;
|
||||
throw 1;
|
||||
}
|
||||
|
||||
// read materials
|
||||
uint j=0;
|
||||
Material default_material = Material::diffuse({1, 1, 1, 1});
|
||||
vector<Material> materials(scene->mNumMaterials);
|
||||
for (Material& material : materials) {
|
||||
const aiMaterial* aimat = scene->mMaterials[j++];
|
||||
|
||||
// print material
|
||||
aiString name; aimat->Get(AI_MATKEY_NAME, name);
|
||||
if (DEBUG){
|
||||
cout << "Read material #" << j-1 << " '" << name.C_Str() << "':" << endl;
|
||||
for (uint i=0; i < aimat->mNumProperties; i++)
|
||||
cout << " " << aimat->mProperties[i]->mKey.C_Str() << endl;
|
||||
}
|
||||
|
||||
aiColor4D diffuse (1,1,1,1);
|
||||
aimat->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
|
||||
//aiGetMaterialColor(aimat, "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0, &diffuse);
|
||||
//aiGetMaterialColor(aimat, "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0, &diffuse);
|
||||
//aiGetMaterialColor(aimat, "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0, &diffuse);
|
||||
material.basecolor = {diffuse.r, diffuse.g, diffuse.b, diffuse.a};
|
||||
|
||||
aimat->Get(AI_MATKEY_SHININESS, material.shininess);
|
||||
}
|
||||
|
||||
for (auto override : overrides)
|
||||
((override.first>=0)
|
||||
? materials[override.first]
|
||||
: default_material
|
||||
) = override.second;
|
||||
|
||||
vector<Mesh> meshes( scene->mNumMeshes);
|
||||
vector<PNGImage> textures(scene->mNumTextures);
|
||||
vector<Material*> mat_lookup(scene->mNumMeshes); // to be passed to buildSceneNodes
|
||||
|
||||
// read meshes
|
||||
j=0;
|
||||
for (Mesh& mesh : meshes) {
|
||||
const aiMesh* aimesh = scene->mMeshes[j++];
|
||||
for (uint i=0; i < aimesh->mNumVertices; i++){
|
||||
mesh.vertices.push_back({
|
||||
aimesh->mVertices[i].x,
|
||||
aimesh->mVertices[i].y,
|
||||
aimesh->mVertices[i].z,
|
||||
});
|
||||
mesh.normals.push_back({
|
||||
aimesh->mNormals[i].x,
|
||||
aimesh->mNormals[i].y,
|
||||
aimesh->mNormals[i].z,
|
||||
});
|
||||
}
|
||||
|
||||
mat_lookup[j-1] = (aimesh->mMaterialIndex)
|
||||
? &materials[aimesh->mMaterialIndex]
|
||||
: &default_material;
|
||||
|
||||
if (aimesh->GetNumUVChannels() >= 1)
|
||||
for (uint i=0; i < aimesh->mNumVertices; i++){
|
||||
//assert(aimesh->mNumUVComponents[0] == 2);
|
||||
mesh.textureCoordinates.push_back({
|
||||
aimesh->mTextureCoords[0][i].x,
|
||||
aimesh->mTextureCoords[0][i].y,
|
||||
});
|
||||
}
|
||||
|
||||
if (aimesh->GetNumColorChannels() >= 1)
|
||||
for (uint i=0; i < aimesh->mNumVertices; i++){
|
||||
mesh.colors.push_back({
|
||||
aimesh->mColors[0][i].r,
|
||||
aimesh->mColors[0][i].g,
|
||||
aimesh->mColors[0][i].b,
|
||||
aimesh->mColors[0][i].a,
|
||||
});
|
||||
}
|
||||
|
||||
for (uint i=0; i < aimesh->mNumFaces; i++){
|
||||
assert(aimesh->mFaces[i].mNumIndices == 3);
|
||||
mesh.indices.insert(mesh.indices.end(), {
|
||||
aimesh->mFaces[i].mIndices[0],
|
||||
aimesh->mFaces[i].mIndices[1],
|
||||
aimesh->mFaces[i].mIndices[2],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// read textures
|
||||
j=0;
|
||||
for (PNGImage& texture : textures) {
|
||||
const aiTexture* aitex = scene->mTextures[j++];
|
||||
// todo
|
||||
}
|
||||
SceneNode* out = buildSceneNodes(scene->mRootNode, meshes, textures, mat_lookup);
|
||||
out->rotation.x += M_PI/2; // account for my weird coordinates. Z is upward damnit!
|
||||
return out;
|
||||
}
|
24
src/utilities/modelLoader.hpp
Normal file
24
src/utilities/modelLoader.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "../sceneGraph.hpp"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#define DEBUG false
|
||||
|
||||
struct Material {
|
||||
vec4 basecolor;
|
||||
float shininess = 10;
|
||||
int texture_id = -1;
|
||||
|
||||
static Material diffuse(vec4 color, float shininess = 10){
|
||||
Material out;
|
||||
out.basecolor = color;
|
||||
out.shininess = shininess;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
SceneNode* loadModelScene(
|
||||
const std::string& filename,
|
||||
const std::map<int, Material>& overrides={});
|
Loading…
Reference in New Issue
Block a user