Edited MeshAssimp and added gltf_viewer sample code

This commit is contained in:
magicwhale
2018-10-15 15:43:48 -07:00
committed by magicwhale
parent 84d2fb222b
commit bc38c8a773
7 changed files with 587 additions and 9 deletions

View File

@@ -35,6 +35,9 @@
#include <assimp/cimport.h>
#include <assimp/scene.h>
#include <stb_image.h>
using namespace filament;
using namespace filamat;
using namespace math;
@@ -48,6 +51,10 @@ static constexpr uint8_t DEFAULT_TRANSPARENT_PACKAGE[] = {
#include "generated/material/aiDefaultTrans.inc"
};
static constexpr uint8_t GLTF2_PACKAGE[] = {
#include "generated/material/gltf2.inc"
};
MeshAssimp::MeshAssimp(Engine& engine) : mEngine(engine) {
}
@@ -56,9 +63,17 @@ MeshAssimp::~MeshAssimp() {
mEngine.destroy(mIndexBuffer);
mEngine.destroy(mDefaultColorMaterial);
mEngine.destroy(mDefaultTransparentColorMaterial);
mEngine.destroy(mGltfMaterial);
mEngine.destroy(mDefaultNormalMap);
mEngine.destroy(mDefaultMap);
for (Entity renderable : mRenderables) {
mEngine.destroy(renderable);
}
for (Texture *tex : mTextures) {
mEngine.destroy(tex);
}
// destroy the Entities itself
EntityManager::get().destroy(mRenderables.size(), mRenderables.data());
}
@@ -75,6 +90,34 @@ struct State {
T const * data() const { return state.data(); }
};
//TODO: Remove redundant method from sample_full_pbr
void loadTex(Engine* engine, const std::string& filePath, Texture** map, bool sRGB = true) {
if (!filePath.empty()) {
Path path(filePath);
if (path.exists()) {
int w, h, n;
unsigned char* data = stbi_load(path.getAbsolutePath().c_str(), &w, &h, &n, 3);
if (data != nullptr) {
*map = Texture::Builder()
.width(uint32_t(w))
.height(uint32_t(h))
.levels(0xff)
.format(sRGB ? driver::TextureFormat::SRGB8 : driver::TextureFormat::RGB8)
.build(*engine);
Texture::PixelBufferDescriptor buffer(data, size_t(w * h * 3),
Texture::Format::RGB, Texture::Type::UBYTE,
(driver::BufferDescriptor::Callback) &stbi_image_free);
(*map)->setImage(*engine, 0, std::move(buffer));
(*map)->generateMipmaps(*engine);
} else {
std::cout << "The texture " << path << " could not be loaded" << std::endl;
}
} else {
std::cout << "The texture " << path << " does not exist" << std::endl;
}
}
}
void MeshAssimp::addFromFile(const Path& path,
std::map<std::string, MaterialInstance*>& materials, bool overrideMaterial) {
@@ -91,7 +134,44 @@ void MeshAssimp::addFromFile(const Path& path,
// "command buffer" lifetime, we wouldn't need to have to deal with freeing the
// std::vectors here.
if (!setFromFile(path, indices, positions, tangents, texCoords, meshes, parents)) {
// Make default map for all textures except Normal
int defaultTexSize = 4;
unsigned char *defaultTexData = (unsigned char *) malloc(defaultTexSize*sizeof(unsigned char*));
for (int i=0; i < defaultTexSize; i++){
defaultTexData[i] = static_cast<unsigned char>(255);
}
mDefaultMap = Texture::Builder()
.width(uint32_t(1))
.height(uint32_t(1))
.levels(0xff)
.format(driver::TextureFormat::SRGB8)
.build(mEngine);
Texture::PixelBufferDescriptor defaultBuffer(defaultTexData, size_t(1 * 1 * 3),
Texture::Format::RGB, Texture::Type::UBYTE
,(driver::BufferDescriptor::Callback) &free);
mDefaultMap->setImage(mEngine, 0, std::move(defaultBuffer));
mDefaultMap->generateMipmaps(mEngine);
//Make default Normal Map
unsigned char *defaultNormalTexData = (unsigned char *) malloc(defaultTexSize*sizeof(unsigned char*));
defaultNormalTexData[0] = static_cast<unsigned char>(128);
defaultNormalTexData[1] = static_cast<unsigned char>(128);
defaultNormalTexData[2] = static_cast<unsigned char>(255);
defaultNormalTexData[3] = static_cast<unsigned char>(0);
mDefaultNormalMap = Texture::Builder()
.width(uint32_t(1))
.height(uint32_t(1))
.levels(0xff)
.format(driver::TextureFormat::SRGB8)
.build(mEngine);
Texture::PixelBufferDescriptor defaultNormalBuffer(defaultNormalTexData, size_t(1 * 1 * 3),
Texture::Format::RGB, Texture::Type::UBYTE
,(driver::BufferDescriptor::Callback) &free);
mDefaultNormalMap->setImage(mEngine, 0, std::move(defaultNormalBuffer));
mDefaultNormalMap->generateMipmaps(mEngine);
if (!setFromFile(path, indices, positions, tangents, texCoords, meshes, parents, materials)) {
return;
}
@@ -146,6 +226,8 @@ void MeshAssimp::addFromFile(const Path& path,
materials[AI_DEFAULT_MATERIAL_NAME] = mDefaultColorMaterial->createInstance();
}
size_t startIndex = mRenderables.size();
mRenderables.resize(startIndex + meshes.size());
EntityManager::get().create(meshes.size(), mRenderables.data() + startIndex);
@@ -163,11 +245,17 @@ void MeshAssimp::addFromFile(const Path& path,
if (overrideMaterial) {
builder.material(partIndex, materials[AI_DEFAULT_MATERIAL_NAME]);
} else {
//TODO: add usage of gltf materials
//Load all gltf textures
auto pos = materials.find(part.material);
if (pos != materials.end()) {
builder.material(partIndex, pos->second);
} else {
std::cout << "I don't think this should be running" << std::endl;
MaterialInstance* colorMaterial;
if (part.opacity < 1.0f) {
colorMaterial = mDefaultTransparentColorMaterial->createInstance();
@@ -208,8 +296,9 @@ bool MeshAssimp::setFromFile(const Path& file,
std::vector<short4>& outTangents,
std::vector<half2>& outTexCoords,
std::vector<Mesh>& outMeshes,
std::vector<int>& outParents
) {
std::vector<int>& outParents,
std::map<std::string, MaterialInstance*>& outMaterials
) {
Importer importer;
importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,
aiPrimitiveType_LINE | aiPrimitiveType_POINT);
@@ -230,6 +319,10 @@ bool MeshAssimp::setFromFile(const Path& file,
// we only support triangles
aiProcess_Triangulate);
if (!scene){
std::cout << "no scene" << std::endl;
}
// we could use those, but we want to keep the graph if any, for testing
// aiProcess_OptimizeGraph
// aiProcess_PreTransformVertices
@@ -238,10 +331,10 @@ bool MeshAssimp::setFromFile(const Path& file,
countVertices = [scene, &countVertices]
(aiNode const* node, size_t& totalVertexCount, size_t& totalIndexCount) {
for (size_t i = 0; i < node->mNumMeshes; i++) {
aiMesh const* mesh = scene->mMeshes[node->mMeshes[i]];
aiMesh const *mesh = scene->mMeshes[node->mMeshes[i]];
totalVertexCount += mesh->mNumVertices;
const aiFace* faces = mesh->mFaces;
const aiFace *faces = mesh->mFaces;
const size_t numFaces = mesh->mNumFaces;
totalIndexCount += numFaces * faces[0].mNumIndices;
}
@@ -255,8 +348,8 @@ bool MeshAssimp::setFromFile(const Path& file,
size_t depth = 0;
const std::function<void(aiNode const* node, int parentIndex)> processNode =
[scene, &processNode, &outParents, &deep, &depth,
&outIndices, &outPositions, &outTangents, &outTexCoords, &outMeshes]
[this, file, scene, &processNode, &outParents, &deep, &depth,
&outIndices, &outPositions, &outTangents, &outTexCoords, &outMeshes, &outMaterials]
(aiNode const* node, int parentIndex) {
mat4f const& current = transpose(*reinterpret_cast<mat4f const*>(&node->mTransformation));
@@ -271,6 +364,10 @@ bool MeshAssimp::setFromFile(const Path& file,
const float bias = 1.0f / 32767.0f;
const float factor = (float) (sqrt(1.0 - (double) bias * (double) bias));
mGltfMaterial = Material::Builder()
.package((void*) GLTF2_PACKAGE, sizeof(GLTF2_PACKAGE))
.build(mEngine);
for (size_t i = 0; i < node->mNumMeshes; i++) {
aiMesh const* mesh = scene->mMeshes[node->mMeshes[i]];
@@ -310,14 +407,142 @@ bool MeshAssimp::setFromFile(const Path& file,
uint32_t materialId = mesh->mMaterialIndex;
aiMaterial const* material = scene->mMaterials[materialId];
//Get filepaths for PBR textures
int texIndex = 0;
aiString baseColorPath;
aiString AOPath;
aiString MRPath;
aiString normalPath;
aiString emissivePath;
aiString name;
std::string materialName;
if (material->Get(AI_MATKEY_NAME, name) != AI_SUCCESS) {
materialName = AI_DEFAULT_MATERIAL_NAME;
} else {
materialName = name.C_Str();
}
// TODO: Add support for non-image path values and binary gltf
TextureSampler sampler(TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR,
TextureSampler::MagFilter::LINEAR, TextureSampler::WrapMode::REPEAT);
sampler.setAnisotropy(8.0f);
std::string dirName = file.getParent();
std::cout << "directory: " << dirName << std::endl;
if (outMaterials.find(materialName) == outMaterials.end()) {
outMaterials[materialName] = mGltfMaterial->createInstance();
// Load property values for gltf files
aiColor4D baseColorFactor;
sRGBColorA baseColorFactorCast{1.0f};
aiColor3D emissiveFactor;
sRGBColor emissiveFactorCast{1.0f};
float metallicFactor = 1.0;
float roughnessFactor = 1.0;
// if(material->Get("$mat.gltf.occlusionTexture.strength", 0, 0, occlusionStrength) == AI_SUCCESS){
// std::cout << "hey" << std::endl;
// }
// Load texture images for gltf files
if (material->GetTexture(aiTextureType_DIFFUSE, 1, &baseColorPath) == AI_SUCCESS) {
Texture* baseColorMap = nullptr;
loadTex(&mEngine, dirName + baseColorPath.C_Str(), &baseColorMap);
mTextures.push_back(baseColorMap);
if (baseColorMap != nullptr) {
outMaterials[materialName]->setParameter(
"baseColorMap", baseColorMap, sampler);
}
std::cout << dirName + baseColorPath.C_Str() << std::endl;
} else {
if (mDefaultMap == nullptr){
std::cout << "default mat is null" << std::endl;
}
outMaterials[materialName]->setParameter("baseColorMap", mDefaultMap, sampler);
}
if (material->GetTexture(aiTextureType_UNKNOWN, 0, &MRPath) == AI_SUCCESS) {
Texture* metallicRoughnessMap = nullptr;
loadTex(&mEngine, dirName + MRPath.C_Str(), &metallicRoughnessMap, false);
mTextures.push_back(metallicRoughnessMap);
if (metallicRoughnessMap != nullptr) {
outMaterials[materialName]->setParameter(
"metallicRoughnessMap", metallicRoughnessMap, sampler);
}
std::cout << dirName + MRPath.C_Str() << std::endl;
} else {
outMaterials[materialName]->setParameter("metallicRoughnessMap", mDefaultMap, sampler);
outMaterials[materialName]->setParameter("metallicFactor", mDefaultMetallic);
outMaterials[materialName]->setParameter("roughnessFactor", mDefaultRoughness);
}
if (material->GetTexture(aiTextureType_LIGHTMAP, 0, &AOPath) == AI_SUCCESS) {
Texture* aoMap = nullptr;
loadTex(&mEngine, dirName + AOPath.C_Str(), &aoMap, false);
mTextures.push_back(aoMap);
if (aoMap != nullptr) {
outMaterials[materialName]->setParameter(
"aoMap", aoMap, sampler);
}
std::cout << dirName + AOPath.C_Str() << std::endl;
} else {
outMaterials[materialName]->setParameter("aoMap", mDefaultMap, sampler);
}
if (material->GetTexture(aiTextureType_NORMALS, 0, &normalPath) == AI_SUCCESS) {
Texture* normalMap = nullptr;
loadTex(&mEngine, dirName + normalPath.C_Str(), &normalMap, false);
mTextures.push_back(normalMap);
if (normalMap != nullptr) {
outMaterials[materialName]->setParameter(
"normalMap", normalMap, sampler);
}
std::cout << dirName + normalPath.C_Str() << std::endl;
} else {
outMaterials[materialName]->setParameter("normalMap", mDefaultNormalMap, sampler);
}
if (material->GetTexture(aiTextureType_EMISSIVE, 0, &emissivePath) == AI_SUCCESS) {
Texture* emissiveMap = nullptr;
loadTex(&mEngine, dirName + emissivePath.C_Str(), &emissiveMap, false);
mTextures.push_back(emissiveMap);
if (emissiveMap != nullptr) {
outMaterials[materialName]->setParameter(
"emissiveMap", emissiveMap, sampler);
}
std::cout << dirName + emissivePath.C_Str() << std::endl;
} else {
outMaterials[materialName]->setParameter("emissiveMap", mDefaultMap, sampler);
outMaterials[materialName]->setParameter("emissiveFactor", mDefaultEmissive);
}
//If the gltf has texture factors, override the default factor values
if(material->Get("$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0, metallicFactor) == AI_SUCCESS){
outMaterials[materialName]->setParameter("metallicFactor", metallicFactor);
}
if (material->Get("$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0, roughnessFactor) == AI_SUCCESS){
outMaterials[materialName]->setParameter("roughnessFactor", roughnessFactor);
}
if(material->Get(AI_MATKEY_COLOR_EMISSIVE, emissiveFactor) == AI_SUCCESS){
emissiveFactorCast = *reinterpret_cast<sRGBColor*>(&emissiveFactor);
outMaterials[materialName]->setParameter("emissiveFactor", emissiveFactorCast);
}
if(material->Get("$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0, baseColorFactor) == AI_SUCCESS){
baseColorFactorCast = *reinterpret_cast<sRGBColorA*>(&baseColorFactor);
outMaterials[materialName]->setParameter("baseColorFactor", baseColorFactorCast);
}
}
aiColor3D color;
sRGBColor baseColor{1.0f};
if (material->Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
@@ -382,6 +607,9 @@ bool MeshAssimp::setFromFile(const Path& file,
if (scene) {
aiNode const* node = scene->mRootNode;
if(!node){
std::cout << scene->mNumMeshes << std::endl;
}
size_t totalVertexCount = 0;
size_t totalIndexCount = 0;