Merge branch 'master' into fix-fbx-utils-double-free
commit
af8ff3b66e
1
Build.md
1
Build.md
|
@ -43,6 +43,7 @@ cd assimp
|
|||
cmake CMakeLists.txt
|
||||
cmake --build .
|
||||
```
|
||||
Note that by default this builds a shared library into the `bin` directory. If you want to build it as a static library see the build options at the bottom of this file.
|
||||
|
||||
### Build instructions for Windows with Visual-Studio
|
||||
|
||||
|
|
|
@ -15,10 +15,10 @@ Open Asset Import Library is a library to load various 3d file formats into a sh
|
|||
APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
|
||||
Additionally, assimp features various __mesh post-processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
|
||||
|
||||
### Latest Doc's ###
|
||||
### Documentation ###
|
||||
Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/).
|
||||
|
||||
### Prebuild binaries ###
|
||||
### Pre-built binaries ###
|
||||
Please check our [Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib)
|
||||
|
||||
If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
|
||||
|
@ -35,7 +35,7 @@ And we also have a Gitter-channel:Gitter [
|
||||
|
||||
### Building ###
|
||||
Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
|
||||
Take a look [here](https://github.com/assimp/assimp/blob/master/Build.md) to get started. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
|
||||
|
||||
### Ports ###
|
||||
* [Android](port/AndroidJNI/README.md)
|
||||
|
@ -52,7 +52,7 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
|
|||
|
||||
### Other tools ###
|
||||
[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
|
||||
[Assimp-Viewer(]https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental).
|
||||
[Assimp-Viewer](https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental).
|
||||
|
||||
#### Repository structure ####
|
||||
Open Asset Import Library is implemented in C++. The directory structure looks like this:
|
||||
|
|
|
@ -186,9 +186,6 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
|
|||
D3MFOpcPackage::~D3MFOpcPackage() {
|
||||
mZipArchive->Close(mRootStream);
|
||||
delete mZipArchive;
|
||||
for (auto tex : mEmbeddedTextures) {
|
||||
delete tex;
|
||||
}
|
||||
}
|
||||
|
||||
IOStream *D3MFOpcPackage::RootStream() const {
|
||||
|
|
|
@ -50,11 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/version.h>
|
||||
#include <assimp/IOStream.hpp>
|
||||
|
||||
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "../contrib/zlib/zlib.h"
|
||||
#endif
|
||||
#include "zlib.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
|
|
|
@ -283,6 +283,11 @@ void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data,
|
|||
if (conv_data.meshes->empty()) {
|
||||
return;
|
||||
}
|
||||
const size_t meshIndex = conv_data.meshes->size() - out.mNumMeshes;
|
||||
if (meshIndex >= conv_data.meshes->size()) {
|
||||
ASSIMP_LOG_ERROR("Invalid index detected.");
|
||||
return;
|
||||
}
|
||||
aiMesh **const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
|
||||
std::unique_ptr<aiMesh *[]> tempmeshes(new aiMesh *[out.mNumMeshes]());
|
||||
|
||||
|
|
|
@ -814,38 +814,38 @@ void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
|
|||
if (!pImage.mFileName.length()) {
|
||||
pImage.mFileName = "unknown_texture";
|
||||
}
|
||||
}
|
||||
} else if (mFormat == FV_1_5_n) {
|
||||
std::string value;
|
||||
XmlNode refChild = currentNode.child("ref");
|
||||
XmlNode hexChild = currentNode.child("hex");
|
||||
if (refChild) {
|
||||
// element content is filename - hopefully
|
||||
if (XmlParser::getValueAsString(refChild, value)) {
|
||||
aiString filepath(value);
|
||||
UriDecodePath(filepath);
|
||||
pImage.mFileName = filepath.C_Str();
|
||||
}
|
||||
} else if (hexChild && !pImage.mFileName.length()) {
|
||||
// embedded image. get format
|
||||
pImage.mEmbeddedFormat = hexChild.attribute("format").as_string();
|
||||
if (pImage.mEmbeddedFormat.empty()) {
|
||||
ASSIMP_LOG_WARN("Collada: Unknown image file format");
|
||||
}
|
||||
} else if (mFormat == FV_1_5_n) {
|
||||
std::string value;
|
||||
XmlNode refChild = currentNode.child("ref");
|
||||
XmlNode hexChild = currentNode.child("hex");
|
||||
if (refChild) {
|
||||
// element content is filename - hopefully
|
||||
if (XmlParser::getValueAsString(refChild, value)) {
|
||||
aiString filepath(value);
|
||||
UriDecodePath(filepath);
|
||||
pImage.mFileName = filepath.C_Str();
|
||||
}
|
||||
} else if (hexChild && !pImage.mFileName.length()) {
|
||||
// embedded image. get format
|
||||
pImage.mEmbeddedFormat = hexChild.attribute("format").as_string();
|
||||
if (pImage.mEmbeddedFormat.empty()) {
|
||||
ASSIMP_LOG_WARN("Collada: Unknown image file format");
|
||||
}
|
||||
|
||||
XmlParser::getValueAsString(hexChild, value);
|
||||
const char *data = value.c_str();
|
||||
// hexadecimal-encoded binary octets. First of all, find the
|
||||
// required buffer size to reserve enough storage.
|
||||
const char *cur = data;
|
||||
while (!IsSpaceOrNewLine(*cur)) {
|
||||
++cur;
|
||||
}
|
||||
XmlParser::getValueAsString(hexChild, value);
|
||||
const char *data = value.c_str();
|
||||
// hexadecimal-encoded binary octets. First of all, find the
|
||||
// required buffer size to reserve enough storage.
|
||||
const char *cur = data;
|
||||
while (!IsSpaceOrNewLine(*cur)) {
|
||||
++cur;
|
||||
}
|
||||
|
||||
const unsigned int size = (unsigned int)(cur - data) * 2;
|
||||
pImage.mImageData.resize(size);
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
|
||||
const unsigned int size = (unsigned int)(cur - data) * 2;
|
||||
pImage.mImageData.resize(size);
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1274,9 +1274,7 @@ void ColladaParser::ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam)
|
|||
return;
|
||||
}
|
||||
|
||||
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
|
||||
XmlNode currentNode;
|
||||
while (xmlIt.getNext(currentNode)) {
|
||||
for (XmlNode ¤tNode : node.children()) {
|
||||
const std::string ¤tName = currentNode.name();
|
||||
if (currentName == "surface") {
|
||||
// image ID given inside <init_from> tags
|
||||
|
@ -1289,22 +1287,24 @@ void ColladaParser::ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam)
|
|||
}
|
||||
} else if (currentName == "sampler2D" && (FV_1_4_n == mFormat || FV_1_3_n == mFormat)) {
|
||||
// surface ID is given inside <source> tags
|
||||
const char *content = currentNode.value();
|
||||
pParam.mType = Param_Sampler;
|
||||
pParam.mReference = content;
|
||||
XmlNode source = currentNode.child("source");
|
||||
if (source) {
|
||||
std::string v;
|
||||
XmlParser::getValueAsString(source, v);
|
||||
pParam.mType = Param_Sampler;
|
||||
pParam.mReference = v.c_str();
|
||||
}
|
||||
} else if (currentName == "sampler2D") {
|
||||
// surface ID is given inside <instance_image> tags
|
||||
std::string url;
|
||||
XmlParser::getStdStrAttribute(currentNode, "url", url);
|
||||
if (url[0] != '#') {
|
||||
throw DeadlyImportError("Unsupported URL format in instance_image");
|
||||
}
|
||||
pParam.mType = Param_Sampler;
|
||||
pParam.mReference = url.c_str() + 1;
|
||||
} else if (currentName == "source") {
|
||||
const char *source = currentNode.child_value();
|
||||
if (nullptr != source) {
|
||||
pParam.mReference = source;
|
||||
XmlNode instance_image = currentNode.child("instance_image");
|
||||
if (instance_image) {
|
||||
std::string url;
|
||||
XmlParser::getStdStrAttribute(instance_image, "url", url);
|
||||
if (url[0] != '#') {
|
||||
throw DeadlyImportError("Unsupported URL format in instance_image");
|
||||
}
|
||||
pParam.mType = Param_Sampler;
|
||||
pParam.mReference = url.c_str() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,9 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <assimp/MathFunctions.h>
|
||||
#include <assimp/StringComparison.h>
|
||||
|
||||
#include <assimp/scene.h>
|
||||
|
||||
#include <assimp/CreateAnimMesh.h>
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/commonMetaData.h>
|
||||
|
@ -1604,7 +1602,7 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
|
|||
|
||||
void FBXConverter::ConvertCluster(std::vector<aiBone*> &local_mesh_bones, const Cluster *cluster,
|
||||
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
|
||||
std::vector<size_t> &count_out_indices, const aiMatrix4x4 & /* absolute_transform*/,
|
||||
std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
|
||||
aiNode *) {
|
||||
ai_assert(cluster != nullptr); // make sure cluster valid
|
||||
|
||||
|
@ -1621,16 +1619,16 @@ void FBXConverter::ConvertCluster(std::vector<aiBone*> &local_mesh_bones, const
|
|||
bone = new aiBone();
|
||||
bone->mName = bone_name;
|
||||
|
||||
bone->mOffsetMatrix = cluster->Transform();
|
||||
//bone->mOffsetMatrix = cluster->Transform();
|
||||
// store local transform link for post processing
|
||||
/*
|
||||
|
||||
bone->mOffsetMatrix = cluster->TransformLink();
|
||||
bone->mOffsetMatrix.Inverse();
|
||||
|
||||
aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
|
||||
const aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
|
||||
|
||||
bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset
|
||||
*/
|
||||
|
||||
//
|
||||
// Now calculate the aiVertexWeights
|
||||
//
|
||||
|
|
|
@ -390,7 +390,7 @@ void Document::ReadObjects() {
|
|||
const auto foundObject = objects.find(id);
|
||||
if(foundObject != objects.end()) {
|
||||
DOMWarning("encountered duplicate object id, ignoring first occurrence",el.second);
|
||||
delete foundObject->second;
|
||||
delete_LazyObject(foundObject->second);
|
||||
}
|
||||
|
||||
objects[id] = new_LazyObject(id, *el.second, *this);
|
||||
|
|
|
@ -1061,14 +1061,14 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene)
|
|||
return transform;
|
||||
}
|
||||
|
||||
int64_t to_ktime(double ticks, const aiAnimation* anim) {
|
||||
inline int64_t to_ktime(double ticks, const aiAnimation* anim) {
|
||||
if (anim->mTicksPerSecond <= 0) {
|
||||
return static_cast<int64_t>(ticks) * FBX::SECOND;
|
||||
}
|
||||
return (static_cast<int64_t>(ticks) / static_cast<int64_t>(anim->mTicksPerSecond)) * FBX::SECOND;
|
||||
return (static_cast<int64_t>(ticks / anim->mTicksPerSecond)) * FBX::SECOND;
|
||||
}
|
||||
|
||||
int64_t to_ktime(double time) {
|
||||
inline int64_t to_ktime(double time) {
|
||||
return (static_cast<int64_t>(time * FBX::SECOND));
|
||||
}
|
||||
|
||||
|
@ -2413,7 +2413,7 @@ void FBXExporter::WriteObjects ()
|
|||
// position/translation
|
||||
for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) {
|
||||
const aiVectorKey& k = na->mPositionKeys[ki];
|
||||
times.push_back(to_ktime(k.mTime));
|
||||
times.push_back(to_ktime(k.mTime, anim));
|
||||
xval.push_back(k.mValue.x);
|
||||
yval.push_back(k.mValue.y);
|
||||
zval.push_back(k.mValue.z);
|
||||
|
@ -2427,7 +2427,7 @@ void FBXExporter::WriteObjects ()
|
|||
times.clear(); xval.clear(); yval.clear(); zval.clear();
|
||||
for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) {
|
||||
const aiQuatKey& k = na->mRotationKeys[ki];
|
||||
times.push_back(to_ktime(k.mTime));
|
||||
times.push_back(to_ktime(k.mTime, anim));
|
||||
// TODO: aiQuaternion method to convert to Euler...
|
||||
aiMatrix4x4 m(k.mValue.GetMatrix());
|
||||
aiVector3D qs, qr, qt;
|
||||
|
@ -2445,7 +2445,7 @@ void FBXExporter::WriteObjects ()
|
|||
times.clear(); xval.clear(); yval.clear(); zval.clear();
|
||||
for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) {
|
||||
const aiVectorKey& k = na->mScalingKeys[ki];
|
||||
times.push_back(to_ktime(k.mTime));
|
||||
times.push_back(to_ktime(k.mTime, anim));
|
||||
xval.push_back(k.mValue.x);
|
||||
yval.push_back(k.mValue.y);
|
||||
zval.push_back(k.mValue.z);
|
||||
|
|
|
@ -45,12 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||
|
||||
//#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
||||
#include "Common/Compression.h"
|
||||
//# include <zlib.h>
|
||||
//#else
|
||||
//# include "../contrib/zlib/zlib.h"
|
||||
//#endif
|
||||
|
||||
#include "FBXTokenizer.h"
|
||||
#include "FBXParser.h"
|
||||
|
|
|
@ -155,7 +155,7 @@ size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOut
|
|||
const size_t realLength = inLength - size_t(in[inLength - 1] == '=') - size_t(in[inLength - 2] == '=');
|
||||
size_t dst_offset = 0;
|
||||
int val = 0, valb = -8;
|
||||
for (size_t src_offset = 0; src_offset < realLength; ++src_offset)
|
||||
for (size_t src_offset = 0; src_offset < realLength && dst_offset < maxOutLength; ++src_offset)
|
||||
{
|
||||
const uint8_t table_value = Util::DecodeBase64(in[src_offset]);
|
||||
if (table_value == 255)
|
||||
|
|
|
@ -42,11 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <utility>
|
||||
#include "MMDPmxParser.h"
|
||||
#include <assimp/StringUtils.h>
|
||||
#ifdef ASSIMP_USE_HUNTER
|
||||
# include <utf8.h>
|
||||
#else
|
||||
# include "../contrib/utf8cpp/source/utf8.h"
|
||||
#endif
|
||||
#include "utf8.h"
|
||||
#include <assimp/Exceptional.h>
|
||||
|
||||
namespace pmx
|
||||
|
@ -93,7 +89,7 @@ namespace pmx
|
|||
{
|
||||
return std::string();
|
||||
}
|
||||
buffer.reserve(size);
|
||||
buffer.resize(size);
|
||||
stream->read((char*) buffer.data(), size);
|
||||
if (encoding == 0)
|
||||
{
|
||||
|
|
|
@ -605,7 +605,8 @@ void ObjFileParser::getMaterialDesc() {
|
|||
}
|
||||
|
||||
if (needsNewMesh(strName)) {
|
||||
createMesh(strName);
|
||||
auto newMeshName = m_pModel->mActiveGroup.empty() ? strName : m_pModel->mActiveGroup;
|
||||
createMesh(newMeshName);
|
||||
}
|
||||
|
||||
m_pModel->mCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName);
|
||||
|
|
|
@ -425,7 +425,8 @@ bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char>
|
|||
break;
|
||||
} else {
|
||||
// ignore unknown header elements
|
||||
streamBuffer.getNextLine(buffer);
|
||||
if (!streamBuffer.getNextLine(buffer))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,11 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "../contrib/zlib/zlib.h"
|
||||
#endif
|
||||
#include "zlib.h"
|
||||
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
#include <assimp/StringComparison.h>
|
||||
|
|
|
@ -56,11 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/ByteSwapper.h>
|
||||
#include <assimp/StreamReader.h>
|
||||
#include <assimp/TinyFormatter.h>
|
||||
#ifdef ASSIMP_USE_HUNTER
|
||||
#include <utf8.h>
|
||||
#else
|
||||
#include "../contrib/utf8cpp/source/utf8.h"
|
||||
#endif
|
||||
#include "utf8.h"
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
|
|
@ -45,11 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
#include "STEPFileEncoding.h"
|
||||
#include <assimp/fast_atof.h>
|
||||
#ifdef ASSIMP_USE_HUNTER
|
||||
# include <utf8.h>
|
||||
#else
|
||||
# include <contrib/utf8cpp/source/utf8.h>
|
||||
#endif
|
||||
#include "utf8.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
|
@ -559,7 +559,11 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsi
|
|||
aiString tex;
|
||||
|
||||
// Read texcoord (UV map index)
|
||||
mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
|
||||
// Note: must be an int to be successful.
|
||||
int tmp = 0;
|
||||
const auto ok = mat.Get(AI_MATKEY_UVWSRC(tt, slot), tmp);
|
||||
if (ok == aiReturn_SUCCESS) texCoord = tmp;
|
||||
|
||||
|
||||
if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
|
||||
std::string path = tex.C_Str();
|
||||
|
|
|
@ -357,11 +357,7 @@ std::string BaseImporter::GetExtension(const std::string &pFile) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef ASSIMP_USE_HUNTER
|
||||
#include <utf8.h>
|
||||
#else
|
||||
#include "../contrib/utf8cpp/source/utf8.h"
|
||||
#endif
|
||||
#include "utf8.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Convert to UTF8 data
|
||||
|
|
|
@ -41,11 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
||||
# include <zlib.h>
|
||||
#else
|
||||
# include "../contrib/zlib/zlib.h"
|
||||
#endif
|
||||
#include "zlib.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cstddef> // size_t
|
||||
|
|
|
@ -287,7 +287,7 @@ static AI_FORCE_INLINE bool isEndOfCache(size_t pos, size_t cacheSize) {
|
|||
template <class T>
|
||||
AI_FORCE_INLINE bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
|
||||
buffer.resize(m_cacheSize);
|
||||
if (isEndOfCache(m_cachePos, m_cacheSize) || 0 == m_filePos) {
|
||||
if (m_cachePos >= m_cacheSize || 0 == m_filePos) {
|
||||
if (!readNextBlock()) {
|
||||
return false;
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -196,3 +196,10 @@ TEST_F(utPLYImportExport, parseErrorTest) {
|
|||
const aiScene *scene = importer.ReadFileFromMemory(test_file, strlen(test_file), 0);
|
||||
EXPECT_NE(nullptr, scene);
|
||||
}
|
||||
|
||||
// This file is invalid, we just want to ensure that the importer is not crashing
|
||||
TEST_F(utPLYImportExport, parseInvalid) {
|
||||
Assimp::Importer importer;
|
||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/invalid/crash-30d6d0f7c529b3b66b4131700b7a4580cd7082df.ply", 0);
|
||||
EXPECT_EQ(nullptr, scene);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue