mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +02:00
if obj data isn't from a url, don't dereference null url pointer
This commit is contained in:
parent
9783740b21
commit
f4a23065b4
2 changed files with 46 additions and 33 deletions
|
@ -195,7 +195,10 @@ void OBJFace::addFrom(const OBJFace* face, int index) { // add using data from f
|
|||
}
|
||||
|
||||
bool OBJReader::isValidTexture(const QByteArray &filename) {
|
||||
QUrl candidateUrl = url->resolved(QUrl(filename));
|
||||
if (!_url) {
|
||||
return false;
|
||||
}
|
||||
QUrl candidateUrl = _url->resolved(QUrl(filename));
|
||||
QNetworkReply *netReply = request(candidateUrl, true);
|
||||
bool isValid = netReply->isFinished() && (netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200);
|
||||
netReply->deleteLater();
|
||||
|
@ -242,7 +245,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
|
|||
} else if ((token == "map_Kd") || (token == "map_Ks")) {
|
||||
QByteArray filename = QUrl(tokenizer.getLineAsDatum()).fileName().toUtf8();
|
||||
if (filename.endsWith(".tga")) {
|
||||
qCDebug(modelformat) << "OBJ Reader WARNING: currently ignoring tga texture " << filename << " in " << url;
|
||||
qCDebug(modelformat) << "OBJ Reader WARNING: currently ignoring tga texture " << filename << " in " << _url;
|
||||
break;
|
||||
}
|
||||
if (isValidTexture(filename)) {
|
||||
|
@ -252,7 +255,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
|
|||
currentMaterial.specularTextureFilename = filename;
|
||||
}
|
||||
} else {
|
||||
qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " ignoring missing texture " << filename;
|
||||
qCDebug(modelformat) << "OBJ Reader WARNING: " << _url << " ignoring missing texture " << filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -316,7 +319,7 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi
|
|||
QByteArray groupName = tokenizer.getDatum();
|
||||
currentGroup = groupName;
|
||||
//qCDebug(modelformat) << "new group:" << groupName;
|
||||
} else if (token == "mtllib") {
|
||||
} else if (token == "mtllib" && _url) {
|
||||
if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) {
|
||||
break;
|
||||
}
|
||||
|
@ -325,13 +328,15 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi
|
|||
break; // Some files use mtllib over and over again for the same libraryName
|
||||
}
|
||||
librariesSeen[libraryName] = true;
|
||||
QUrl libraryUrl = url->resolved(QUrl(libraryName).fileName()); // Throw away any path part of libraryName, and merge against original url.
|
||||
// Throw away any path part of libraryName, and merge against original url.
|
||||
QUrl libraryUrl = _url->resolved(QUrl(libraryName).fileName());
|
||||
qCDebug(modelformat) << "OBJ Reader new library:" << libraryName << " at:" << libraryUrl;
|
||||
QNetworkReply* netReply = request(libraryUrl, false);
|
||||
if (netReply->isFinished() && (netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200)) {
|
||||
parseMaterialLibrary(netReply);
|
||||
} else {
|
||||
qCDebug(modelformat) << "OBJ Reader " << libraryName << " did not answer. Got " << netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
|
||||
qCDebug(modelformat) << "OBJ Reader " << libraryName << " did not answer. Got "
|
||||
<< netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
|
||||
}
|
||||
netReply->deleteLater();
|
||||
} else if (token == "usemtl") {
|
||||
|
@ -406,10 +411,10 @@ FBXGeometry OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, Q
|
|||
OBJTokenizer tokenizer(device);
|
||||
float scaleGuess = 1.0f;
|
||||
|
||||
this->url = url;
|
||||
_url = url;
|
||||
geometry.meshExtents.reset();
|
||||
geometry.meshes.append(FBXMesh());
|
||||
|
||||
|
||||
try {
|
||||
// call parseOBJGroup as long as it's returning true. Each successful call will
|
||||
// add a new meshPart to the geometry's single mesh.
|
||||
|
@ -417,7 +422,7 @@ FBXGeometry OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, Q
|
|||
|
||||
FBXMesh& mesh = geometry.meshes[0];
|
||||
mesh.meshIndex = 0;
|
||||
|
||||
|
||||
geometry.joints.resize(1);
|
||||
geometry.joints[0].isFree = false;
|
||||
geometry.joints[0].parentIndex = -1;
|
||||
|
@ -440,37 +445,44 @@ FBXGeometry OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, Q
|
|||
0, 0, 1, 0,
|
||||
0, 0, 0, 1);
|
||||
mesh.clusters.append(cluster);
|
||||
|
||||
// Some .obj files use the convention that a group with uv coordinates that doesn't define a material, should use a texture with the same basename as the .obj file.
|
||||
QString filename = url->fileName();
|
||||
int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail
|
||||
QString basename = filename.remove(extIndex + 1, sizeof("obj"));
|
||||
OBJMaterial& preDefinedMaterial = materials[SMART_DEFAULT_MATERIAL_NAME];
|
||||
preDefinedMaterial.diffuseColor = glm::vec3(1.0f);
|
||||
QVector<QByteArray> extensions = {"jpg", "jpeg", "png", "tga"};
|
||||
QByteArray base = basename.toUtf8(), textName = "";
|
||||
for (int i = 0; i < extensions.count(); i++) {
|
||||
QByteArray candidateString = base + extensions[i];
|
||||
if (isValidTexture(candidateString)) {
|
||||
textName = candidateString;
|
||||
break;
|
||||
|
||||
// Some .obj files use the convention that a group with uv coordinates that doesn't define a material, should use
|
||||
// a texture with the same basename as the .obj file.
|
||||
if (url) {
|
||||
QString filename = url->fileName();
|
||||
int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail
|
||||
QString basename = filename.remove(extIndex + 1, sizeof("obj"));
|
||||
OBJMaterial& preDefinedMaterial = materials[SMART_DEFAULT_MATERIAL_NAME];
|
||||
preDefinedMaterial.diffuseColor = glm::vec3(1.0f);
|
||||
QVector<QByteArray> extensions = {"jpg", "jpeg", "png", "tga"};
|
||||
QByteArray base = basename.toUtf8(), textName = "";
|
||||
for (int i = 0; i < extensions.count(); i++) {
|
||||
QByteArray candidateString = base + extensions[i];
|
||||
if (isValidTexture(candidateString)) {
|
||||
textName = candidateString;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!textName.isEmpty()) {
|
||||
preDefinedMaterial.diffuseTextureFilename = textName;
|
||||
}
|
||||
materials[SMART_DEFAULT_MATERIAL_NAME] = preDefinedMaterial;
|
||||
}
|
||||
if (!textName.isEmpty()) {
|
||||
preDefinedMaterial.diffuseTextureFilename = textName;
|
||||
}
|
||||
materials[SMART_DEFAULT_MATERIAL_NAME] = preDefinedMaterial;
|
||||
|
||||
|
||||
for (int i = 0, meshPartCount = 0; i < mesh.parts.count(); i++, meshPartCount++) {
|
||||
FBXMeshPart& meshPart = mesh.parts[i];
|
||||
FaceGroup faceGroup = faceGroups[meshPartCount];
|
||||
OBJFace leadFace = faceGroup[0]; // All the faces in the same group will have the same name and material.
|
||||
QString groupMaterialName = leadFace.materialName;
|
||||
if (groupMaterialName.isEmpty() && (leadFace.textureUVIndices.count() > 0)) {
|
||||
qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " needs a texture that isn't specified. Using default mechanism.";
|
||||
qCDebug(modelformat) << "OBJ Reader WARNING: " << url
|
||||
<< " needs a texture that isn't specified. Using default mechanism.";
|
||||
groupMaterialName = SMART_DEFAULT_MATERIAL_NAME;
|
||||
} else if (!groupMaterialName.isEmpty() && !materials.contains(groupMaterialName)) {
|
||||
qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " specifies a material " << groupMaterialName << " that is not defined. Using default mechanism.";
|
||||
qCDebug(modelformat) << "OBJ Reader WARNING: " << url
|
||||
<< " specifies a material " << groupMaterialName
|
||||
<< " that is not defined. Using default mechanism.";
|
||||
groupMaterialName = SMART_DEFAULT_MATERIAL_NAME;
|
||||
}
|
||||
if (!groupMaterialName.isEmpty()) {
|
||||
|
|
|
@ -69,12 +69,13 @@ public:
|
|||
QVector<FaceGroup> faceGroups;
|
||||
QString currentMaterialName;
|
||||
QHash<QString, OBJMaterial> materials;
|
||||
QUrl* url;
|
||||
|
||||
|
||||
QNetworkReply* request(QUrl& url, bool isTest);
|
||||
FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping);
|
||||
FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping, QUrl* url);
|
||||
private:
|
||||
QUrl* _url = nullptr;
|
||||
|
||||
QHash<QByteArray, bool> librariesSeen;
|
||||
bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess);
|
||||
void parseMaterialLibrary(QIODevice* device);
|
||||
|
@ -83,4 +84,4 @@ private:
|
|||
|
||||
// What are these utilities doing here? One is used by fbx loading code in VHACD Utils, and the other a general debugging utility.
|
||||
void setMeshPartDefaults(FBXMeshPart& meshPart, QString materialID);
|
||||
void fbxDebugDump(const FBXGeometry& fbxgeo);
|
||||
void fbxDebugDump(const FBXGeometry& fbxgeo);
|
||||
|
|
Loading…
Reference in a new issue