Merge pull request #5170 from vulcanozz/vulcano/export_gltf2_with_roughness_texture

Add DIFFUSE_ROUGHNESS_TEXTURE for gltf2 exporter
pull/5216/head^2
Kim Kulling 2023-08-29 15:27:55 +02:00 committed by GitHub
commit f623870dd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 55 additions and 45 deletions

View File

@ -263,7 +263,7 @@ size_t NZDiff(void *data, void *dataBase, size_t count, unsigned int numCompsIn,
for (short idx = 0; bufferData_ptr < bufferData_end; idx += 1, bufferData_ptr += numCompsIn) { for (short idx = 0; bufferData_ptr < bufferData_end; idx += 1, bufferData_ptr += numCompsIn) {
bool bNonZero = false; bool bNonZero = false;
//for the data, check any component Non Zero // for the data, check any component Non Zero
for (unsigned int j = 0; j < numCompsOut; j++) { for (unsigned int j = 0; j < numCompsOut; j++) {
double valueData = bufferData_ptr[j]; double valueData = bufferData_ptr[j];
double valueBase = bufferBase_ptr ? bufferBase_ptr[j] : 0; double valueBase = bufferBase_ptr ? bufferBase_ptr[j] : 0;
@ -273,11 +273,11 @@ size_t NZDiff(void *data, void *dataBase, size_t count, unsigned int numCompsIn,
} }
} }
//all zeros, continue // all zeros, continue
if (!bNonZero) if (!bNonZero)
continue; continue;
//non zero, store the data // non zero, store the data
for (unsigned int j = 0; j < numCompsOut; j++) { for (unsigned int j = 0; j < numCompsOut; j++) {
T valueData = bufferData_ptr[j]; T valueData = bufferData_ptr[j];
T valueBase = bufferBase_ptr ? bufferBase_ptr[j] : 0; T valueBase = bufferBase_ptr ? bufferBase_ptr[j] : 0;
@ -286,14 +286,14 @@ size_t NZDiff(void *data, void *dataBase, size_t count, unsigned int numCompsIn,
vNZIdx.push_back(idx); vNZIdx.push_back(idx);
} }
//avoid all-0, put 1 item // avoid all-0, put 1 item
if (vNZDiff.size() == 0) { if (vNZDiff.size() == 0) {
for (unsigned int j = 0; j < numCompsOut; j++) for (unsigned int j = 0; j < numCompsOut; j++)
vNZDiff.push_back(0); vNZDiff.push_back(0);
vNZIdx.push_back(0); vNZIdx.push_back(0);
} }
//process data // process data
outputNZDiff = new T[vNZDiff.size()]; outputNZDiff = new T[vNZDiff.size()];
memcpy(outputNZDiff, vNZDiff.data(), vNZDiff.size() * sizeof(T)); memcpy(outputNZDiff, vNZDiff.data(), vNZDiff.size() * sizeof(T));
@ -361,7 +361,7 @@ inline Ref<Accessor> ExportDataSparse(Asset &a, std::string &meshName, Ref<Buffe
acc->sparse.reset(new Accessor::Sparse); acc->sparse.reset(new Accessor::Sparse);
acc->sparse->count = nzCount; acc->sparse->count = nzCount;
//indices // indices
unsigned int bytesPerIdx = sizeof(unsigned short); unsigned int bytesPerIdx = sizeof(unsigned short);
size_t indices_offset = buffer->byteLength; size_t indices_offset = buffer->byteLength;
size_t indices_padding = indices_offset % bytesPerIdx; size_t indices_padding = indices_offset % bytesPerIdx;
@ -379,7 +379,7 @@ inline Ref<Accessor> ExportDataSparse(Asset &a, std::string &meshName, Ref<Buffe
acc->sparse->indicesByteOffset = 0; acc->sparse->indicesByteOffset = 0;
acc->WriteSparseIndices(nzCount, nzIdx, 1 * bytesPerIdx); acc->WriteSparseIndices(nzCount, nzIdx, 1 * bytesPerIdx);
//values // values
size_t values_offset = buffer->byteLength; size_t values_offset = buffer->byteLength;
size_t values_padding = values_offset % bytesPerComp; size_t values_padding = values_offset % bytesPerComp;
values_offset += values_padding; values_offset += values_padding;
@ -395,9 +395,9 @@ inline Ref<Accessor> ExportDataSparse(Asset &a, std::string &meshName, Ref<Buffe
acc->sparse->valuesByteOffset = 0; acc->sparse->valuesByteOffset = 0;
acc->WriteSparseValues(nzCount, nzDiff, numCompsIn * bytesPerComp); acc->WriteSparseValues(nzCount, nzDiff, numCompsIn * bytesPerComp);
//clear // clear
delete[](char *) nzDiff; delete[] (char *)nzDiff;
delete[](char *) nzIdx; delete[] (char *)nzIdx;
} }
return acc; return acc;
} }
@ -599,7 +599,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsi
if (curTex != nullptr) { // embedded if (curTex != nullptr) { // embedded
texture->source->name = curTex->mFilename.C_Str(); texture->source->name = curTex->mFilename.C_Str();
//basisu: embedded ktx2, bu // basisu: embedded ktx2, bu
if (curTex->achFormatHint[0]) { if (curTex->achFormatHint[0]) {
std::string mimeType = "image/"; std::string mimeType = "image/";
if (memcmp(curTex->achFormatHint, "jpg", 3) == 0) if (memcmp(curTex->achFormatHint, "jpg", 3) == 0)
@ -619,7 +619,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsi
} }
// The asset has its own buffer, see Image::SetData // The asset has its own buffer, see Image::SetData
//basisu: "image/ktx2", "image/basis" as is // basisu: "image/ktx2", "image/basis" as is
texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset); texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset);
} else { } else {
texture->source->uri = path; texture->source->uri = path;
@ -629,7 +629,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsi
} }
} }
//basisu // basisu
if (useBasisUniversal) { if (useBasisUniversal) {
mAsset->extensionsUsed.KHR_texture_basisu = true; mAsset->extensionsUsed.KHR_texture_basisu = true;
mAsset->extensionsRequired.KHR_texture_basisu = true; mAsset->extensionsRequired.KHR_texture_basisu = true;
@ -652,7 +652,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, NormalTextureInfo &prop, ai
GetMatTex(mat, texture, prop.texCoord, tt, slot); GetMatTex(mat, texture, prop.texCoord, tt, slot);
if (texture) { if (texture) {
//GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); // GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
GetMatTexProp(mat, prop.scale, "scale", tt, slot); GetMatTexProp(mat, prop.scale, "scale", tt, slot);
} }
} }
@ -663,7 +663,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, OcclusionTextureInfo &prop,
GetMatTex(mat, texture, prop.texCoord, tt, slot); GetMatTex(mat, texture, prop.texCoord, tt, slot);
if (texture) { if (texture) {
//GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); // GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
GetMatTexProp(mat, prop.strength, "strength", tt, slot); GetMatTexProp(mat, prop.strength, "strength", tt, slot);
} }
} }
@ -832,20 +832,30 @@ void glTF2Exporter::ExportMaterials() {
GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_BASE_COLOR); GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_BASE_COLOR);
if (!m->pbrMetallicRoughness.baseColorTexture.texture) { if (!m->pbrMetallicRoughness.baseColorTexture.texture) {
//if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture // if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture
GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE); GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE);
} }
GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, aiTextureType_DIFFUSE_ROUGHNESS);
if (!m->pbrMetallicRoughness.metallicRoughnessTexture.texture) {
// if there wasn't a aiTextureType_DIFFUSE_ROUGHNESS defined in the source, fallback to aiTextureType_METALNESS
GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, aiTextureType_METALNESS);
}
if (!m->pbrMetallicRoughness.metallicRoughnessTexture.texture) {
// if there still wasn't a aiTextureType_METALNESS defined in the source, fallback to AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE
GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
}
if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_BASE_COLOR) != AI_SUCCESS) { if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_BASE_COLOR) != AI_SUCCESS) {
// if baseColorFactor wasn't defined, then the source is likely not a metallic roughness material. // if baseColorFactor wasn't defined, then the source is likely not a metallic roughness material.
//a fallback to any diffuse color should be used instead // a fallback to any diffuse color should be used instead
GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
} }
if (mat.Get(AI_MATKEY_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) { if (mat.Get(AI_MATKEY_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) {
//if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0 // if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0
m->pbrMetallicRoughness.metallicFactor = 0; m->pbrMetallicRoughness.metallicFactor = 0;
} }
@ -858,10 +868,10 @@ void glTF2Exporter::ExportMaterials() {
if (mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
// convert specular color to luminance // convert specular color to luminance
float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f; float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f;
//normalize shininess (assuming max is 1000) with an inverse exponentional curve // normalize shininess (assuming max is 1000) with an inverse exponentional curve
float normalizedShininess = std::sqrt(shininess / 1000); float normalizedShininess = std::sqrt(shininess / 1000);
//clamp the shininess value between 0 and 1 // clamp the shininess value between 0 and 1
normalizedShininess = std::min(std::max(normalizedShininess, 0.0f), 1.0f); normalizedShininess = std::min(std::max(normalizedShininess, 0.0f), 1.0f);
// low specular intensity values should produce a rough material even if shininess is high. // low specular intensity values should produce a rough material even if shininess is high.
normalizedShininess = normalizedShininess * specularIntensity; normalizedShininess = normalizedShininess * specularIntensity;
@ -1059,7 +1069,7 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buf
if (boneIndexFitted != -1) { if (boneIndexFitted != -1) {
vertexJointData[vertexId][boneIndexFitted] = static_cast<float>(jointNamesIndex); vertexJointData[vertexId][boneIndexFitted] = static_cast<float>(jointNamesIndex);
} }
}else { } else {
vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast<float>(jointNamesIndex); vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast<float>(jointNamesIndex);
vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight; vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight;
@ -1362,24 +1372,24 @@ void glTF2Exporter::MergeMeshes() {
unsigned int nMeshes = static_cast<unsigned int>(node->meshes.size()); unsigned int nMeshes = static_cast<unsigned int>(node->meshes.size());
//skip if it's 1 or less meshes per node // skip if it's 1 or less meshes per node
if (nMeshes > 1) { if (nMeshes > 1) {
Ref<Mesh> firstMesh = node->meshes.at(0); Ref<Mesh> firstMesh = node->meshes.at(0);
//loop backwards to allow easy removal of a mesh from a node once it's merged // loop backwards to allow easy removal of a mesh from a node once it's merged
for (unsigned int m = nMeshes - 1; m >= 1; --m) { for (unsigned int m = nMeshes - 1; m >= 1; --m) {
Ref<Mesh> mesh = node->meshes.at(m); Ref<Mesh> mesh = node->meshes.at(m);
//append this mesh's primitives to the first mesh's primitives // append this mesh's primitives to the first mesh's primitives
firstMesh->primitives.insert( firstMesh->primitives.insert(
firstMesh->primitives.end(), firstMesh->primitives.end(),
mesh->primitives.begin(), mesh->primitives.begin(),
mesh->primitives.end()); mesh->primitives.end());
//remove the mesh from the list of meshes // remove the mesh from the list of meshes
unsigned int removedIndex = mAsset->meshes.Remove(mesh->id.c_str()); unsigned int removedIndex = mAsset->meshes.Remove(mesh->id.c_str());
//find the presence of the removed mesh in other nodes // find the presence of the removed mesh in other nodes
for (unsigned int nn = 0; nn < mAsset->nodes.Size(); ++nn) { for (unsigned int nn = 0; nn < mAsset->nodes.Size(); ++nn) {
Ref<Node> curNode = mAsset->nodes.Get(nn); Ref<Node> curNode = mAsset->nodes.Get(nn);
@ -1398,7 +1408,7 @@ void glTF2Exporter::MergeMeshes() {
} }
} }
//since we were looping backwards, reverse the order of merged primitives to their original order // since we were looping backwards, reverse the order of merged primitives to their original order
std::reverse(firstMesh->primitives.begin() + 1, firstMesh->primitives.end()); std::reverse(firstMesh->primitives.begin() + 1, firstMesh->primitives.end());
} }
} }
@ -1430,7 +1440,7 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode *n) {
return node.GetIndex(); return node.GetIndex();
} }
/* /*
* Export node and recursively calls ExportNode for all children. * Export node and recursively calls ExportNode for all children.
* Since these nodes are not the root node, we also export the parent Ref<Node> * Since these nodes are not the root node, we also export the parent Ref<Node>
*/ */
@ -1525,9 +1535,9 @@ inline void ExtractTranslationSampler(Asset &asset, std::string &animId, Ref<Buf
const aiVectorKey &key = nodeChannel->mPositionKeys[i]; const aiVectorKey &key = nodeChannel->mPositionKeys[i];
// mTime is measured in ticks, but GLTF time is measured in seconds, so convert. // mTime is measured in ticks, but GLTF time is measured in seconds, so convert.
times[i] = static_cast<float>(key.mTime / ticksPerSecond); times[i] = static_cast<float>(key.mTime / ticksPerSecond);
values[(i * 3) + 0] = (ai_real) key.mValue.x; values[(i * 3) + 0] = (ai_real)key.mValue.x;
values[(i * 3) + 1] = (ai_real) key.mValue.y; values[(i * 3) + 1] = (ai_real)key.mValue.y;
values[(i * 3) + 2] = (ai_real) key.mValue.z; values[(i * 3) + 2] = (ai_real)key.mValue.z;
} }
sampler.input = GetSamplerInputRef(asset, animId, buffer, times); sampler.input = GetSamplerInputRef(asset, animId, buffer, times);
@ -1544,9 +1554,9 @@ inline void ExtractScaleSampler(Asset &asset, std::string &animId, Ref<Buffer> &
const aiVectorKey &key = nodeChannel->mScalingKeys[i]; const aiVectorKey &key = nodeChannel->mScalingKeys[i];
// mTime is measured in ticks, but GLTF time is measured in seconds, so convert. // mTime is measured in ticks, but GLTF time is measured in seconds, so convert.
times[i] = static_cast<float>(key.mTime / ticksPerSecond); times[i] = static_cast<float>(key.mTime / ticksPerSecond);
values[(i * 3) + 0] = (ai_real) key.mValue.x; values[(i * 3) + 0] = (ai_real)key.mValue.x;
values[(i * 3) + 1] = (ai_real) key.mValue.y; values[(i * 3) + 1] = (ai_real)key.mValue.y;
values[(i * 3) + 2] = (ai_real) key.mValue.z; values[(i * 3) + 2] = (ai_real)key.mValue.z;
} }
sampler.input = GetSamplerInputRef(asset, animId, buffer, times); sampler.input = GetSamplerInputRef(asset, animId, buffer, times);
@ -1563,10 +1573,10 @@ inline void ExtractRotationSampler(Asset &asset, std::string &animId, Ref<Buffer
const aiQuatKey &key = nodeChannel->mRotationKeys[i]; const aiQuatKey &key = nodeChannel->mRotationKeys[i];
// mTime is measured in ticks, but GLTF time is measured in seconds, so convert. // mTime is measured in ticks, but GLTF time is measured in seconds, so convert.
times[i] = static_cast<float>(key.mTime / ticksPerSecond); times[i] = static_cast<float>(key.mTime / ticksPerSecond);
values[(i * 4) + 0] = (ai_real) key.mValue.x; values[(i * 4) + 0] = (ai_real)key.mValue.x;
values[(i * 4) + 1] = (ai_real) key.mValue.y; values[(i * 4) + 1] = (ai_real)key.mValue.y;
values[(i * 4) + 2] = (ai_real) key.mValue.z; values[(i * 4) + 2] = (ai_real)key.mValue.z;
values[(i * 4) + 3] = (ai_real) key.mValue.w; values[(i * 4) + 3] = (ai_real)key.mValue.w;
} }
sampler.input = GetSamplerInputRef(asset, animId, buffer, times); sampler.input = GetSamplerInputRef(asset, animId, buffer, times);