Edited MeshAssimp and added gltf_viewer sample code
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user