replace NULL and avoid ai_assert with more than 2 tests.
This commit is contained in:
@@ -113,7 +113,7 @@ class LogToCallbackRedirector : public LogStream {
|
||||
public:
|
||||
explicit LogToCallbackRedirector(const aiLogStream &s) :
|
||||
stream(s) {
|
||||
ai_assert(NULL != s.callback);
|
||||
ai_assert(nullptr != s.callback);
|
||||
}
|
||||
|
||||
~LogToCallbackRedirector() {
|
||||
@@ -154,20 +154,20 @@ void ReportSceneNotFoundError() {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Reads the given file and returns its content.
|
||||
const aiScene *aiImportFile(const char *pFile, unsigned int pFlags) {
|
||||
return aiImportFileEx(pFile, pFlags, NULL);
|
||||
return aiImportFileEx(pFile, pFlags, nullptr);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiScene *aiImportFileEx(const char *pFile, unsigned int pFlags, aiFileIO *pFS) {
|
||||
return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
|
||||
return aiImportFileExWithProperties(pFile, pFlags, pFS, nullptr);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiScene *aiImportFileExWithProperties(const char *pFile, unsigned int pFlags,
|
||||
aiFileIO *pFS, const aiPropertyStore *props) {
|
||||
ai_assert(NULL != pFile);
|
||||
ai_assert(nullptr != pFile);
|
||||
|
||||
const aiScene *scene = NULL;
|
||||
const aiScene *scene = nullptr;
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// create an Importer for this file
|
||||
@@ -200,7 +200,7 @@ const aiScene *aiImportFileExWithProperties(const char *pFile, unsigned int pFla
|
||||
delete imp;
|
||||
}
|
||||
|
||||
// return imported data. If the import failed the pointer is NULL anyways
|
||||
// return imported data. If the import failed the pointer is nullptr anyways
|
||||
ASSIMP_END_EXCEPTION_REGION(const aiScene *);
|
||||
|
||||
return scene;
|
||||
@@ -212,7 +212,7 @@ const aiScene *aiImportFileFromMemory(
|
||||
unsigned int pLength,
|
||||
unsigned int pFlags,
|
||||
const char *pHint) {
|
||||
return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
|
||||
return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, nullptr);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -222,10 +222,10 @@ const aiScene *aiImportFileFromMemoryWithProperties(
|
||||
unsigned int pFlags,
|
||||
const char *pHint,
|
||||
const aiPropertyStore *props) {
|
||||
ai_assert(NULL != pBuffer);
|
||||
ai_assert(nullptr != pBuffer);
|
||||
ai_assert(0 != pLength);
|
||||
|
||||
const aiScene *scene = NULL;
|
||||
const aiScene *scene = nullptr;
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// create an Importer for this file
|
||||
@@ -253,7 +253,7 @@ const aiScene *aiImportFileFromMemoryWithProperties(
|
||||
gLastErrorString = imp->GetErrorString();
|
||||
delete imp;
|
||||
}
|
||||
// return imported data. If the import failed the pointer is NULL anyways
|
||||
// return imported data. If the import failed the pointer is nullptr anyways
|
||||
ASSIMP_END_EXCEPTION_REGION(const aiScene *);
|
||||
return scene;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ void aiReleaseImport(const aiScene *pScene) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API const aiScene *aiApplyPostProcessing(const aiScene *pScene,
|
||||
unsigned int pFlags) {
|
||||
const aiScene *sc = NULL;
|
||||
const aiScene *sc = nullptr;
|
||||
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
@@ -293,14 +293,14 @@ ASSIMP_API const aiScene *aiApplyPostProcessing(const aiScene *pScene,
|
||||
const ScenePrivateData *priv = ScenePriv(pScene);
|
||||
if (!priv || !priv->mOrigImporter) {
|
||||
ReportSceneNotFoundError();
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
|
||||
|
||||
if (!sc) {
|
||||
aiReleaseImport(pScene);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION(const aiScene *);
|
||||
@@ -311,22 +311,22 @@ ASSIMP_API const aiScene *aiApplyPostProcessing(const aiScene *pScene,
|
||||
ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing(const aiScene *scene,
|
||||
BaseProcess *process,
|
||||
bool requestValidation) {
|
||||
const aiScene *sc(NULL);
|
||||
const aiScene *sc(nullptr);
|
||||
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// find the importer associated with this data
|
||||
const ScenePrivateData *priv = ScenePriv(scene);
|
||||
if (NULL == priv || NULL == priv->mOrigImporter) {
|
||||
if (nullptr == priv || nullptr == priv->mOrigImporter) {
|
||||
ReportSceneNotFoundError();
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sc = priv->mOrigImporter->ApplyCustomizedPostProcessing(process, requestValidation);
|
||||
|
||||
if (!sc) {
|
||||
aiReleaseImport(scene);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ASSIMP_END_EXCEPTION_REGION(const aiScene *);
|
||||
@@ -336,8 +336,8 @@ ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing(const aiScene *scene,
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CallbackToLogRedirector(const char *msg, char *dt) {
|
||||
ai_assert(NULL != msg);
|
||||
ai_assert(NULL != dt);
|
||||
ai_assert(nullptr != msg);
|
||||
ai_assert(nullptr != dt);
|
||||
LogStream *s = (LogStream *)dt;
|
||||
|
||||
s->write(msg);
|
||||
@@ -350,8 +350,8 @@ ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, cons
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
LogStream *stream = LogStream::createDefaultStream(pStream, file);
|
||||
if (!stream) {
|
||||
sout.callback = NULL;
|
||||
sout.user = NULL;
|
||||
sout.callback = nullptr;
|
||||
sout.user = nullptr;
|
||||
} else {
|
||||
sout.callback = &CallbackToLogRedirector;
|
||||
sout.user = (char *)stream;
|
||||
@@ -373,7 +373,7 @@ ASSIMP_API void aiAttachLogStream(const aiLogStream *stream) {
|
||||
gActiveLogStreams[*stream] = lg;
|
||||
|
||||
if (DefaultLogger::isNullLogger()) {
|
||||
DefaultLogger::create(NULL, (gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
|
||||
DefaultLogger::create(nullptr, (gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
|
||||
}
|
||||
DefaultLogger::get()->attachStream(lg);
|
||||
ASSIMP_END_EXCEPTION_REGION(void);
|
||||
@@ -392,7 +392,7 @@ ASSIMP_API aiReturn aiDetachLogStream(const aiLogStream *stream) {
|
||||
if (it == gActiveLogStreams.end()) {
|
||||
return AI_FAILURE;
|
||||
}
|
||||
DefaultLogger::get()->detatchStream(it->second);
|
||||
DefaultLogger::get()->detachStream(it->second);
|
||||
delete it->second;
|
||||
|
||||
gActiveLogStreams.erase(it);
|
||||
@@ -411,12 +411,12 @@ ASSIMP_API void aiDetachAllLogStreams(void) {
|
||||
std::lock_guard<std::mutex> lock(gLogStreamMutex);
|
||||
#endif
|
||||
Logger *logger(DefaultLogger::get());
|
||||
if (NULL == logger) {
|
||||
if (nullptr == logger) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
|
||||
logger->detatchStream(it->second);
|
||||
logger->detachStream(it->second);
|
||||
delete it->second;
|
||||
}
|
||||
gActiveLogStreams.clear();
|
||||
@@ -454,7 +454,7 @@ size_t aiGetImportFormatCount(void) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns the error text of the last failed import process.
|
||||
aiBool aiIsExtensionSupported(const char *szExtension) {
|
||||
ai_assert(NULL != szExtension);
|
||||
ai_assert(nullptr != szExtension);
|
||||
aiBool candoit = AI_FALSE;
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
@@ -469,7 +469,7 @@ aiBool aiIsExtensionSupported(const char *szExtension) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get a list of all file extensions supported by ASSIMP
|
||||
void aiGetExtensionList(aiString *szOut) {
|
||||
ai_assert(NULL != szOut);
|
||||
ai_assert(nullptr != szOut);
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// FIXME: no need to create a temporary Importer instance just for that ..
|
||||
@@ -553,8 +553,8 @@ ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore *p, const char *szName
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Rotation matrix to quaternion
|
||||
ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion *quat, const aiMatrix3x3 *mat) {
|
||||
ai_assert(NULL != quat);
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != quat);
|
||||
ai_assert(nullptr != mat);
|
||||
*quat = aiQuaternion(*mat);
|
||||
}
|
||||
|
||||
@@ -563,23 +563,23 @@ ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion *quat, const aiMatrix3
|
||||
ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4 *mat, aiVector3D *scaling,
|
||||
aiQuaternion *rotation,
|
||||
aiVector3D *position) {
|
||||
ai_assert(NULL != rotation);
|
||||
ai_assert(NULL != position);
|
||||
ai_assert(NULL != scaling);
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != rotation);
|
||||
ai_assert(nullptr != position);
|
||||
ai_assert(nullptr != scaling);
|
||||
ai_assert(nullptr != mat);
|
||||
mat->Decompose(*scaling, *rotation, *position);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Matrix transpose
|
||||
ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
mat->Transpose();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
mat->Transpose();
|
||||
}
|
||||
|
||||
@@ -587,16 +587,16 @@ ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4 *mat) {
|
||||
// Vector transformation
|
||||
ASSIMP_API void aiTransformVecByMatrix3(aiVector3D *vec,
|
||||
const aiMatrix3x3 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != vec);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != vec);
|
||||
*vec *= (*mat);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiTransformVecByMatrix4(aiVector3D *vec,
|
||||
const aiMatrix4x4 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != vec);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != vec);
|
||||
|
||||
*vec *= (*mat);
|
||||
}
|
||||
@@ -606,8 +606,8 @@ ASSIMP_API void aiTransformVecByMatrix4(aiVector3D *vec,
|
||||
ASSIMP_API void aiMultiplyMatrix4(
|
||||
aiMatrix4x4 *dst,
|
||||
const aiMatrix4x4 *src) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != src);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != src);
|
||||
*dst = (*dst) * (*src);
|
||||
}
|
||||
|
||||
@@ -615,8 +615,8 @@ ASSIMP_API void aiMultiplyMatrix4(
|
||||
ASSIMP_API void aiMultiplyMatrix3(
|
||||
aiMatrix3x3 *dst,
|
||||
const aiMatrix3x3 *src) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != src);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != src);
|
||||
*dst = (*dst) * (*src);
|
||||
}
|
||||
|
||||
@@ -624,23 +624,23 @@ ASSIMP_API void aiMultiplyMatrix3(
|
||||
// Matrix identity
|
||||
ASSIMP_API void aiIdentityMatrix3(
|
||||
aiMatrix3x3 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
*mat = aiMatrix3x3();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiIdentityMatrix4(
|
||||
aiMatrix4x4 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
*mat = aiMatrix4x4();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API C_STRUCT const aiImporterDesc *aiGetImporterDesc(const char *extension) {
|
||||
if (NULL == extension) {
|
||||
return NULL;
|
||||
if (nullptr == extension) {
|
||||
return nullptr;
|
||||
}
|
||||
const aiImporterDesc *desc(NULL);
|
||||
const aiImporterDesc *desc(nullptr);
|
||||
std::vector<BaseImporter *> out;
|
||||
GetImporterInstanceList(out);
|
||||
for (size_t i = 0; i < out.size(); ++i) {
|
||||
@@ -659,8 +659,8 @@ ASSIMP_API C_STRUCT const aiImporterDesc *aiGetImporterDesc(const char *extensio
|
||||
ASSIMP_API int aiVector2AreEqual(
|
||||
const C_STRUCT aiVector2D *a,
|
||||
const C_STRUCT aiVector2D *b) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return *a == *b;
|
||||
}
|
||||
|
||||
@@ -669,8 +669,8 @@ ASSIMP_API int aiVector2AreEqualEpsilon(
|
||||
const C_STRUCT aiVector2D *a,
|
||||
const C_STRUCT aiVector2D *b,
|
||||
const float epsilon) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return a->Equal(*b, epsilon);
|
||||
}
|
||||
|
||||
@@ -678,8 +678,8 @@ ASSIMP_API int aiVector2AreEqualEpsilon(
|
||||
ASSIMP_API void aiVector2Add(
|
||||
C_STRUCT aiVector2D *dst,
|
||||
const C_STRUCT aiVector2D *src) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != src);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != src);
|
||||
*dst = *dst + *src;
|
||||
}
|
||||
|
||||
@@ -687,8 +687,8 @@ ASSIMP_API void aiVector2Add(
|
||||
ASSIMP_API void aiVector2Subtract(
|
||||
C_STRUCT aiVector2D *dst,
|
||||
const C_STRUCT aiVector2D *src) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != src);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != src);
|
||||
*dst = *dst - *src;
|
||||
}
|
||||
|
||||
@@ -696,7 +696,7 @@ ASSIMP_API void aiVector2Subtract(
|
||||
ASSIMP_API void aiVector2Scale(
|
||||
C_STRUCT aiVector2D *dst,
|
||||
const float s) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(nullptr != dst);
|
||||
*dst *= s;
|
||||
}
|
||||
|
||||
@@ -704,8 +704,8 @@ ASSIMP_API void aiVector2Scale(
|
||||
ASSIMP_API void aiVector2SymMul(
|
||||
C_STRUCT aiVector2D *dst,
|
||||
const C_STRUCT aiVector2D *other) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != other);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != other);
|
||||
*dst = dst->SymMul(*other);
|
||||
}
|
||||
|
||||
@@ -713,7 +713,7 @@ ASSIMP_API void aiVector2SymMul(
|
||||
ASSIMP_API void aiVector2DivideByScalar(
|
||||
C_STRUCT aiVector2D *dst,
|
||||
const float s) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(nullptr != dst);
|
||||
*dst /= s;
|
||||
}
|
||||
|
||||
@@ -721,29 +721,29 @@ ASSIMP_API void aiVector2DivideByScalar(
|
||||
ASSIMP_API void aiVector2DivideByVector(
|
||||
C_STRUCT aiVector2D *dst,
|
||||
C_STRUCT aiVector2D *v) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != v);
|
||||
*dst = *dst / *v;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API float aiVector2Length(
|
||||
const C_STRUCT aiVector2D *v) {
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(nullptr != v);
|
||||
return v->Length();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API float aiVector2SquareLength(
|
||||
const C_STRUCT aiVector2D *v) {
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(nullptr != v);
|
||||
return v->SquareLength();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiVector2Negate(
|
||||
C_STRUCT aiVector2D *dst) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(nullptr != dst);
|
||||
*dst = -(*dst);
|
||||
}
|
||||
|
||||
@@ -751,15 +751,15 @@ ASSIMP_API void aiVector2Negate(
|
||||
ASSIMP_API float aiVector2DotProduct(
|
||||
const C_STRUCT aiVector2D *a,
|
||||
const C_STRUCT aiVector2D *b) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return (*a) * (*b);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiVector2Normalize(
|
||||
C_STRUCT aiVector2D *v) {
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(nullptr != v);
|
||||
v->Normalize();
|
||||
}
|
||||
|
||||
@@ -767,8 +767,8 @@ ASSIMP_API void aiVector2Normalize(
|
||||
ASSIMP_API int aiVector3AreEqual(
|
||||
const C_STRUCT aiVector3D *a,
|
||||
const C_STRUCT aiVector3D *b) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return *a == *b;
|
||||
}
|
||||
|
||||
@@ -777,8 +777,8 @@ ASSIMP_API int aiVector3AreEqualEpsilon(
|
||||
const C_STRUCT aiVector3D *a,
|
||||
const C_STRUCT aiVector3D *b,
|
||||
const float epsilon) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return a->Equal(*b, epsilon);
|
||||
}
|
||||
|
||||
@@ -786,8 +786,8 @@ ASSIMP_API int aiVector3AreEqualEpsilon(
|
||||
ASSIMP_API int aiVector3LessThan(
|
||||
const C_STRUCT aiVector3D *a,
|
||||
const C_STRUCT aiVector3D *b) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return *a < *b;
|
||||
}
|
||||
|
||||
@@ -795,8 +795,8 @@ ASSIMP_API int aiVector3LessThan(
|
||||
ASSIMP_API void aiVector3Add(
|
||||
C_STRUCT aiVector3D *dst,
|
||||
const C_STRUCT aiVector3D *src) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != src);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != src);
|
||||
*dst = *dst + *src;
|
||||
}
|
||||
|
||||
@@ -804,8 +804,8 @@ ASSIMP_API void aiVector3Add(
|
||||
ASSIMP_API void aiVector3Subtract(
|
||||
C_STRUCT aiVector3D *dst,
|
||||
const C_STRUCT aiVector3D *src) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != src);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != src);
|
||||
*dst = *dst - *src;
|
||||
}
|
||||
|
||||
@@ -813,7 +813,7 @@ ASSIMP_API void aiVector3Subtract(
|
||||
ASSIMP_API void aiVector3Scale(
|
||||
C_STRUCT aiVector3D *dst,
|
||||
const float s) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(nullptr != dst);
|
||||
*dst *= s;
|
||||
}
|
||||
|
||||
@@ -821,15 +821,15 @@ ASSIMP_API void aiVector3Scale(
|
||||
ASSIMP_API void aiVector3SymMul(
|
||||
C_STRUCT aiVector3D *dst,
|
||||
const C_STRUCT aiVector3D *other) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != other);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != other);
|
||||
*dst = dst->SymMul(*other);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiVector3DivideByScalar(
|
||||
C_STRUCT aiVector3D *dst, const float s) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(nullptr != dst);
|
||||
*dst /= s;
|
||||
}
|
||||
|
||||
@@ -837,29 +837,29 @@ ASSIMP_API void aiVector3DivideByScalar(
|
||||
ASSIMP_API void aiVector3DivideByVector(
|
||||
C_STRUCT aiVector3D *dst,
|
||||
C_STRUCT aiVector3D *v) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != v);
|
||||
*dst = *dst / *v;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API float aiVector3Length(
|
||||
const C_STRUCT aiVector3D *v) {
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(nullptr != v);
|
||||
return v->Length();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API float aiVector3SquareLength(
|
||||
const C_STRUCT aiVector3D *v) {
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(nullptr != v);
|
||||
return v->SquareLength();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiVector3Negate(
|
||||
C_STRUCT aiVector3D *dst) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(nullptr != dst);
|
||||
*dst = -(*dst);
|
||||
}
|
||||
|
||||
@@ -867,8 +867,8 @@ ASSIMP_API void aiVector3Negate(
|
||||
ASSIMP_API float aiVector3DotProduct(
|
||||
const C_STRUCT aiVector3D *a,
|
||||
const C_STRUCT aiVector3D *b) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return (*a) * (*b);
|
||||
}
|
||||
|
||||
@@ -877,23 +877,23 @@ ASSIMP_API void aiVector3CrossProduct(
|
||||
C_STRUCT aiVector3D *dst,
|
||||
const C_STRUCT aiVector3D *a,
|
||||
const C_STRUCT aiVector3D *b) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
*dst = *a ^ *b;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiVector3Normalize(
|
||||
C_STRUCT aiVector3D *v) {
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(nullptr != v);
|
||||
v->Normalize();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiVector3NormalizeSafe(
|
||||
C_STRUCT aiVector3D *v) {
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(nullptr != v);
|
||||
v->NormalizeSafe();
|
||||
}
|
||||
|
||||
@@ -901,8 +901,8 @@ ASSIMP_API void aiVector3NormalizeSafe(
|
||||
ASSIMP_API void aiVector3RotateByQuaternion(
|
||||
C_STRUCT aiVector3D *v,
|
||||
const C_STRUCT aiQuaternion *q) {
|
||||
ai_assert(NULL != v);
|
||||
ai_assert(NULL != q);
|
||||
ai_assert(nullptr != v);
|
||||
ai_assert(nullptr != q);
|
||||
*v = q->Rotate(*v);
|
||||
}
|
||||
|
||||
@@ -910,8 +910,8 @@ ASSIMP_API void aiVector3RotateByQuaternion(
|
||||
ASSIMP_API void aiMatrix3FromMatrix4(
|
||||
C_STRUCT aiMatrix3x3 *dst,
|
||||
const C_STRUCT aiMatrix4x4 *mat) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != mat);
|
||||
*dst = aiMatrix3x3(*mat);
|
||||
}
|
||||
|
||||
@@ -919,8 +919,8 @@ ASSIMP_API void aiMatrix3FromMatrix4(
|
||||
ASSIMP_API void aiMatrix3FromQuaternion(
|
||||
C_STRUCT aiMatrix3x3 *mat,
|
||||
const C_STRUCT aiQuaternion *q) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != q);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != q);
|
||||
*mat = q->GetMatrix();
|
||||
}
|
||||
|
||||
@@ -928,8 +928,8 @@ ASSIMP_API void aiMatrix3FromQuaternion(
|
||||
ASSIMP_API int aiMatrix3AreEqual(
|
||||
const C_STRUCT aiMatrix3x3 *a,
|
||||
const C_STRUCT aiMatrix3x3 *b) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return *a == *b;
|
||||
}
|
||||
|
||||
@@ -938,20 +938,20 @@ ASSIMP_API int aiMatrix3AreEqualEpsilon(
|
||||
const C_STRUCT aiMatrix3x3 *a,
|
||||
const C_STRUCT aiMatrix3x3 *b,
|
||||
const float epsilon) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return a->Equal(*b, epsilon);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiMatrix3Inverse(C_STRUCT aiMatrix3x3 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
mat->Inverse();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API float aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
return mat->Determinant();
|
||||
}
|
||||
|
||||
@@ -959,7 +959,7 @@ ASSIMP_API float aiMatrix3Determinant(const C_STRUCT aiMatrix3x3 *mat) {
|
||||
ASSIMP_API void aiMatrix3RotationZ(
|
||||
C_STRUCT aiMatrix3x3 *mat,
|
||||
const float angle) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
aiMatrix3x3::RotationZ(angle, *mat);
|
||||
}
|
||||
|
||||
@@ -968,8 +968,8 @@ ASSIMP_API void aiMatrix3FromRotationAroundAxis(
|
||||
C_STRUCT aiMatrix3x3 *mat,
|
||||
const C_STRUCT aiVector3D *axis,
|
||||
const float angle) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != axis);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != axis);
|
||||
aiMatrix3x3::Rotation(angle, *axis, *mat);
|
||||
}
|
||||
|
||||
@@ -977,8 +977,8 @@ ASSIMP_API void aiMatrix3FromRotationAroundAxis(
|
||||
ASSIMP_API void aiMatrix3Translation(
|
||||
C_STRUCT aiMatrix3x3 *mat,
|
||||
const C_STRUCT aiVector2D *translation) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != translation);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != translation);
|
||||
aiMatrix3x3::Translation(*translation, *mat);
|
||||
}
|
||||
|
||||
@@ -987,9 +987,9 @@ ASSIMP_API void aiMatrix3FromTo(
|
||||
C_STRUCT aiMatrix3x3 *mat,
|
||||
const C_STRUCT aiVector3D *from,
|
||||
const C_STRUCT aiVector3D *to) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != from);
|
||||
ai_assert(NULL != to);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != from);
|
||||
ai_assert(nullptr != to);
|
||||
aiMatrix3x3::FromToMatrix(*from, *to, *mat);
|
||||
}
|
||||
|
||||
@@ -997,8 +997,8 @@ ASSIMP_API void aiMatrix3FromTo(
|
||||
ASSIMP_API void aiMatrix4FromMatrix3(
|
||||
C_STRUCT aiMatrix4x4 *dst,
|
||||
const C_STRUCT aiMatrix3x3 *mat) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != mat);
|
||||
*dst = aiMatrix4x4(*mat);
|
||||
}
|
||||
|
||||
@@ -1008,10 +1008,10 @@ ASSIMP_API void aiMatrix4FromScalingQuaternionPosition(
|
||||
const C_STRUCT aiVector3D *scaling,
|
||||
const C_STRUCT aiQuaternion *rotation,
|
||||
const C_STRUCT aiVector3D *position) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != scaling);
|
||||
ai_assert(NULL != rotation);
|
||||
ai_assert(NULL != position);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != scaling);
|
||||
ai_assert(nullptr != rotation);
|
||||
ai_assert(nullptr != position);
|
||||
*mat = aiMatrix4x4(*scaling, *rotation, *position);
|
||||
}
|
||||
|
||||
@@ -1019,8 +1019,8 @@ ASSIMP_API void aiMatrix4FromScalingQuaternionPosition(
|
||||
ASSIMP_API void aiMatrix4Add(
|
||||
C_STRUCT aiMatrix4x4 *dst,
|
||||
const C_STRUCT aiMatrix4x4 *src) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != src);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != src);
|
||||
*dst = *dst + *src;
|
||||
}
|
||||
|
||||
@@ -1028,8 +1028,8 @@ ASSIMP_API void aiMatrix4Add(
|
||||
ASSIMP_API int aiMatrix4AreEqual(
|
||||
const C_STRUCT aiMatrix4x4 *a,
|
||||
const C_STRUCT aiMatrix4x4 *b) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return *a == *b;
|
||||
}
|
||||
|
||||
@@ -1038,26 +1038,26 @@ ASSIMP_API int aiMatrix4AreEqualEpsilon(
|
||||
const C_STRUCT aiMatrix4x4 *a,
|
||||
const C_STRUCT aiMatrix4x4 *b,
|
||||
const float epsilon) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return a->Equal(*b, epsilon);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiMatrix4Inverse(C_STRUCT aiMatrix4x4 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
mat->Inverse();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API float aiMatrix4Determinant(const C_STRUCT aiMatrix4x4 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
return mat->Determinant();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API int aiMatrix4IsIdentity(const C_STRUCT aiMatrix4x4 *mat) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
return mat->IsIdentity();
|
||||
}
|
||||
|
||||
@@ -1067,10 +1067,10 @@ ASSIMP_API void aiMatrix4DecomposeIntoScalingEulerAnglesPosition(
|
||||
C_STRUCT aiVector3D *scaling,
|
||||
C_STRUCT aiVector3D *rotation,
|
||||
C_STRUCT aiVector3D *position) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != scaling);
|
||||
ai_assert(NULL != rotation);
|
||||
ai_assert(NULL != position);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != scaling);
|
||||
ai_assert(nullptr != rotation);
|
||||
ai_assert(nullptr != position);
|
||||
mat->Decompose(*scaling, *rotation, *position);
|
||||
}
|
||||
|
||||
@@ -1081,11 +1081,11 @@ ASSIMP_API void aiMatrix4DecomposeIntoScalingAxisAnglePosition(
|
||||
C_STRUCT aiVector3D *axis,
|
||||
float *angle,
|
||||
C_STRUCT aiVector3D *position) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != scaling);
|
||||
ai_assert(NULL != axis);
|
||||
ai_assert(NULL != angle);
|
||||
ai_assert(NULL != position);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != scaling);
|
||||
ai_assert(nullptr != axis);
|
||||
ai_assert(nullptr != angle);
|
||||
ai_assert(nullptr != position);
|
||||
mat->Decompose(*scaling, *axis, *angle, *position);
|
||||
}
|
||||
|
||||
@@ -1094,9 +1094,9 @@ ASSIMP_API void aiMatrix4DecomposeNoScaling(
|
||||
const C_STRUCT aiMatrix4x4 *mat,
|
||||
C_STRUCT aiQuaternion *rotation,
|
||||
C_STRUCT aiVector3D *position) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != rotation);
|
||||
ai_assert(NULL != position);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != rotation);
|
||||
ai_assert(nullptr != position);
|
||||
mat->DecomposeNoScaling(*rotation, *position);
|
||||
}
|
||||
|
||||
@@ -1104,7 +1104,7 @@ ASSIMP_API void aiMatrix4DecomposeNoScaling(
|
||||
ASSIMP_API void aiMatrix4FromEulerAngles(
|
||||
C_STRUCT aiMatrix4x4 *mat,
|
||||
float x, float y, float z) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
mat->FromEulerAnglesXYZ(x, y, z);
|
||||
}
|
||||
|
||||
@@ -1112,7 +1112,7 @@ ASSIMP_API void aiMatrix4FromEulerAngles(
|
||||
ASSIMP_API void aiMatrix4RotationX(
|
||||
C_STRUCT aiMatrix4x4 *mat,
|
||||
const float angle) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
aiMatrix4x4::RotationX(angle, *mat);
|
||||
}
|
||||
|
||||
@@ -1128,7 +1128,7 @@ ASSIMP_API void aiMatrix4RotationY(
|
||||
ASSIMP_API void aiMatrix4RotationZ(
|
||||
C_STRUCT aiMatrix4x4 *mat,
|
||||
const float angle) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(nullptr != mat);
|
||||
aiMatrix4x4::RotationZ(angle, *mat);
|
||||
}
|
||||
|
||||
@@ -1137,8 +1137,8 @@ ASSIMP_API void aiMatrix4FromRotationAroundAxis(
|
||||
C_STRUCT aiMatrix4x4 *mat,
|
||||
const C_STRUCT aiVector3D *axis,
|
||||
const float angle) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != axis);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != axis);
|
||||
aiMatrix4x4::Rotation(angle, *axis, *mat);
|
||||
}
|
||||
|
||||
@@ -1146,8 +1146,8 @@ ASSIMP_API void aiMatrix4FromRotationAroundAxis(
|
||||
ASSIMP_API void aiMatrix4Translation(
|
||||
C_STRUCT aiMatrix4x4 *mat,
|
||||
const C_STRUCT aiVector3D *translation) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != translation);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != translation);
|
||||
aiMatrix4x4::Translation(*translation, *mat);
|
||||
}
|
||||
|
||||
@@ -1155,8 +1155,8 @@ ASSIMP_API void aiMatrix4Translation(
|
||||
ASSIMP_API void aiMatrix4Scaling(
|
||||
C_STRUCT aiMatrix4x4 *mat,
|
||||
const C_STRUCT aiVector3D *scaling) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != scaling);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != scaling);
|
||||
aiMatrix4x4::Scaling(*scaling, *mat);
|
||||
}
|
||||
|
||||
@@ -1165,9 +1165,9 @@ ASSIMP_API void aiMatrix4FromTo(
|
||||
C_STRUCT aiMatrix4x4 *mat,
|
||||
const C_STRUCT aiVector3D *from,
|
||||
const C_STRUCT aiVector3D *to) {
|
||||
ai_assert(NULL != mat);
|
||||
ai_assert(NULL != from);
|
||||
ai_assert(NULL != to);
|
||||
ai_assert(nullptr != mat);
|
||||
ai_assert(nullptr != from);
|
||||
ai_assert(nullptr != to);
|
||||
aiMatrix4x4::FromToMatrix(*from, *to, *mat);
|
||||
}
|
||||
|
||||
@@ -1175,7 +1175,7 @@ ASSIMP_API void aiMatrix4FromTo(
|
||||
ASSIMP_API void aiQuaternionFromEulerAngles(
|
||||
C_STRUCT aiQuaternion *q,
|
||||
float x, float y, float z) {
|
||||
ai_assert(NULL != q);
|
||||
ai_assert(nullptr != q);
|
||||
*q = aiQuaternion(x, y, z);
|
||||
}
|
||||
|
||||
@@ -1184,8 +1184,8 @@ ASSIMP_API void aiQuaternionFromAxisAngle(
|
||||
C_STRUCT aiQuaternion *q,
|
||||
const C_STRUCT aiVector3D *axis,
|
||||
const float angle) {
|
||||
ai_assert(NULL != q);
|
||||
ai_assert(NULL != axis);
|
||||
ai_assert(nullptr != q);
|
||||
ai_assert(nullptr != axis);
|
||||
*q = aiQuaternion(*axis, angle);
|
||||
}
|
||||
|
||||
@@ -1193,8 +1193,8 @@ ASSIMP_API void aiQuaternionFromAxisAngle(
|
||||
ASSIMP_API void aiQuaternionFromNormalizedQuaternion(
|
||||
C_STRUCT aiQuaternion *q,
|
||||
const C_STRUCT aiVector3D *normalized) {
|
||||
ai_assert(NULL != q);
|
||||
ai_assert(NULL != normalized);
|
||||
ai_assert(nullptr != q);
|
||||
ai_assert(nullptr != normalized);
|
||||
*q = aiQuaternion(*normalized);
|
||||
}
|
||||
|
||||
@@ -1202,8 +1202,8 @@ ASSIMP_API void aiQuaternionFromNormalizedQuaternion(
|
||||
ASSIMP_API int aiQuaternionAreEqual(
|
||||
const C_STRUCT aiQuaternion *a,
|
||||
const C_STRUCT aiQuaternion *b) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return *a == *b;
|
||||
}
|
||||
|
||||
@@ -1212,22 +1212,22 @@ ASSIMP_API int aiQuaternionAreEqualEpsilon(
|
||||
const C_STRUCT aiQuaternion *a,
|
||||
const C_STRUCT aiQuaternion *b,
|
||||
const float epsilon) {
|
||||
ai_assert(NULL != a);
|
||||
ai_assert(NULL != b);
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
return a->Equal(*b, epsilon);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiQuaternionNormalize(
|
||||
C_STRUCT aiQuaternion *q) {
|
||||
ai_assert(NULL != q);
|
||||
ai_assert(nullptr != q);
|
||||
q->Normalize();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiQuaternionConjugate(
|
||||
C_STRUCT aiQuaternion *q) {
|
||||
ai_assert(NULL != q);
|
||||
ai_assert(nullptr != q);
|
||||
q->Conjugate();
|
||||
}
|
||||
|
||||
@@ -1235,8 +1235,8 @@ ASSIMP_API void aiQuaternionConjugate(
|
||||
ASSIMP_API void aiQuaternionMultiply(
|
||||
C_STRUCT aiQuaternion *dst,
|
||||
const C_STRUCT aiQuaternion *q) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != q);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != q);
|
||||
*dst = (*dst) * (*q);
|
||||
}
|
||||
|
||||
@@ -1246,8 +1246,8 @@ ASSIMP_API void aiQuaternionInterpolate(
|
||||
const C_STRUCT aiQuaternion *start,
|
||||
const C_STRUCT aiQuaternion *end,
|
||||
const float factor) {
|
||||
ai_assert(NULL != dst);
|
||||
ai_assert(NULL != start);
|
||||
ai_assert(NULL != end);
|
||||
ai_assert(nullptr != dst);
|
||||
ai_assert(nullptr != start);
|
||||
ai_assert(nullptr != end);
|
||||
aiQuaternion::Interpolate(*dst, *start, *end, factor);
|
||||
}
|
||||
|
||||
@@ -45,28 +45,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* @brief Implementation of BaseImporter
|
||||
*/
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include "FileSystemFilter.h"
|
||||
#include "Importer.h"
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/ByteSwapper.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <ios>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <cctype>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
BaseImporter::BaseImporter() AI_NO_EXCEPT
|
||||
: m_progress() {
|
||||
: m_progress() {
|
||||
/**
|
||||
* Assimp Importer
|
||||
* unit conversions available
|
||||
@@ -89,8 +89,7 @@ BaseImporter::~BaseImporter() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
void BaseImporter::UpdateImporterScale( Importer* pImp )
|
||||
{
|
||||
void BaseImporter::UpdateImporterScale(Importer *pImp) {
|
||||
ai_assert(pImp != nullptr);
|
||||
ai_assert(importerScale != 0.0);
|
||||
ai_assert(fileScale != 0.0);
|
||||
@@ -98,15 +97,14 @@ void BaseImporter::UpdateImporterScale( Importer* pImp )
|
||||
double activeScale = importerScale * fileScale;
|
||||
|
||||
// Set active scaling
|
||||
pImp->SetPropertyFloat( AI_CONFIG_APP_SCALE_KEY, static_cast<float>( activeScale) );
|
||||
pImp->SetPropertyFloat(AI_CONFIG_APP_SCALE_KEY, static_cast<float>(activeScale));
|
||||
|
||||
ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale );
|
||||
ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file and returns the imported data.
|
||||
aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) {
|
||||
|
||||
aiScene *BaseImporter::ReadFile(Importer *pImp, const std::string &pFile, IOSystem *pIOHandler) {
|
||||
|
||||
m_progress = pImp->GetProgressHandler();
|
||||
if (nullptr == m_progress) {
|
||||
@@ -116,25 +114,23 @@ aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSyst
|
||||
ai_assert(m_progress);
|
||||
|
||||
// Gather configuration properties for this run
|
||||
SetupProperties( pImp );
|
||||
SetupProperties(pImp);
|
||||
|
||||
// Construct a file system filter to improve our success ratio at reading external files
|
||||
FileSystemFilter filter(pFile,pIOHandler);
|
||||
FileSystemFilter filter(pFile, pIOHandler);
|
||||
|
||||
// create a scene object to hold the data
|
||||
std::unique_ptr<aiScene> sc(new aiScene());
|
||||
|
||||
// dispatch importing
|
||||
try
|
||||
{
|
||||
InternReadFile( pFile, sc.get(), &filter);
|
||||
try {
|
||||
InternReadFile(pFile, sc.get(), &filter);
|
||||
|
||||
// Calculate import scale hook - required because pImp not available anywhere else
|
||||
// passes scale into ScaleProcess
|
||||
UpdateImporterScale(pImp);
|
||||
|
||||
|
||||
} catch( const std::exception& err ) {
|
||||
} catch (const std::exception &err) {
|
||||
// extract error description
|
||||
m_ErrorText = err.what();
|
||||
ASSIMP_LOG_ERROR(m_ErrorText);
|
||||
@@ -146,69 +142,66 @@ aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSyst
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BaseImporter::SetupProperties(const Importer* )
|
||||
{
|
||||
void BaseImporter::SetupProperties(const Importer *) {
|
||||
// the default implementation does nothing
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
||||
const aiImporterDesc* desc = GetInfo();
|
||||
void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
|
||||
const aiImporterDesc *desc = GetInfo();
|
||||
ai_assert(desc != nullptr);
|
||||
|
||||
const char* ext = desc->mFileExtensions;
|
||||
ai_assert(ext != nullptr );
|
||||
const char *ext = desc->mFileExtensions;
|
||||
ai_assert(ext != nullptr);
|
||||
|
||||
const char* last = ext;
|
||||
const char *last = ext;
|
||||
do {
|
||||
if (!*ext || *ext == ' ') {
|
||||
extensions.insert(std::string(last,ext-last));
|
||||
ai_assert(ext-last > 0);
|
||||
extensions.insert(std::string(last, ext - last));
|
||||
ai_assert(ext - last > 0);
|
||||
last = ext;
|
||||
while(*last == ' ') {
|
||||
while (*last == ' ') {
|
||||
++last;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(*ext++);
|
||||
} while (*ext++);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/*static*/ bool BaseImporter::SearchFileHeaderForToken( IOSystem* pIOHandler,
|
||||
const std::string& pFile,
|
||||
const char** tokens,
|
||||
unsigned int numTokens,
|
||||
unsigned int searchBytes /* = 200 */,
|
||||
bool tokensSol /* false */,
|
||||
bool noAlphaBeforeTokens /* false */)
|
||||
{
|
||||
ai_assert( nullptr != tokens );
|
||||
ai_assert( 0 != numTokens );
|
||||
ai_assert( 0 != searchBytes);
|
||||
/*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem *pIOHandler,
|
||||
const std::string &pFile,
|
||||
const char **tokens,
|
||||
unsigned int numTokens,
|
||||
unsigned int searchBytes /* = 200 */,
|
||||
bool tokensSol /* false */,
|
||||
bool noAlphaBeforeTokens /* false */) {
|
||||
ai_assert(nullptr != tokens);
|
||||
ai_assert(0 != numTokens);
|
||||
ai_assert(0 != searchBytes);
|
||||
|
||||
if ( nullptr == pIOHandler ) {
|
||||
if (nullptr == pIOHandler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
|
||||
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile));
|
||||
if (pStream) {
|
||||
// read 200 characters from the file
|
||||
std::unique_ptr<char[]> _buffer (new char[searchBytes+1 /* for the '\0' */]);
|
||||
char *buffer( _buffer.get() );
|
||||
const size_t read( pStream->Read(buffer,1,searchBytes) );
|
||||
if( 0 == read ) {
|
||||
std::unique_ptr<char[]> _buffer(new char[searchBytes + 1 /* for the '\0' */]);
|
||||
char *buffer(_buffer.get());
|
||||
const size_t read(pStream->Read(buffer, 1, searchBytes));
|
||||
if (0 == read) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < read; ++i ) {
|
||||
buffer[ i ] = static_cast<char>( ::tolower( buffer[ i ] ) );
|
||||
for (size_t i = 0; i < read; ++i) {
|
||||
buffer[i] = static_cast<char>(::tolower(buffer[i]));
|
||||
}
|
||||
|
||||
// It is not a proper handling of unicode files here ...
|
||||
// ehm ... but it works in most cases.
|
||||
char* cur = buffer,*cur2 = buffer,*end = &buffer[read];
|
||||
while (cur != end) {
|
||||
if( *cur ) {
|
||||
char *cur = buffer, *cur2 = buffer, *end = &buffer[read];
|
||||
while (cur != end) {
|
||||
if (*cur) {
|
||||
*cur2++ = *cur;
|
||||
}
|
||||
++cur;
|
||||
@@ -216,17 +209,17 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
||||
*cur2 = '\0';
|
||||
|
||||
std::string token;
|
||||
for (unsigned int i = 0; i < numTokens; ++i ) {
|
||||
ai_assert( nullptr != tokens[i] );
|
||||
const size_t len( strlen( tokens[ i ] ) );
|
||||
for (unsigned int i = 0; i < numTokens; ++i) {
|
||||
ai_assert(nullptr != tokens[i]);
|
||||
const size_t len(strlen(tokens[i]));
|
||||
token.clear();
|
||||
const char *ptr( tokens[ i ] );
|
||||
for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) {
|
||||
token.push_back( static_cast<char>( tolower( *ptr ) ) );
|
||||
const char *ptr(tokens[i]);
|
||||
for (size_t tokIdx = 0; tokIdx < len; ++tokIdx) {
|
||||
token.push_back(static_cast<char>(tolower(*ptr)));
|
||||
++ptr;
|
||||
}
|
||||
const char* r = strstr( buffer, token.c_str() );
|
||||
if( !r ) {
|
||||
const char *r = strstr(buffer, token.c_str());
|
||||
if (!r) {
|
||||
continue;
|
||||
}
|
||||
// We need to make sure that we didn't accidentially identify the end of another token as our token,
|
||||
@@ -237,7 +230,7 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
||||
// We got a match, either we don't care where it is, or it happens to
|
||||
// be in the beginning of the file / line
|
||||
if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
|
||||
ASSIMP_LOG_DEBUG_F( "Found positive match for header keyword: ", tokens[i] );
|
||||
ASSIMP_LOG_DEBUG_F("Found positive match for header keyword: ", tokens[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -248,26 +241,25 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Simple check for file extension
|
||||
/*static*/ bool BaseImporter::SimpleExtensionCheck (const std::string& pFile,
|
||||
const char* ext0,
|
||||
const char* ext1,
|
||||
const char* ext2)
|
||||
{
|
||||
/*static*/ bool BaseImporter::SimpleExtensionCheck(const std::string &pFile,
|
||||
const char *ext0,
|
||||
const char *ext1,
|
||||
const char *ext2) {
|
||||
std::string::size_type pos = pFile.find_last_of('.');
|
||||
|
||||
// no file extension - can't read
|
||||
if( pos == std::string::npos)
|
||||
if (pos == std::string::npos)
|
||||
return false;
|
||||
|
||||
const char* ext_real = & pFile[ pos+1 ];
|
||||
if( !ASSIMP_stricmp(ext_real,ext0) )
|
||||
const char *ext_real = &pFile[pos + 1];
|
||||
if (!ASSIMP_stricmp(ext_real, ext0))
|
||||
return true;
|
||||
|
||||
// check for other, optional, file extensions
|
||||
if (ext1 && !ASSIMP_stricmp(ext_real,ext1))
|
||||
if (ext1 && !ASSIMP_stricmp(ext_real, ext1))
|
||||
return true;
|
||||
|
||||
if (ext2 && !ASSIMP_stricmp(ext_real,ext2))
|
||||
if (ext2 && !ASSIMP_stricmp(ext_real, ext2))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -275,7 +267,7 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get file extension from path
|
||||
std::string BaseImporter::GetExtension( const std::string& file ) {
|
||||
std::string BaseImporter::GetExtension(const std::string &file) {
|
||||
std::string::size_type pos = file.find_last_of('.');
|
||||
|
||||
// no file extension at all
|
||||
@@ -284,34 +276,33 @@ std::string BaseImporter::GetExtension( const std::string& file ) {
|
||||
}
|
||||
|
||||
// thanks to Andy Maloney for the hint
|
||||
std::string ret = file.substr( pos + 1 );
|
||||
std::transform( ret.begin(), ret.end(), ret.begin(), ToLower<char>);
|
||||
std::string ret = file.substr(pos + 1);
|
||||
std::transform(ret.begin(), ret.end(), ret.begin(), ToLower<char>);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Check for magic bytes at the beginning of the file.
|
||||
/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
|
||||
const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
|
||||
{
|
||||
ai_assert( size <= 16 );
|
||||
ai_assert( _magic );
|
||||
/* static */ bool BaseImporter::CheckMagicToken(IOSystem *pIOHandler, const std::string &pFile,
|
||||
const void *_magic, unsigned int num, unsigned int offset, unsigned int size) {
|
||||
ai_assert(size <= 16);
|
||||
ai_assert(_magic);
|
||||
|
||||
if (!pIOHandler) {
|
||||
return false;
|
||||
}
|
||||
union {
|
||||
const char* magic;
|
||||
const uint16_t* magic_u16;
|
||||
const uint32_t* magic_u32;
|
||||
const char *magic;
|
||||
const uint16_t *magic_u16;
|
||||
const uint32_t *magic_u32;
|
||||
};
|
||||
magic = reinterpret_cast<const char*>(_magic);
|
||||
std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
|
||||
magic = reinterpret_cast<const char *>(_magic);
|
||||
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile));
|
||||
if (pStream) {
|
||||
|
||||
// skip to offset
|
||||
pStream->Seek(offset,aiOrigin_SET);
|
||||
pStream->Seek(offset, aiOrigin_SET);
|
||||
|
||||
// read 'size' characters from the file
|
||||
union {
|
||||
@@ -319,7 +310,7 @@ std::string BaseImporter::GetExtension( const std::string& file ) {
|
||||
uint16_t data_u16[8];
|
||||
uint32_t data_u32[4];
|
||||
};
|
||||
if(size != pStream->Read(data,1,size)) {
|
||||
if (size != pStream->Read(data, 1, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -333,17 +324,15 @@ std::string BaseImporter::GetExtension( const std::string& file ) {
|
||||
if (data_u16[0] == *magic_u16 || data_u16[0] == rev) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (4 == size) {
|
||||
} else if (4 == size) {
|
||||
uint32_t rev = *magic_u32;
|
||||
ByteSwap::Swap(&rev);
|
||||
if (data_u32[0] == *magic_u32 || data_u32[0] == rev) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// any length ... just compare
|
||||
if(!memcmp(magic,data,size)) {
|
||||
if (!memcmp(magic, data, size)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -354,61 +343,59 @@ std::string BaseImporter::GetExtension( const std::string& file ) {
|
||||
}
|
||||
|
||||
#ifdef ASSIMP_USE_HUNTER
|
||||
# include <utf8/utf8.h>
|
||||
#include <utf8/utf8.h>
|
||||
#else
|
||||
# include "../contrib/utf8cpp/source/utf8.h"
|
||||
#include "../contrib/utf8cpp/source/utf8.h"
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Convert to UTF8 data
|
||||
void BaseImporter::ConvertToUTF8(std::vector<char>& data)
|
||||
{
|
||||
void BaseImporter::ConvertToUTF8(std::vector<char> &data) {
|
||||
//ConversionResult result;
|
||||
if(data.size() < 8) {
|
||||
if (data.size() < 8) {
|
||||
throw DeadlyImportError("File is too small");
|
||||
}
|
||||
|
||||
// UTF 8 with BOM
|
||||
if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
|
||||
if ((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
|
||||
ASSIMP_LOG_DEBUG("Found UTF-8 BOM ...");
|
||||
|
||||
std::copy(data.begin()+3,data.end(),data.begin());
|
||||
data.resize(data.size()-3);
|
||||
std::copy(data.begin() + 3, data.end(), data.begin());
|
||||
data.resize(data.size() - 3);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// UTF 32 BE with BOM
|
||||
if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
|
||||
if (*((uint32_t *)&data.front()) == 0xFFFE0000) {
|
||||
|
||||
// swap the endianness ..
|
||||
for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) {
|
||||
for (uint32_t *p = (uint32_t *)&data.front(), *end = (uint32_t *)&data.back(); p <= end; ++p) {
|
||||
AI_SWAP4P(p);
|
||||
}
|
||||
}
|
||||
|
||||
// UTF 32 LE with BOM
|
||||
if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
|
||||
if (*((uint32_t *)&data.front()) == 0x0000FFFE) {
|
||||
ASSIMP_LOG_DEBUG("Found UTF-32 BOM ...");
|
||||
|
||||
std::vector<char> output;
|
||||
int *ptr = (int*)&data[ 0 ];
|
||||
int *end = ptr + ( data.size() / sizeof(int) ) +1;
|
||||
utf8::utf32to8( ptr, end, back_inserter(output));
|
||||
int *ptr = (int *)&data[0];
|
||||
int *end = ptr + (data.size() / sizeof(int)) + 1;
|
||||
utf8::utf32to8(ptr, end, back_inserter(output));
|
||||
return;
|
||||
}
|
||||
|
||||
// UTF 16 BE with BOM
|
||||
if(*((uint16_t*)&data.front()) == 0xFFFE) {
|
||||
if (*((uint16_t *)&data.front()) == 0xFFFE) {
|
||||
|
||||
// swap the endianness ..
|
||||
for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) {
|
||||
for (uint16_t *p = (uint16_t *)&data.front(), *end = (uint16_t *)&data.back(); p <= end; ++p) {
|
||||
ByteSwap::Swap2(p);
|
||||
}
|
||||
}
|
||||
|
||||
// UTF 16 LE with BOM
|
||||
if(*((uint16_t*)&data.front()) == 0xFEFF) {
|
||||
if (*((uint16_t *)&data.front()) == 0xFEFF) {
|
||||
ASSIMP_LOG_DEBUG("Found UTF-16 BOM ...");
|
||||
|
||||
std::vector<unsigned char> output;
|
||||
@@ -419,23 +406,22 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Convert to UTF8 data to ISO-8859-1
|
||||
void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
|
||||
{
|
||||
void BaseImporter::ConvertUTF8toISO8859_1(std::string &data) {
|
||||
size_t size = data.size();
|
||||
size_t i = 0, j = 0;
|
||||
|
||||
while(i < size) {
|
||||
if ((unsigned char) data[i] < (size_t) 0x80) {
|
||||
while (i < size) {
|
||||
if ((unsigned char)data[i] < (size_t)0x80) {
|
||||
data[j] = data[i];
|
||||
} else if(i < size - 1) {
|
||||
if((unsigned char) data[i] == 0xC2) {
|
||||
} else if (i < size - 1) {
|
||||
if ((unsigned char)data[i] == 0xC2) {
|
||||
data[j] = data[++i];
|
||||
} else if((unsigned char) data[i] == 0xC3) {
|
||||
data[j] = ((unsigned char) data[++i] + 0x40);
|
||||
} else if ((unsigned char)data[i] == 0xC3) {
|
||||
data[j] = ((unsigned char)data[++i] + 0x40);
|
||||
} else {
|
||||
std::stringstream stream;
|
||||
stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
|
||||
ASSIMP_LOG_ERROR( stream.str() );
|
||||
ASSIMP_LOG_ERROR(stream.str());
|
||||
|
||||
data[j++] = data[i++];
|
||||
data[j] = data[i];
|
||||
@@ -446,30 +432,30 @@ void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
|
||||
data[j] = data[i];
|
||||
}
|
||||
|
||||
i++; j++;
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
data.resize(j);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BaseImporter::TextFileToBuffer(IOStream* stream,
|
||||
std::vector<char>& data,
|
||||
TextFileMode mode)
|
||||
{
|
||||
void BaseImporter::TextFileToBuffer(IOStream *stream,
|
||||
std::vector<char> &data,
|
||||
TextFileMode mode) {
|
||||
ai_assert(nullptr != stream);
|
||||
|
||||
const size_t fileSize = stream->FileSize();
|
||||
if (mode == FORBID_EMPTY) {
|
||||
if(!fileSize) {
|
||||
if (!fileSize) {
|
||||
throw DeadlyImportError("File is empty");
|
||||
}
|
||||
}
|
||||
|
||||
data.reserve(fileSize+1);
|
||||
data.reserve(fileSize + 1);
|
||||
data.resize(fileSize);
|
||||
if(fileSize > 0) {
|
||||
if(fileSize != stream->Read( &data[0], 1, fileSize)) {
|
||||
if (fileSize > 0) {
|
||||
if (fileSize != stream->Read(&data[0], 1, fileSize)) {
|
||||
throw DeadlyImportError("File read error");
|
||||
}
|
||||
|
||||
@@ -482,58 +468,55 @@ void BaseImporter::TextFileToBuffer(IOStream* stream,
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace Assimp {
|
||||
// Represents an import request
|
||||
struct LoadRequest {
|
||||
LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id)
|
||||
: file(_file)
|
||||
, flags(_flags)
|
||||
, refCnt(1)
|
||||
, scene(NULL)
|
||||
, loaded(false)
|
||||
, id(_id) {
|
||||
if ( _map ) {
|
||||
map = *_map;
|
||||
}
|
||||
// Represents an import request
|
||||
struct LoadRequest {
|
||||
LoadRequest(const std::string &_file, unsigned int _flags, const BatchLoader::PropertyMap *_map, unsigned int _id) :
|
||||
file(_file),
|
||||
flags(_flags),
|
||||
refCnt(1),
|
||||
scene(nullptr),
|
||||
loaded(false),
|
||||
id(_id) {
|
||||
if (_map) {
|
||||
map = *_map;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator== ( const std::string& f ) const {
|
||||
return file == f;
|
||||
}
|
||||
bool operator==(const std::string &f) const {
|
||||
return file == f;
|
||||
}
|
||||
|
||||
const std::string file;
|
||||
unsigned int flags;
|
||||
unsigned int refCnt;
|
||||
aiScene *scene;
|
||||
bool loaded;
|
||||
BatchLoader::PropertyMap map;
|
||||
unsigned int id;
|
||||
};
|
||||
}
|
||||
const std::string file;
|
||||
unsigned int flags;
|
||||
unsigned int refCnt;
|
||||
aiScene *scene;
|
||||
bool loaded;
|
||||
BatchLoader::PropertyMap map;
|
||||
unsigned int id;
|
||||
};
|
||||
} // namespace Assimp
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// BatchLoader::pimpl data structure
|
||||
struct Assimp::BatchData {
|
||||
BatchData( IOSystem* pIO, bool validate )
|
||||
: pIOSystem( pIO )
|
||||
, pImporter( nullptr )
|
||||
, next_id(0xffff)
|
||||
, validate( validate ) {
|
||||
ai_assert( nullptr != pIO );
|
||||
|
||||
BatchData(IOSystem *pIO, bool validate) :
|
||||
pIOSystem(pIO), pImporter(nullptr), next_id(0xffff), validate(validate) {
|
||||
ai_assert(nullptr != pIO);
|
||||
|
||||
pImporter = new Importer();
|
||||
pImporter->SetIOHandler( pIO );
|
||||
pImporter->SetIOHandler(pIO);
|
||||
}
|
||||
|
||||
~BatchData() {
|
||||
pImporter->SetIOHandler( nullptr ); /* get pointer back into our possession */
|
||||
pImporter->SetIOHandler(nullptr); /* get pointer back into our possession */
|
||||
delete pImporter;
|
||||
}
|
||||
|
||||
// IO system to be used for all imports
|
||||
IOSystem* pIOSystem;
|
||||
IOSystem *pIOSystem;
|
||||
|
||||
// Importer used to load all meshes
|
||||
Importer* pImporter;
|
||||
Importer *pImporter;
|
||||
|
||||
// List of all imports
|
||||
std::list<LoadRequest> requests;
|
||||
@@ -551,24 +534,23 @@ struct Assimp::BatchData {
|
||||
typedef std::list<LoadRequest>::iterator LoadReqIt;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BatchLoader::BatchLoader(IOSystem* pIO, bool validate ) {
|
||||
BatchLoader::BatchLoader(IOSystem *pIO, bool validate) {
|
||||
ai_assert(nullptr != pIO);
|
||||
|
||||
m_data = new BatchData( pIO, validate );
|
||||
m_data = new BatchData(pIO, validate);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BatchLoader::~BatchLoader()
|
||||
{
|
||||
BatchLoader::~BatchLoader() {
|
||||
// delete all scenes what have not been polled by the user
|
||||
for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
|
||||
for (LoadReqIt it = m_data->requests.begin(); it != m_data->requests.end(); ++it) {
|
||||
delete (*it).scene;
|
||||
}
|
||||
delete m_data;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BatchLoader::setValidation( bool enabled ) {
|
||||
void BatchLoader::setValidation(bool enabled) {
|
||||
m_data->validate = enabled;
|
||||
}
|
||||
|
||||
@@ -578,21 +560,19 @@ bool BatchLoader::getValidation() const {
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int BatchLoader::AddLoadRequest(const std::string& file,
|
||||
unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/)
|
||||
{
|
||||
unsigned int BatchLoader::AddLoadRequest(const std::string &file,
|
||||
unsigned int steps /*= 0*/, const PropertyMap *map /*= nullptr*/) {
|
||||
ai_assert(!file.empty());
|
||||
|
||||
// check whether we have this loading request already
|
||||
for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
|
||||
for (LoadReqIt it = m_data->requests.begin(); it != m_data->requests.end(); ++it) {
|
||||
// Call IOSystem's path comparison function here
|
||||
if ( m_data->pIOSystem->ComparePaths((*it).file,file)) {
|
||||
if (m_data->pIOSystem->ComparePaths((*it).file, file)) {
|
||||
if (map) {
|
||||
if ( !( ( *it ).map == *map ) ) {
|
||||
if (!((*it).map == *map)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ( !( *it ).map.empty() ) {
|
||||
} else if (!(*it).map.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -607,12 +587,11 @@ unsigned int BatchLoader::AddLoadRequest(const std::string& file,
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiScene* BatchLoader::GetImport( unsigned int which )
|
||||
{
|
||||
for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
|
||||
if ((*it).id == which && (*it).loaded) {
|
||||
aiScene* sc = (*it).scene;
|
||||
if (!(--(*it).refCnt)) {
|
||||
aiScene *BatchLoader::GetImport(unsigned int which) {
|
||||
for (LoadReqIt it = m_data->requests.begin(); it != m_data->requests.end(); ++it) {
|
||||
if ((*it).id == which && (*it).loaded) {
|
||||
aiScene *sc = (*it).scene;
|
||||
if (!(--(*it).refCnt)) {
|
||||
m_data->requests.erase(it);
|
||||
}
|
||||
return sc;
|
||||
@@ -621,32 +600,28 @@ aiScene* BatchLoader::GetImport( unsigned int which )
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BatchLoader::LoadAll()
|
||||
{
|
||||
void BatchLoader::LoadAll() {
|
||||
// no threaded implementation for the moment
|
||||
for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
|
||||
for (LoadReqIt it = m_data->requests.begin(); it != m_data->requests.end(); ++it) {
|
||||
// force validation in debug builds
|
||||
unsigned int pp = (*it).flags;
|
||||
if ( m_data->validate ) {
|
||||
if (m_data->validate) {
|
||||
pp |= aiProcess_ValidateDataStructure;
|
||||
}
|
||||
|
||||
// setup config properties if necessary
|
||||
ImporterPimpl* pimpl = m_data->pImporter->Pimpl();
|
||||
pimpl->mFloatProperties = (*it).map.floats;
|
||||
pimpl->mIntProperties = (*it).map.ints;
|
||||
ImporterPimpl *pimpl = m_data->pImporter->Pimpl();
|
||||
pimpl->mFloatProperties = (*it).map.floats;
|
||||
pimpl->mIntProperties = (*it).map.ints;
|
||||
pimpl->mStringProperties = (*it).map.strings;
|
||||
pimpl->mMatrixProperties = (*it).map.matrices;
|
||||
|
||||
if (!DefaultLogger::isNullLogger())
|
||||
{
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%");
|
||||
ASSIMP_LOG_INFO_F("File: ", (*it).file);
|
||||
}
|
||||
m_data->pImporter->ReadFile((*it).file,pp);
|
||||
m_data->pImporter->ReadFile((*it).file, pp);
|
||||
(*it).scene = m_data->pImporter->GetOrphanedScene();
|
||||
(*it).loaded = true;
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ public:
|
||||
bool GetProperty(const char *name, T *&out) const {
|
||||
THeapData<T> *t = (THeapData<T> *)GetPropertyInternal(name);
|
||||
if (!t) {
|
||||
out = NULL;
|
||||
out = nullptr;
|
||||
return false;
|
||||
}
|
||||
out = t->data;
|
||||
@@ -202,7 +202,7 @@ public:
|
||||
// -------------------------------------------------------------------
|
||||
/** Executes the post processing step on the given imported data.
|
||||
* The function deletes the scene if the postprocess step fails (
|
||||
* the object pointer will be set to NULL).
|
||||
* the object pointer will be set to nullptr).
|
||||
* @param pImp Importer instance (pImp->mScene must be valid)
|
||||
*/
|
||||
void ExecuteOnScene(Importer *pImp);
|
||||
@@ -225,7 +225,7 @@ public:
|
||||
// -------------------------------------------------------------------
|
||||
/** Assign a new SharedPostProcessInfo to the step. This object
|
||||
* allows multiple postprocess steps to share data.
|
||||
* @param sh May be NULL
|
||||
* @param sh May be nullptr
|
||||
*/
|
||||
inline void SetSharedData(SharedPostProcessInfo *sh) {
|
||||
shared = sh;
|
||||
|
||||
@@ -47,109 +47,109 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* Used for file formats which embed their textures into the model file.
|
||||
*/
|
||||
|
||||
|
||||
#include <assimp/Bitmap.h>
|
||||
#include <assimp/ByteSwapper.h>
|
||||
#include <assimp/texture.h>
|
||||
#include <assimp/IOStream.hpp>
|
||||
#include <assimp/ByteSwapper.h>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
void Bitmap::Save(aiTexture* texture, IOStream* file) {
|
||||
if(file != NULL) {
|
||||
Header header;
|
||||
DIB dib;
|
||||
void Bitmap::Save(aiTexture *texture, IOStream *file) {
|
||||
if (file != nullptr) {
|
||||
Header header;
|
||||
DIB dib;
|
||||
|
||||
dib.size = DIB::dib_size;
|
||||
dib.width = texture->mWidth;
|
||||
dib.height = texture->mHeight;
|
||||
dib.planes = 1;
|
||||
dib.bits_per_pixel = 8 * mBytesPerPixel;
|
||||
dib.compression = 0;
|
||||
dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height;
|
||||
dib.x_resolution = 0;
|
||||
dib.y_resolution = 0;
|
||||
dib.nb_colors = 0;
|
||||
dib.nb_important_colors = 0;
|
||||
dib.size = DIB::dib_size;
|
||||
dib.width = texture->mWidth;
|
||||
dib.height = texture->mHeight;
|
||||
dib.planes = 1;
|
||||
dib.bits_per_pixel = 8 * mBytesPerPixel;
|
||||
dib.compression = 0;
|
||||
dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height;
|
||||
dib.x_resolution = 0;
|
||||
dib.y_resolution = 0;
|
||||
dib.nb_colors = 0;
|
||||
dib.nb_important_colors = 0;
|
||||
|
||||
header.type = 0x4D42; // 'BM'
|
||||
header.offset = Header::header_size + DIB::dib_size;
|
||||
header.size = header.offset + dib.image_size;
|
||||
header.reserved1 = 0;
|
||||
header.reserved2 = 0;
|
||||
header.type = 0x4D42; // 'BM'
|
||||
header.offset = Header::header_size + DIB::dib_size;
|
||||
header.size = header.offset + dib.image_size;
|
||||
header.reserved1 = 0;
|
||||
header.reserved2 = 0;
|
||||
|
||||
WriteHeader(header, file);
|
||||
WriteDIB(dib, file);
|
||||
WriteData(texture, file);
|
||||
}
|
||||
WriteHeader(header, file);
|
||||
WriteDIB(dib, file);
|
||||
WriteData(texture, file);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
std::size_t Copy(uint8_t* data, const T &field) {
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
T field_swapped=AI_BE(field);
|
||||
std::memcpy(data, &field_swapped, sizeof(field)); return sizeof(field);
|
||||
#else
|
||||
std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Bitmap::WriteHeader(Header& header, IOStream* file) {
|
||||
uint8_t data[Header::header_size];
|
||||
|
||||
std::size_t offset = 0;
|
||||
|
||||
offset += Copy(&data[offset], header.type);
|
||||
offset += Copy(&data[offset], header.size);
|
||||
offset += Copy(&data[offset], header.reserved1);
|
||||
offset += Copy(&data[offset], header.reserved2);
|
||||
Copy(&data[offset], header.offset);
|
||||
|
||||
file->Write(data, Header::header_size, 1);
|
||||
}
|
||||
|
||||
void Bitmap::WriteDIB(DIB& dib, IOStream* file) {
|
||||
uint8_t data[DIB::dib_size];
|
||||
|
||||
std::size_t offset = 0;
|
||||
|
||||
offset += Copy(&data[offset], dib.size);
|
||||
offset += Copy(&data[offset], dib.width);
|
||||
offset += Copy(&data[offset], dib.height);
|
||||
offset += Copy(&data[offset], dib.planes);
|
||||
offset += Copy(&data[offset], dib.bits_per_pixel);
|
||||
offset += Copy(&data[offset], dib.compression);
|
||||
offset += Copy(&data[offset], dib.image_size);
|
||||
offset += Copy(&data[offset], dib.x_resolution);
|
||||
offset += Copy(&data[offset], dib.y_resolution);
|
||||
offset += Copy(&data[offset], dib.nb_colors);
|
||||
Copy(&data[offset], dib.nb_important_colors);
|
||||
|
||||
file->Write(data, DIB::dib_size, 1);
|
||||
}
|
||||
|
||||
void Bitmap::WriteData(aiTexture* texture, IOStream* file) {
|
||||
static const std::size_t padding_offset = 4;
|
||||
static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0};
|
||||
|
||||
unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
|
||||
uint8_t pixel[mBytesPerPixel];
|
||||
|
||||
for(std::size_t i = 0; i < texture->mHeight; ++i) {
|
||||
for(std::size_t j = 0; j < texture->mWidth; ++j) {
|
||||
const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
|
||||
|
||||
pixel[0] = texel.r;
|
||||
pixel[1] = texel.g;
|
||||
pixel[2] = texel.b;
|
||||
pixel[3] = texel.a;
|
||||
|
||||
file->Write(pixel, mBytesPerPixel, 1);
|
||||
}
|
||||
|
||||
file->Write(padding_data, padding, 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::size_t Copy(uint8_t *data, const T &field) {
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
T field_swapped = AI_BE(field);
|
||||
std::memcpy(data, &field_swapped, sizeof(field));
|
||||
return sizeof(field);
|
||||
#else
|
||||
std::memcpy(data, &AI_BE(field), sizeof(field));
|
||||
return sizeof(field);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Bitmap::WriteHeader(Header &header, IOStream *file) {
|
||||
uint8_t data[Header::header_size];
|
||||
|
||||
std::size_t offset = 0;
|
||||
|
||||
offset += Copy(&data[offset], header.type);
|
||||
offset += Copy(&data[offset], header.size);
|
||||
offset += Copy(&data[offset], header.reserved1);
|
||||
offset += Copy(&data[offset], header.reserved2);
|
||||
Copy(&data[offset], header.offset);
|
||||
|
||||
file->Write(data, Header::header_size, 1);
|
||||
}
|
||||
|
||||
void Bitmap::WriteDIB(DIB &dib, IOStream *file) {
|
||||
uint8_t data[DIB::dib_size];
|
||||
|
||||
std::size_t offset = 0;
|
||||
|
||||
offset += Copy(&data[offset], dib.size);
|
||||
offset += Copy(&data[offset], dib.width);
|
||||
offset += Copy(&data[offset], dib.height);
|
||||
offset += Copy(&data[offset], dib.planes);
|
||||
offset += Copy(&data[offset], dib.bits_per_pixel);
|
||||
offset += Copy(&data[offset], dib.compression);
|
||||
offset += Copy(&data[offset], dib.image_size);
|
||||
offset += Copy(&data[offset], dib.x_resolution);
|
||||
offset += Copy(&data[offset], dib.y_resolution);
|
||||
offset += Copy(&data[offset], dib.nb_colors);
|
||||
Copy(&data[offset], dib.nb_important_colors);
|
||||
|
||||
file->Write(data, DIB::dib_size, 1);
|
||||
}
|
||||
|
||||
void Bitmap::WriteData(aiTexture *texture, IOStream *file) {
|
||||
static const std::size_t padding_offset = 4;
|
||||
static const uint8_t padding_data[padding_offset] = { 0x0, 0x0, 0x0, 0x0 };
|
||||
|
||||
unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
|
||||
uint8_t pixel[mBytesPerPixel];
|
||||
|
||||
for (std::size_t i = 0; i < texture->mHeight; ++i) {
|
||||
for (std::size_t j = 0; j < texture->mWidth; ++j) {
|
||||
const aiTexel &texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
|
||||
|
||||
pixel[0] = texel.r;
|
||||
pixel[1] = texel.g;
|
||||
pixel[2] = texel.b;
|
||||
pixel[3] = texel.a;
|
||||
|
||||
file->Write(pixel, mBytesPerPixel, 1);
|
||||
}
|
||||
|
||||
file->Write(padding_data, padding, 1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
@@ -70,7 +70,7 @@ aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
|
||||
animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D));
|
||||
} else {
|
||||
animesh->mColors[i] = NULL;
|
||||
animesh->mColors[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
|
||||
animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
|
||||
std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D));
|
||||
} else {
|
||||
animesh->mTextureCoords[i] = NULL;
|
||||
animesh->mTextureCoords[i] = nullptr;
|
||||
}
|
||||
}
|
||||
return animesh;
|
||||
|
||||
@@ -44,46 +44,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* @brief Default File I/O implementation for #Importer
|
||||
*/
|
||||
|
||||
|
||||
#include <assimp/ai_assert.h>
|
||||
#include <assimp/DefaultIOStream.h>
|
||||
#include <sys/types.h>
|
||||
#include <assimp/ai_assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
namespace
|
||||
{
|
||||
template<size_t sizeOfPointer>
|
||||
size_t select_ftell(FILE* file)
|
||||
{
|
||||
return ::ftell(file);
|
||||
}
|
||||
|
||||
template<size_t sizeOfPointer>
|
||||
int select_fseek(FILE* file, int64_t offset, int origin)
|
||||
{
|
||||
return ::fseek(file, static_cast<long>(offset), origin);
|
||||
}
|
||||
|
||||
#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
|
||||
template<>
|
||||
size_t select_ftell<8>(FILE* file)
|
||||
{
|
||||
return (size_t)::_ftelli64(file);
|
||||
}
|
||||
|
||||
template<>
|
||||
int select_fseek<8>(FILE* file, int64_t offset, int origin)
|
||||
{
|
||||
return ::_fseeki64(file, offset, origin);
|
||||
}
|
||||
#endif
|
||||
namespace {
|
||||
template <size_t sizeOfPointer>
|
||||
size_t select_ftell(FILE *file) {
|
||||
return ::ftell(file);
|
||||
}
|
||||
|
||||
template <size_t sizeOfPointer>
|
||||
int select_fseek(FILE *file, int64_t offset, int origin) {
|
||||
return ::fseek(file, static_cast<long>(offset), origin);
|
||||
}
|
||||
|
||||
#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
|
||||
template <>
|
||||
size_t select_ftell<8>(FILE *file) {
|
||||
return (size_t)::_ftelli64(file);
|
||||
}
|
||||
|
||||
template <>
|
||||
int select_fseek<8>(FILE *file, int64_t offset, int origin) {
|
||||
return ::_fseeki64(file, offset, origin);
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
DefaultIOStream::~DefaultIOStream()
|
||||
{
|
||||
DefaultIOStream::~DefaultIOStream() {
|
||||
if (mFile) {
|
||||
::fclose(mFile);
|
||||
mFile = nullptr;
|
||||
@@ -91,57 +84,59 @@ DefaultIOStream::~DefaultIOStream()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
size_t DefaultIOStream::Read(void* pvBuffer,
|
||||
size_t pSize,
|
||||
size_t pCount)
|
||||
{
|
||||
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
|
||||
size_t DefaultIOStream::Read(void *pvBuffer,
|
||||
size_t pSize,
|
||||
size_t pCount) {
|
||||
ai_assert(nullptr != pvBuffer);
|
||||
ai_assert(0 != pSize);
|
||||
ai_assert(0 != pCount);
|
||||
|
||||
return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
size_t DefaultIOStream::Write(const void* pvBuffer,
|
||||
size_t pSize,
|
||||
size_t pCount)
|
||||
{
|
||||
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
|
||||
size_t DefaultIOStream::Write(const void *pvBuffer,
|
||||
size_t pSize,
|
||||
size_t pCount) {
|
||||
ai_assert(nullptr != pvBuffer);
|
||||
ai_assert(0 != pSize);
|
||||
ai_assert(0 != pCount);
|
||||
|
||||
return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
aiReturn DefaultIOStream::Seek(size_t pOffset,
|
||||
aiOrigin pOrigin)
|
||||
{
|
||||
aiOrigin pOrigin) {
|
||||
if (!mFile) {
|
||||
return AI_FAILURE;
|
||||
}
|
||||
|
||||
// Just to check whether our enum maps one to one with the CRT constants
|
||||
static_assert(aiOrigin_CUR == SEEK_CUR &&
|
||||
aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET, "aiOrigin_CUR == SEEK_CUR && \
|
||||
aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET,
|
||||
"aiOrigin_CUR == SEEK_CUR && \
|
||||
aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET");
|
||||
|
||||
// do the seek
|
||||
return (0 == select_fseek<sizeof(void*)>(mFile, (int64_t)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE);
|
||||
return (0 == select_fseek<sizeof(void *)>(mFile, (int64_t)pOffset, (int)pOrigin) ? AI_SUCCESS : AI_FAILURE);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
size_t DefaultIOStream::Tell() const
|
||||
{
|
||||
size_t DefaultIOStream::Tell() const {
|
||||
if (!mFile) {
|
||||
return 0;
|
||||
}
|
||||
return select_ftell<sizeof(void*)>(mFile);
|
||||
return select_ftell<sizeof(void *)>(mFile);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
size_t DefaultIOStream::FileSize() const
|
||||
{
|
||||
if (! mFile || mFilename.empty()) {
|
||||
size_t DefaultIOStream::FileSize() const {
|
||||
if (!mFile || mFilename.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SIZE_MAX == mCachedSize ) {
|
||||
if (SIZE_MAX == mCachedSize) {
|
||||
|
||||
// Although fseek/ftell would allow us to reuse the existing file handle here,
|
||||
// it is generally unsafe because:
|
||||
@@ -154,27 +149,26 @@ size_t DefaultIOStream::FileSize() const
|
||||
#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
|
||||
struct __stat64 fileStat;
|
||||
//using fileno + fstat avoids having to handle the filename
|
||||
int err = _fstat64( _fileno(mFile), &fileStat );
|
||||
int err = _fstat64(_fileno(mFile), &fileStat);
|
||||
if (0 != err)
|
||||
return 0;
|
||||
mCachedSize = (size_t) (fileStat.st_size);
|
||||
mCachedSize = (size_t)(fileStat.st_size);
|
||||
#elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__
|
||||
struct stat fileStat;
|
||||
int err = stat(mFilename.c_str(), &fileStat );
|
||||
int err = stat(mFilename.c_str(), &fileStat);
|
||||
if (0 != err)
|
||||
return 0;
|
||||
const unsigned long long cachedSize = fileStat.st_size;
|
||||
mCachedSize = static_cast< size_t >( cachedSize );
|
||||
mCachedSize = static_cast<size_t>(cachedSize);
|
||||
#else
|
||||
# error "Unknown platform"
|
||||
#error "Unknown platform"
|
||||
#endif
|
||||
}
|
||||
return mCachedSize;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
void DefaultIOStream::Flush()
|
||||
{
|
||||
void DefaultIOStream::Flush() {
|
||||
if (mFile) {
|
||||
::fflush(mFile);
|
||||
}
|
||||
|
||||
@@ -46,25 +46,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Default log streams
|
||||
#include "Win32DebugLogStream.h"
|
||||
#include "StdOStreamLogStream.h"
|
||||
#include "FileLogStream.h"
|
||||
#include "StdOStreamLogStream.h"
|
||||
#include "Win32DebugLogStream.h"
|
||||
#include <assimp/StringUtils.h>
|
||||
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
#include <assimp/NullLogger.hpp>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/ai_assert.h>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/NullLogger.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
# include <thread>
|
||||
# include <mutex>
|
||||
std::mutex loggerMutex;
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
std::mutex loggerMutex;
|
||||
#endif
|
||||
|
||||
namespace Assimp {
|
||||
namespace Assimp {
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
NullLogger DefaultLogger::s_pNullLogger;
|
||||
@@ -75,13 +75,13 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Represents a log-stream + its error severity
|
||||
struct LogStreamInfo {
|
||||
unsigned int m_uiErrorSeverity;
|
||||
LogStream *m_pStream;
|
||||
unsigned int m_uiErrorSeverity;
|
||||
LogStream *m_pStream;
|
||||
|
||||
// Constructor
|
||||
LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
|
||||
m_uiErrorSeverity( uiErrorSev ),
|
||||
m_pStream( pStream ) {
|
||||
LogStreamInfo(unsigned int uiErrorSev, LogStream *pStream) :
|
||||
m_uiErrorSeverity(uiErrorSev),
|
||||
m_pStream(pStream) {
|
||||
// empty
|
||||
}
|
||||
|
||||
@@ -93,12 +93,10 @@ struct LogStreamInfo {
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Construct a default log stream
|
||||
LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
|
||||
const char* name /*= "AssimpLog.txt"*/,
|
||||
IOSystem* io /*= NULL*/)
|
||||
{
|
||||
switch (streams)
|
||||
{
|
||||
LogStream *LogStream::createDefaultStream(aiDefaultLogStream streams,
|
||||
const char *name /*= "AssimpLog.txt"*/,
|
||||
IOSystem *io /*= nullptr*/) {
|
||||
switch (streams) {
|
||||
// This is a platform-specific feature
|
||||
case aiDefaultLogStream_DEBUGGER:
|
||||
#ifdef WIN32
|
||||
@@ -113,11 +111,10 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
|
||||
case aiDefaultLogStream_STDOUT:
|
||||
return new StdOStreamLogStream(std::cout);
|
||||
case aiDefaultLogStream_FILE:
|
||||
return (name && *name ? new FileLogStream(name,io) : nullptr );
|
||||
return (name && *name ? new FileLogStream(name, io) : nullptr);
|
||||
default:
|
||||
// We don't know this default log stream, so raise an assertion
|
||||
ai_assert(false);
|
||||
|
||||
};
|
||||
|
||||
// For compilers without dead code path detection
|
||||
@@ -126,97 +123,109 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Creates the only singleton instance
|
||||
Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
|
||||
LogSeverity severity /*= NORMAL*/,
|
||||
unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
|
||||
IOSystem* io /*= NULL*/) {
|
||||
Logger *DefaultLogger::create(const char *name /*= "AssimpLog.txt"*/,
|
||||
LogSeverity severity /*= NORMAL*/,
|
||||
unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
|
||||
IOSystem *io /*= nullptr*/) {
|
||||
// enter the mutex here to avoid concurrency problems
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
std::lock_guard<std::mutex> lock(loggerMutex);
|
||||
#endif
|
||||
|
||||
if ( m_pLogger && !isNullLogger() ) {
|
||||
if (m_pLogger && !isNullLogger()) {
|
||||
delete m_pLogger;
|
||||
}
|
||||
|
||||
m_pLogger = new DefaultLogger( severity );
|
||||
m_pLogger = new DefaultLogger(severity);
|
||||
|
||||
// Attach default log streams
|
||||
// Stream the log to the MSVC debugger?
|
||||
if ( defStreams & aiDefaultLogStream_DEBUGGER ) {
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) );
|
||||
if (defStreams & aiDefaultLogStream_DEBUGGER) {
|
||||
m_pLogger->attachStream(LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER));
|
||||
}
|
||||
|
||||
// Stream the log to COUT?
|
||||
if ( defStreams & aiDefaultLogStream_STDOUT ) {
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) );
|
||||
if (defStreams & aiDefaultLogStream_STDOUT) {
|
||||
m_pLogger->attachStream(LogStream::createDefaultStream(aiDefaultLogStream_STDOUT));
|
||||
}
|
||||
|
||||
// Stream the log to CERR?
|
||||
if ( defStreams & aiDefaultLogStream_STDERR ) {
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) );
|
||||
if (defStreams & aiDefaultLogStream_STDERR) {
|
||||
m_pLogger->attachStream(LogStream::createDefaultStream(aiDefaultLogStream_STDERR));
|
||||
}
|
||||
|
||||
// Stream the log to a file
|
||||
if ( defStreams & aiDefaultLogStream_FILE && name && *name ) {
|
||||
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) );
|
||||
if (defStreams & aiDefaultLogStream_FILE && name && *name) {
|
||||
m_pLogger->attachStream(LogStream::createDefaultStream(aiDefaultLogStream_FILE, name, io));
|
||||
}
|
||||
|
||||
return m_pLogger;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
void Logger::debug(const char* message) {
|
||||
void Logger::debug(const char *message) {
|
||||
|
||||
// SECURITY FIX: otherwise it's easy to produce overruns since
|
||||
// sometimes importers will include data from the input file
|
||||
// (i.e. node names) in their messages.
|
||||
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
|
||||
if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
|
||||
return;
|
||||
}
|
||||
return OnDebug(message);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
void Logger::info(const char* message) {
|
||||
void Logger::verboseDebug(const char *message) {
|
||||
|
||||
// SECURITY FIX: otherwise it's easy to produce overruns since
|
||||
// sometimes importers will include data from the input file
|
||||
// (i.e. node names) in their messages.
|
||||
if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
|
||||
return;
|
||||
}
|
||||
return OnVerboseDebug(message);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
void Logger::info(const char *message) {
|
||||
|
||||
// SECURITY FIX: see above
|
||||
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
|
||||
if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
|
||||
return;
|
||||
}
|
||||
return OnInfo(message);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
void Logger::warn(const char* message) {
|
||||
void Logger::warn(const char *message) {
|
||||
|
||||
// SECURITY FIX: see above
|
||||
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
|
||||
if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
|
||||
return;
|
||||
}
|
||||
return OnWarn(message);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
void Logger::error(const char* message) {
|
||||
void Logger::error(const char *message) {
|
||||
// SECURITY FIX: see above
|
||||
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
|
||||
if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) {
|
||||
return;
|
||||
}
|
||||
return OnError(message);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
void DefaultLogger::set( Logger *logger ) {
|
||||
void DefaultLogger::set(Logger *logger) {
|
||||
// enter the mutex here to avoid concurrency problems
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
std::lock_guard<std::mutex> lock(loggerMutex);
|
||||
#endif
|
||||
|
||||
if ( nullptr == logger ) {
|
||||
if (nullptr == logger) {
|
||||
logger = &s_pNullLogger;
|
||||
}
|
||||
if ( nullptr != m_pLogger && !isNullLogger() ) {
|
||||
if (nullptr != m_pLogger && !isNullLogger()) {
|
||||
delete m_pLogger;
|
||||
}
|
||||
|
||||
@@ -241,103 +250,115 @@ void DefaultLogger::kill() {
|
||||
std::lock_guard<std::mutex> lock(loggerMutex);
|
||||
#endif
|
||||
|
||||
if ( m_pLogger == &s_pNullLogger ) {
|
||||
return;
|
||||
}
|
||||
if (m_pLogger == &s_pNullLogger) {
|
||||
return;
|
||||
}
|
||||
delete m_pLogger;
|
||||
m_pLogger = &s_pNullLogger;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Debug message
|
||||
void DefaultLogger::OnDebug( const char* message ) {
|
||||
if ( m_Severity == Logger::NORMAL ) {
|
||||
void DefaultLogger::OnDebug(const char *message) {
|
||||
if (m_Severity < Logger::DEBUG) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message);
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message);
|
||||
|
||||
WriteToStreams( msg, Logger::Debugging );
|
||||
WriteToStreams(msg, Logger::Debugging);
|
||||
}
|
||||
|
||||
// Verbose debug message
|
||||
void DefaultLogger::OnVerboseDebug(const char *message) {
|
||||
if (m_Severity < Logger::VERBOSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message);
|
||||
|
||||
WriteToStreams(msg, Logger::Debugging);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Logs an info
|
||||
void DefaultLogger::OnInfo( const char* message ){
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message );
|
||||
void DefaultLogger::OnInfo(const char *message) {
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message);
|
||||
|
||||
WriteToStreams( msg , Logger::Info );
|
||||
WriteToStreams(msg, Logger::Info);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Logs a warning
|
||||
void DefaultLogger::OnWarn( const char* message ) {
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message );
|
||||
void DefaultLogger::OnWarn(const char *message) {
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message);
|
||||
|
||||
WriteToStreams( msg, Logger::Warn );
|
||||
WriteToStreams(msg, Logger::Warn);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Logs an error
|
||||
void DefaultLogger::OnError( const char* message ) {
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[ Size ];
|
||||
ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
|
||||
void DefaultLogger::OnError(const char *message) {
|
||||
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
|
||||
char msg[Size];
|
||||
ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message);
|
||||
|
||||
WriteToStreams( msg, Logger::Err );
|
||||
WriteToStreams(msg, Logger::Err);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Will attach a new stream
|
||||
bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) {
|
||||
if ( nullptr == pStream ) {
|
||||
bool DefaultLogger::attachStream(LogStream *pStream, unsigned int severity) {
|
||||
if (nullptr == pStream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 == severity) {
|
||||
if (0 == severity) {
|
||||
severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
|
||||
}
|
||||
|
||||
for ( StreamIt it = m_StreamArray.begin();
|
||||
it != m_StreamArray.end();
|
||||
++it )
|
||||
{
|
||||
if ( (*it)->m_pStream == pStream ) {
|
||||
for (StreamIt it = m_StreamArray.begin();
|
||||
it != m_StreamArray.end();
|
||||
++it) {
|
||||
if ((*it)->m_pStream == pStream) {
|
||||
(*it)->m_uiErrorSeverity |= severity;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream );
|
||||
m_StreamArray.push_back( pInfo );
|
||||
LogStreamInfo *pInfo = new LogStreamInfo(severity, pStream);
|
||||
m_StreamArray.push_back(pInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Detach a stream
|
||||
bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) {
|
||||
if ( nullptr == pStream ) {
|
||||
bool DefaultLogger::detachStream(LogStream *pStream, unsigned int severity) {
|
||||
if (nullptr == pStream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 == severity) {
|
||||
if (0 == severity) {
|
||||
severity = SeverityAll;
|
||||
}
|
||||
|
||||
bool res( false );
|
||||
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
|
||||
if ( (*it)->m_pStream == pStream ) {
|
||||
bool res(false);
|
||||
for (StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it) {
|
||||
if ((*it)->m_pStream == pStream) {
|
||||
(*it)->m_uiErrorSeverity &= ~severity;
|
||||
if ( (*it)->m_uiErrorSeverity == 0 ) {
|
||||
if ((*it)->m_uiErrorSeverity == 0) {
|
||||
// don't delete the underlying stream 'cause the caller gains ownership again
|
||||
(**it).m_pStream = nullptr;
|
||||
delete *it;
|
||||
m_StreamArray.erase( it );
|
||||
m_StreamArray.erase(it);
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
@@ -349,17 +370,15 @@ bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) {
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Constructor
|
||||
DefaultLogger::DefaultLogger(LogSeverity severity)
|
||||
: Logger ( severity )
|
||||
, noRepeatMsg (false)
|
||||
, lastLen( 0 ) {
|
||||
DefaultLogger::DefaultLogger(LogSeverity severity) :
|
||||
Logger(severity), noRepeatMsg(false), lastLen(0) {
|
||||
lastMsg[0] = '\0';
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Destructor
|
||||
DefaultLogger::~DefaultLogger() {
|
||||
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
|
||||
for (StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it) {
|
||||
// also frees the underlying stream, we are its owner.
|
||||
delete *it;
|
||||
}
|
||||
@@ -367,43 +386,37 @@ DefaultLogger::~DefaultLogger() {
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Writes message to stream
|
||||
void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) {
|
||||
void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev) {
|
||||
ai_assert(nullptr != message);
|
||||
|
||||
// Check whether this is a repeated message
|
||||
if (! ::strncmp( message,lastMsg, lastLen-1))
|
||||
{
|
||||
if (!noRepeatMsg)
|
||||
{
|
||||
if (!::strncmp(message, lastMsg, lastLen - 1)) {
|
||||
if (!noRepeatMsg) {
|
||||
noRepeatMsg = true;
|
||||
message = "Skipping one or more lines with the same contents\n";
|
||||
}
|
||||
else return;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else
|
||||
return;
|
||||
} else {
|
||||
// append a new-line character to the message to be printed
|
||||
lastLen = ::strlen(message);
|
||||
::memcpy(lastMsg,message,lastLen+1);
|
||||
::strcat(lastMsg+lastLen,"\n");
|
||||
::memcpy(lastMsg, message, lastLen + 1);
|
||||
::strcat(lastMsg + lastLen, "\n");
|
||||
|
||||
message = lastMsg;
|
||||
noRepeatMsg = false;
|
||||
++lastLen;
|
||||
}
|
||||
for ( ConstStreamIt it = m_StreamArray.begin();
|
||||
it != m_StreamArray.end();
|
||||
++it)
|
||||
{
|
||||
if ( ErrorSev & (*it)->m_uiErrorSeverity )
|
||||
(*it)->m_pStream->write( message);
|
||||
for (ConstStreamIt it = m_StreamArray.begin();
|
||||
it != m_StreamArray.end();
|
||||
++it) {
|
||||
if (ErrorSev & (*it)->m_uiErrorSeverity)
|
||||
(*it)->m_pStream->write(message);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Returns thread id, if not supported only a zero will be returned.
|
||||
unsigned int DefaultLogger::GetThreadID()
|
||||
{
|
||||
unsigned int DefaultLogger::GetThreadID() {
|
||||
// fixme: we can get this value via std::threads
|
||||
// std::this_thread::get_id().hash() returns a (big) size_t, not sure if this is useful in this case.
|
||||
#ifdef WIN32
|
||||
@@ -415,4 +428,4 @@ unsigned int DefaultLogger::GetThreadID()
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
} // !namespace Assimp
|
||||
} // namespace Assimp
|
||||
|
||||
@@ -83,32 +83,61 @@ namespace Assimp {
|
||||
void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
|
||||
// do not use const, because some exporter need to convert the scene temporary
|
||||
// Exporter worker function prototypes. Do not use const, because some exporter need to convert
|
||||
// the scene temporary
|
||||
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
|
||||
void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_X_EXPORTER
|
||||
void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
|
||||
void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
|
||||
void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneObjNoMtl(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
|
||||
void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER
|
||||
void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
|
||||
void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
|
||||
void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
|
||||
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
|
||||
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
|
||||
void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||
void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
|
||||
void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER
|
||||
void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
void ExportSceneM3DA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
|
||||
void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*);
|
||||
|
||||
#endif
|
||||
|
||||
static void setupExporterArray(std::vector<Exporter::ExportFormatEntry> &exporters) {
|
||||
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
|
||||
@@ -446,7 +475,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
|
||||
proc.Execute(scenecopy.get());
|
||||
}
|
||||
|
||||
ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry.
|
||||
ExportProperties emptyProperties; // Never pass nullptr ExportProperties so Exporters don't have to worry.
|
||||
ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties;
|
||||
pProp->SetPropertyBool("bJoinIdenticalVertices", pp & aiProcess_JoinIdenticalVertices);
|
||||
exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp);
|
||||
|
||||
@@ -43,23 +43,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef ASSIMP_FILELOGSTREAM_H_INC
|
||||
#define ASSIMP_FILELOGSTREAM_H_INC
|
||||
|
||||
#include <assimp/LogStream.hpp>
|
||||
#include <assimp/IOStream.hpp>
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
#include <assimp/IOStream.hpp>
|
||||
#include <assimp/LogStream.hpp>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Assimp {
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
/** @class FileLogStream
|
||||
* @brief Logstream to write into a file.
|
||||
*/
|
||||
class FileLogStream :
|
||||
public LogStream
|
||||
{
|
||||
class FileLogStream : public LogStream {
|
||||
public:
|
||||
FileLogStream( const char* file, IOSystem* io = NULL );
|
||||
FileLogStream(const char *file, IOSystem *io = nullptr);
|
||||
~FileLogStream();
|
||||
void write( const char* message );
|
||||
void write(const char *message);
|
||||
|
||||
private:
|
||||
IOStream *m_pStream;
|
||||
@@ -67,41 +65,36 @@ private:
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Constructor
|
||||
inline FileLogStream::FileLogStream( const char* file, IOSystem* io ) :
|
||||
m_pStream(NULL)
|
||||
{
|
||||
if ( !file || 0 == *file )
|
||||
inline FileLogStream::FileLogStream(const char *file, IOSystem *io) :
|
||||
m_pStream(nullptr) {
|
||||
if (!file || 0 == *file)
|
||||
return;
|
||||
|
||||
// If no IOSystem is specified: take a default one
|
||||
if (!io)
|
||||
{
|
||||
if (!io) {
|
||||
DefaultIOSystem FileSystem;
|
||||
m_pStream = FileSystem.Open( file, "wt");
|
||||
}
|
||||
else m_pStream = io->Open( file, "wt" );
|
||||
m_pStream = FileSystem.Open(file, "wt");
|
||||
} else
|
||||
m_pStream = io->Open(file, "wt");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Destructor
|
||||
inline FileLogStream::~FileLogStream()
|
||||
{
|
||||
inline FileLogStream::~FileLogStream() {
|
||||
// The virtual d'tor should destroy the underlying file
|
||||
delete m_pStream;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Write method
|
||||
inline void FileLogStream::write( const char* message )
|
||||
{
|
||||
if (m_pStream != NULL)
|
||||
{
|
||||
inline void FileLogStream::write(const char *message) {
|
||||
if (m_pStream != nullptr) {
|
||||
m_pStream->Write(message, sizeof(char), ::strlen(message));
|
||||
m_pStream->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
} // !Namespace Assimp
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !! ASSIMP_FILELOGSTREAM_H_INC
|
||||
|
||||
@@ -249,7 +249,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp) {
|
||||
// Unregister a custom loader plugin
|
||||
aiReturn Importer::UnregisterLoader(BaseImporter* pImp) {
|
||||
if(!pImp) {
|
||||
// unregistering a NULL importer is no problem for us ... really!
|
||||
// unregistering a nullptr importer is no problem for us ... really!
|
||||
return AI_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp) {
|
||||
// Unregister a custom loader plugin
|
||||
aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) {
|
||||
if(!pImp) {
|
||||
// unregistering a NULL ppstep is no problem for us ... really!
|
||||
// unregistering a nullptr ppstep is no problem for us ... really!
|
||||
return AI_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
|
||||
std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr);
|
||||
if (profiler) {
|
||||
profiler->BeginRegion("total");
|
||||
}
|
||||
@@ -775,7 +775,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
|
||||
}
|
||||
#endif // ! DEBUG
|
||||
|
||||
std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
|
||||
std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr);
|
||||
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
|
||||
BaseProcess* process = pimpl->mPostProcessingSteps[a];
|
||||
pimpl->mProgressHandler->UpdatePostProcess(static_cast<int>(a), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
|
||||
@@ -841,7 +841,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
|
||||
}
|
||||
|
||||
// If no flags are given, return the current scene with no further action
|
||||
if ( NULL == rootProcess ) {
|
||||
if (nullptr == rootProcess) {
|
||||
return pimpl->mScene;
|
||||
}
|
||||
|
||||
@@ -873,7 +873,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
|
||||
}
|
||||
#endif // ! DEBUG
|
||||
|
||||
std::unique_ptr<Profiler> profiler( GetPropertyInteger( AI_CONFIG_GLOB_MEASURE_TIME, 0 ) ? new Profiler() : NULL );
|
||||
std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr);
|
||||
|
||||
if ( profiler ) {
|
||||
profiler->BeginRegion( "postprocess" );
|
||||
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
/** Post processing steps we can apply at the imported data. */
|
||||
std::vector< BaseProcess* > mPostProcessingSteps;
|
||||
|
||||
/** The imported data, if ReadFile() was successful, NULL otherwise. */
|
||||
/** The imported data, if ReadFile() was successful, nullptr otherwise. */
|
||||
aiScene* mScene;
|
||||
|
||||
/** The error description, if there was one. */
|
||||
@@ -216,7 +216,7 @@ public:
|
||||
unsigned int AddLoadRequest (
|
||||
const std::string& file,
|
||||
unsigned int steps = 0,
|
||||
const PropertyMap* map = NULL
|
||||
const PropertyMap *map = nullptr
|
||||
);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@@ -226,7 +226,7 @@ public:
|
||||
* can be called several times, too.
|
||||
*
|
||||
* @param which LRWC returned by AddLoadRequest().
|
||||
* @return NULL if there is no scene with this file name
|
||||
* @return nullptr if there is no scene with this file name
|
||||
* in the queue of the scene hasn't been loaded yet. */
|
||||
aiScene* GetImport(
|
||||
unsigned int which
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
@@ -46,330 +46,326 @@ directly (unless you are adding new loaders), instead use the
|
||||
corresponding preprocessor flag to selectively disable formats.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <vector>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Importers
|
||||
// (include_new_importers_here)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#ifndef ASSIMP_BUILD_NO_X_IMPORTER
|
||||
# include "X/XFileImporter.h"
|
||||
#include "AssetLib/X/XFileImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
|
||||
# include "AMF/AMFImporter.hpp"
|
||||
#include "AssetLib/AMF/AMFImporter.hpp"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
|
||||
# include "3DS/3DSLoader.h"
|
||||
#include "AssetLib/3DS/3DSLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
|
||||
# include "MD3/MD3Loader.h"
|
||||
#include "AssetLib/MD3/MD3Loader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
|
||||
# include "MDL/MDLLoader.h"
|
||||
#include "AssetLib/MDL/MDLLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
|
||||
# include "MD2/MD2Loader.h"
|
||||
#include "AssetLib/MD2/MD2Loader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
|
||||
# include "Ply/PlyLoader.h"
|
||||
#include "AssetLib/Ply/PlyLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
|
||||
# include "ASE/ASELoader.h"
|
||||
#include "AssetLib/ASE/ASELoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
|
||||
# include "Obj/ObjFileImporter.h"
|
||||
#include "AssetLib/Obj/ObjFileImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
|
||||
# include "HMP/HMPLoader.h"
|
||||
#include "AssetLib/HMP/HMPLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER
|
||||
# include "SMD/SMDLoader.h"
|
||||
#include "AssetLib/SMD/SMDLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
|
||||
# include "MDC/MDCLoader.h"
|
||||
#include "AssetLib/MDC/MDCLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
|
||||
# include "MD5/MD5Loader.h"
|
||||
#include "AssetLib/MD5/MD5Loader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_STL_IMPORTER
|
||||
# include "STL/STLLoader.h"
|
||||
#include "AssetLib/STL/STLLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
|
||||
# include "LWO/LWOLoader.h"
|
||||
#include "AssetLib/LWO/LWOLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
|
||||
# include "DXF/DXFLoader.h"
|
||||
#include "AssetLib/DXF/DXFLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_NFF_IMPORTER
|
||||
# include "NFF/NFFLoader.h"
|
||||
#include "AssetLib/NFF/NFFLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
|
||||
# include "Raw/RawLoader.h"
|
||||
#include "AssetLib/Raw/RawLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_SIB_IMPORTER
|
||||
# include "SIB/SIBImporter.h"
|
||||
#include "AssetLib/SIB/SIBImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
|
||||
# include "OFF/OFFLoader.h"
|
||||
#include "AssetLib/OFF/OFFLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_AC_IMPORTER
|
||||
# include "AC/ACLoader.h"
|
||||
#include "AssetLib/AC/ACLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
|
||||
# include "BVH/BVHLoader.h"
|
||||
#include "AssetLib/BVH/BVHLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
|
||||
# include "Irr/IRRMeshLoader.h"
|
||||
#include "AssetLib/Irr/IRRMeshLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
|
||||
# include "Irr/IRRLoader.h"
|
||||
#include "AssetLib/Irr/IRRLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER
|
||||
# include "Q3D/Q3DLoader.h"
|
||||
#include "AssetLib/Q3D/Q3DLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
|
||||
# include "B3D/B3DImporter.h"
|
||||
#include "AssetLib/B3D/B3DImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
|
||||
# include "Collada/ColladaLoader.h"
|
||||
#include "AssetLib/Collada/ColladaLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
|
||||
# include "Terragen/TerragenLoader.h"
|
||||
#include "AssetLib/Terragen/TerragenLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
|
||||
# include "CSM/CSMLoader.h"
|
||||
#include "AssetLib/CSM/CSMLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3D_IMPORTER
|
||||
# include "Unreal/UnrealLoader.h"
|
||||
#include "AssetLib/Unreal/UnrealLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
|
||||
# include "LWS/LWSLoader.h"
|
||||
#include "AssetLib/LWS/LWSLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||
# include "Ogre/OgreImporter.h"
|
||||
#include "AssetLib/Ogre/OgreImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
|
||||
# include "OpenGEX/OpenGEXImporter.h"
|
||||
#include "AssetLib/OpenGEX/OpenGEXImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
|
||||
# include "MS3D/MS3DLoader.h"
|
||||
#include "AssetLib/MS3D/MS3DLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
|
||||
# include "COB/COBLoader.h"
|
||||
#include "AssetLib/COB/COBLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
# include "Blender/BlenderLoader.h"
|
||||
#include "AssetLib/Blender/BlenderLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
|
||||
# include "Q3BSP/Q3BSPFileImporter.h"
|
||||
#include "AssetLib/Q3BSP/Q3BSPFileImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
|
||||
# include "NDO/NDOLoader.h"
|
||||
#include "AssetLib/NDO/NDOLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
|
||||
# include "Importer/IFC/IFCLoader.h"
|
||||
#include "AssetLib/IFC/IFCLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
|
||||
# include "XGL/XGLLoader.h"
|
||||
#include "AssetLib/XGL/XGLLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||
# include "FBX/FBXImporter.h"
|
||||
#include "AssetLib/FBX/FBXImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
|
||||
# include "Assbin/AssbinLoader.h"
|
||||
#include "AssetLib/Assbin/AssbinLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
|
||||
# include "glTF/glTFImporter.h"
|
||||
# include "glTF2/glTF2Importer.h"
|
||||
#include "AssetLib/glTF/glTFImporter.h"
|
||||
#include "AssetLib/glTF2/glTF2Importer.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
|
||||
# include "C4D/C4DImporter.h"
|
||||
#include "AssetLib/C4D/C4DImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
|
||||
# include "3MF/D3MFImporter.h"
|
||||
#include "AssetLib/3MF/D3MFImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
# include "X3D/X3DImporter.hpp"
|
||||
#include "AssetLib/X3D/X3DImporter.hpp"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
|
||||
# include "MMD/MMDImporter.h"
|
||||
#include "AssetLib/MMD/MMDImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
|
||||
# include "M3D/M3DImporter.h"
|
||||
#include "AssetLib/M3D/M3DImporter.h"
|
||||
#endif
|
||||
//#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
|
||||
//# include "Importer/StepFile/StepFileImporter.h"
|
||||
//#endif
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void GetImporterInstanceList(std::vector< BaseImporter* >& out)
|
||||
{
|
||||
void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// Add an instance of each worker class here
|
||||
// (register_new_importers_here)
|
||||
// ----------------------------------------------------------------------------
|
||||
out.reserve(64);
|
||||
#if (!defined ASSIMP_BUILD_NO_X_IMPORTER)
|
||||
out.push_back( new XFileImporter());
|
||||
out.push_back(new XFileImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
|
||||
out.push_back( new ObjFileImporter());
|
||||
out.push_back(new ObjFileImporter());
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
|
||||
out.push_back( new AMFImporter() );
|
||||
out.push_back(new AMFImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
|
||||
out.push_back( new Discreet3DSImporter());
|
||||
out.push_back(new Discreet3DSImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_M3D_IMPORTER)
|
||||
out.push_back( new M3DImporter());
|
||||
out.push_back(new M3DImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
|
||||
out.push_back( new MD3Importer());
|
||||
out.push_back(new MD3Importer());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
|
||||
out.push_back( new MD2Importer());
|
||||
out.push_back(new MD2Importer());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
|
||||
out.push_back( new PLYImporter());
|
||||
out.push_back(new PLYImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
|
||||
out.push_back( new MDLImporter());
|
||||
out.push_back(new MDLImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
|
||||
#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
|
||||
out.push_back( new ASEImporter());
|
||||
# endif
|
||||
#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
|
||||
out.push_back(new ASEImporter());
|
||||
#endif
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
|
||||
out.push_back( new HMPImporter());
|
||||
out.push_back(new HMPImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
|
||||
out.push_back( new SMDImporter());
|
||||
out.push_back(new SMDImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
|
||||
out.push_back( new MDCImporter());
|
||||
out.push_back(new MDCImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
|
||||
out.push_back( new MD5Importer());
|
||||
out.push_back(new MD5Importer());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
|
||||
out.push_back( new STLImporter());
|
||||
out.push_back(new STLImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
|
||||
out.push_back( new LWOImporter());
|
||||
out.push_back(new LWOImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
|
||||
out.push_back( new DXFImporter());
|
||||
out.push_back(new DXFImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
|
||||
out.push_back( new NFFImporter());
|
||||
out.push_back(new NFFImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
|
||||
out.push_back( new RAWImporter());
|
||||
out.push_back(new RAWImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_SIB_IMPORTER)
|
||||
out.push_back( new SIBImporter());
|
||||
out.push_back(new SIBImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
|
||||
out.push_back( new OFFImporter());
|
||||
out.push_back(new OFFImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
|
||||
out.push_back( new AC3DImporter());
|
||||
out.push_back(new AC3DImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
|
||||
out.push_back( new BVHLoader());
|
||||
out.push_back(new BVHLoader());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
|
||||
out.push_back( new IRRMeshImporter());
|
||||
out.push_back(new IRRMeshImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
|
||||
out.push_back( new IRRImporter());
|
||||
out.push_back(new IRRImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
|
||||
out.push_back( new Q3DImporter());
|
||||
out.push_back(new Q3DImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
|
||||
out.push_back( new B3DImporter());
|
||||
out.push_back(new B3DImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
|
||||
out.push_back( new ColladaLoader());
|
||||
out.push_back(new ColladaLoader());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
|
||||
out.push_back( new TerragenImporter());
|
||||
out.push_back(new TerragenImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
|
||||
out.push_back( new CSMImporter());
|
||||
out.push_back(new CSMImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
|
||||
out.push_back( new UnrealImporter());
|
||||
out.push_back(new UnrealImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
|
||||
out.push_back( new LWSImporter());
|
||||
out.push_back(new LWSImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER)
|
||||
out.push_back( new Ogre::OgreImporter());
|
||||
out.push_back(new Ogre::OgreImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_OPENGEX_IMPORTER )
|
||||
out.push_back( new OpenGEX::OpenGEXImporter() );
|
||||
#if (!defined ASSIMP_BUILD_NO_OPENGEX_IMPORTER)
|
||||
out.push_back(new OpenGEX::OpenGEXImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER)
|
||||
out.push_back( new MS3DImporter());
|
||||
out.push_back(new MS3DImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
|
||||
out.push_back( new COBImporter());
|
||||
out.push_back(new COBImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
|
||||
out.push_back( new BlenderImporter());
|
||||
out.push_back(new BlenderImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
|
||||
out.push_back( new Q3BSPFileImporter() );
|
||||
out.push_back(new Q3BSPFileImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
|
||||
out.push_back( new NDOImporter() );
|
||||
out.push_back(new NDOImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
|
||||
out.push_back( new IFCImporter() );
|
||||
out.push_back(new IFCImporter());
|
||||
#endif
|
||||
#if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
|
||||
out.push_back( new XGLImporter() );
|
||||
#if (!defined ASSIMP_BUILD_NO_XGL_IMPORTER)
|
||||
out.push_back(new XGLImporter());
|
||||
#endif
|
||||
#if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
|
||||
out.push_back( new FBXImporter() );
|
||||
#if (!defined ASSIMP_BUILD_NO_FBX_IMPORTER)
|
||||
out.push_back(new FBXImporter());
|
||||
#endif
|
||||
#if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
|
||||
out.push_back( new AssbinImporter() );
|
||||
#if (!defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER)
|
||||
out.push_back(new AssbinImporter());
|
||||
#endif
|
||||
#if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER )
|
||||
out.push_back( new glTFImporter() );
|
||||
out.push_back( new glTF2Importer() );
|
||||
#if (!defined ASSIMP_BUILD_NO_GLTF_IMPORTER)
|
||||
out.push_back(new glTFImporter());
|
||||
out.push_back(new glTF2Importer());
|
||||
#endif
|
||||
#if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER )
|
||||
out.push_back( new C4DImporter() );
|
||||
#if (!defined ASSIMP_BUILD_NO_C4D_IMPORTER)
|
||||
out.push_back(new C4DImporter());
|
||||
#endif
|
||||
#if ( !defined ASSIMP_BUILD_NO_3MF_IMPORTER )
|
||||
out.push_back( new D3MFImporter() );
|
||||
#if (!defined ASSIMP_BUILD_NO_3MF_IMPORTER)
|
||||
out.push_back(new D3MFImporter());
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
out.push_back( new X3DImporter() );
|
||||
out.push_back(new X3DImporter());
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
|
||||
out.push_back( new MMDImporter() );
|
||||
out.push_back(new MMDImporter());
|
||||
#endif
|
||||
//#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
|
||||
// out.push_back(new StepFile::StepFileImporter());
|
||||
//#endif
|
||||
//#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
|
||||
// out.push_back(new StepFile::StepFileImporter());
|
||||
//#endif
|
||||
}
|
||||
|
||||
/** will delete all registered importers. */
|
||||
void DeleteImporterInstanceList(std::vector< BaseImporter* >& deleteList){
|
||||
for(size_t i= 0; i<deleteList.size();++i){
|
||||
delete deleteList[i];
|
||||
deleteList[i]=nullptr;
|
||||
}//for
|
||||
void DeleteImporterInstanceList(std::vector<BaseImporter *> &deleteList) {
|
||||
for (size_t i = 0; i < deleteList.size(); ++i) {
|
||||
delete deleteList[i];
|
||||
deleteList[i] = nullptr;
|
||||
} //for
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
@@ -55,7 +55,9 @@ void CommentRemover::RemoveLineComments(const char* szComment,
|
||||
char* szBuffer, char chReplacement /* = ' ' */)
|
||||
{
|
||||
// validate parameters
|
||||
ai_assert(NULL != szComment && NULL != szBuffer && *szComment);
|
||||
ai_assert(nullptr != szComment);
|
||||
ai_assert(nullptr != szBuffer);
|
||||
ai_assert(*szComment);
|
||||
|
||||
const size_t len = strlen(szComment);
|
||||
while (*szBuffer) {
|
||||
@@ -83,8 +85,11 @@ void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
|
||||
char chReplacement)
|
||||
{
|
||||
// validate parameters
|
||||
ai_assert(NULL != szCommentStart && NULL != szCommentEnd &&
|
||||
NULL != szBuffer && *szCommentStart && *szCommentEnd);
|
||||
ai_assert(nullptr != szCommentStart);
|
||||
ai_assert(nullptr != szCommentEnd);
|
||||
ai_assert(nullptr != szBuffer);
|
||||
ai_assert(*szCommentStart);
|
||||
ai_assert(*szCommentEnd);
|
||||
|
||||
const size_t len = strlen(szCommentEnd);
|
||||
const size_t len2 = strlen(szCommentStart);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,16 +45,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
void ScenePreprocessor::ProcessScene ()
|
||||
{
|
||||
ai_assert(scene != NULL);
|
||||
void ScenePreprocessor::ProcessScene() {
|
||||
ai_assert(scene != nullptr);
|
||||
|
||||
// Process all meshes
|
||||
for (unsigned int i = 0; i < scene->mNumMeshes;++i)
|
||||
for (unsigned int i = 0; i < scene->mNumMeshes; ++i)
|
||||
ProcessMesh(scene->mMeshes[i]);
|
||||
|
||||
// - nothing to do for nodes for the moment
|
||||
@@ -63,27 +61,27 @@ void ScenePreprocessor::ProcessScene ()
|
||||
// - nothing to do for cameras for the moment
|
||||
|
||||
// Process all animations
|
||||
for (unsigned int i = 0; i < scene->mNumAnimations;++i)
|
||||
for (unsigned int i = 0; i < scene->mNumAnimations; ++i)
|
||||
ProcessAnimation(scene->mAnimations[i]);
|
||||
|
||||
// Generate a default material if none was specified
|
||||
if (!scene->mNumMaterials && scene->mNumMeshes) {
|
||||
scene->mMaterials = new aiMaterial*[2];
|
||||
aiMaterial* helper;
|
||||
scene->mMaterials = new aiMaterial *[2];
|
||||
aiMaterial *helper;
|
||||
|
||||
aiString name;
|
||||
|
||||
scene->mMaterials[scene->mNumMaterials] = helper = new aiMaterial();
|
||||
aiColor3D clr(0.6f,0.6f,0.6f);
|
||||
helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||
aiColor3D clr(0.6f, 0.6f, 0.6f);
|
||||
helper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
|
||||
// setup the default name to make this material identifiable
|
||||
name.Set(AI_DEFAULT_MATERIAL_NAME);
|
||||
helper->AddProperty(&name,AI_MATKEY_NAME);
|
||||
helper->AddProperty(&name, AI_MATKEY_NAME);
|
||||
|
||||
ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'");
|
||||
ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'");
|
||||
|
||||
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
|
||||
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
|
||||
scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials;
|
||||
}
|
||||
|
||||
@@ -92,17 +90,16 @@ void ScenePreprocessor::ProcessScene ()
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
|
||||
{
|
||||
void ScenePreprocessor::ProcessMesh(aiMesh *mesh) {
|
||||
// If aiMesh::mNumUVComponents is *not* set assign the default value of 2
|
||||
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||
if (!mesh->mTextureCoords[i]) {
|
||||
mesh->mNumUVComponents[i] = 0;
|
||||
} else {
|
||||
if (!mesh->mNumUVComponents[i])
|
||||
mesh->mNumUVComponents[i] = 2;
|
||||
|
||||
aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices;
|
||||
aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices;
|
||||
|
||||
// Ensure unused components are zeroed. This will make 1D texture channels work
|
||||
// as if they were 2D channels .. just in case an application doesn't handle
|
||||
@@ -110,12 +107,10 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
|
||||
if (2 == mesh->mNumUVComponents[i]) {
|
||||
for (; p != end; ++p)
|
||||
p->z = 0.f;
|
||||
}
|
||||
else if (1 == mesh->mNumUVComponents[i]) {
|
||||
} else if (1 == mesh->mNumUVComponents[i]) {
|
||||
for (; p != end; ++p)
|
||||
p->z = p->y = 0.f;
|
||||
}
|
||||
else if (3 == mesh->mNumUVComponents[i]) {
|
||||
} else if (3 == mesh->mNumUVComponents[i]) {
|
||||
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
|
||||
for (; p != end; ++p) {
|
||||
if (p->z != 0)
|
||||
@@ -132,10 +127,9 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
|
||||
// If the information which primitive types are there in the
|
||||
// mesh is currently not available, compute it.
|
||||
if (!mesh->mPrimitiveTypes) {
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
|
||||
aiFace& face = mesh->mFaces[a];
|
||||
switch (face.mNumIndices)
|
||||
{
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
|
||||
aiFace &face = mesh->mFaces[a];
|
||||
switch (face.mNumIndices) {
|
||||
case 3u:
|
||||
mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||
break;
|
||||
@@ -156,21 +150,20 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
|
||||
}
|
||||
|
||||
// If tangents and normals are given but no bitangents compute them
|
||||
if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) {
|
||||
if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) {
|
||||
|
||||
mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices;++i) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
mesh->mBitangents[i] = mesh->mNormals[i] ^ mesh->mTangents[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
|
||||
{
|
||||
void ScenePreprocessor::ProcessAnimation(aiAnimation *anim) {
|
||||
double first = 10e10, last = -10e10;
|
||||
for (unsigned int i = 0; i < anim->mNumChannels;++i) {
|
||||
aiNodeAnim* channel = anim->mChannels[i];
|
||||
for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
|
||||
aiNodeAnim *channel = anim->mChannels[i];
|
||||
|
||||
/* If the exact duration of the animation is not given
|
||||
* compute it now.
|
||||
@@ -178,24 +171,24 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
|
||||
if (anim->mDuration == -1.) {
|
||||
|
||||
// Position keys
|
||||
for (unsigned int j = 0; j < channel->mNumPositionKeys;++j) {
|
||||
aiVectorKey& key = channel->mPositionKeys[j];
|
||||
first = std::min (first, key.mTime);
|
||||
last = std::max (last, key.mTime);
|
||||
for (unsigned int j = 0; j < channel->mNumPositionKeys; ++j) {
|
||||
aiVectorKey &key = channel->mPositionKeys[j];
|
||||
first = std::min(first, key.mTime);
|
||||
last = std::max(last, key.mTime);
|
||||
}
|
||||
|
||||
// Scaling keys
|
||||
for (unsigned int j = 0; j < channel->mNumScalingKeys;++j ) {
|
||||
aiVectorKey& key = channel->mScalingKeys[j];
|
||||
first = std::min (first, key.mTime);
|
||||
last = std::max (last, key.mTime);
|
||||
for (unsigned int j = 0; j < channel->mNumScalingKeys; ++j) {
|
||||
aiVectorKey &key = channel->mScalingKeys[j];
|
||||
first = std::min(first, key.mTime);
|
||||
last = std::max(last, key.mTime);
|
||||
}
|
||||
|
||||
// Rotation keys
|
||||
for (unsigned int j = 0; j < channel->mNumRotationKeys;++j ) {
|
||||
aiQuatKey& key = channel->mRotationKeys[ j ];
|
||||
first = std::min (first, key.mTime);
|
||||
last = std::max (last, key.mTime);
|
||||
for (unsigned int j = 0; j < channel->mNumRotationKeys; ++j) {
|
||||
aiQuatKey &key = channel->mRotationKeys[j];
|
||||
first = std::min(first, key.mTime);
|
||||
last = std::max(last, key.mTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,43 +197,43 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
|
||||
* track from the information we have in the transformation
|
||||
* matrix of the corresponding node.
|
||||
*/
|
||||
if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) {
|
||||
if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) {
|
||||
// Find the node that belongs to this animation
|
||||
aiNode* node = scene->mRootNode->FindNode(channel->mNodeName);
|
||||
if (node) // ValidateDS will complain later if 'node' is NULL
|
||||
aiNode *node = scene->mRootNode->FindNode(channel->mNodeName);
|
||||
if (node) // ValidateDS will complain later if 'node' is nullptr
|
||||
{
|
||||
// Decompose the transformation matrix of the node
|
||||
aiVector3D scaling, position;
|
||||
aiQuaternion rotation;
|
||||
|
||||
node->mTransformation.Decompose(scaling, rotation,position);
|
||||
node->mTransformation.Decompose(scaling, rotation, position);
|
||||
|
||||
// No rotation keys? Generate a dummy track
|
||||
if (!channel->mNumRotationKeys) {
|
||||
ai_assert(!channel->mRotationKeys);
|
||||
channel->mNumRotationKeys = 1;
|
||||
channel->mRotationKeys = new aiQuatKey[1];
|
||||
aiQuatKey& q = channel->mRotationKeys[0];
|
||||
aiQuatKey &q = channel->mRotationKeys[0];
|
||||
|
||||
q.mTime = 0.;
|
||||
q.mTime = 0.;
|
||||
q.mValue = rotation;
|
||||
|
||||
ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy rotation track has been generated");
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy rotation track has been generated");
|
||||
} else {
|
||||
ai_assert(channel->mRotationKeys);
|
||||
}
|
||||
|
||||
// No scaling keys? Generate a dummy track
|
||||
if (!channel->mNumScalingKeys) {
|
||||
if (!channel->mNumScalingKeys) {
|
||||
ai_assert(!channel->mScalingKeys);
|
||||
channel->mNumScalingKeys = 1;
|
||||
channel->mScalingKeys = new aiVectorKey[1];
|
||||
aiVectorKey& q = channel->mScalingKeys[0];
|
||||
aiVectorKey &q = channel->mScalingKeys[0];
|
||||
|
||||
q.mTime = 0.;
|
||||
q.mTime = 0.;
|
||||
q.mValue = scaling;
|
||||
|
||||
ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy scaling track has been generated");
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy scaling track has been generated");
|
||||
} else {
|
||||
ai_assert(channel->mScalingKeys);
|
||||
}
|
||||
@@ -250,12 +243,12 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
|
||||
ai_assert(!channel->mPositionKeys);
|
||||
channel->mNumPositionKeys = 1;
|
||||
channel->mPositionKeys = new aiVectorKey[1];
|
||||
aiVectorKey& q = channel->mPositionKeys[0];
|
||||
aiVectorKey &q = channel->mPositionKeys[0];
|
||||
|
||||
q.mTime = 0.;
|
||||
q.mTime = 0.;
|
||||
q.mValue = position;
|
||||
|
||||
ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy position track has been generated");
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy position track has been generated");
|
||||
} else {
|
||||
ai_assert(channel->mPositionKeys);
|
||||
}
|
||||
@@ -263,8 +256,8 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
|
||||
}
|
||||
}
|
||||
|
||||
if (anim->mDuration == -1.) {
|
||||
ASSIMP_LOG_DEBUG("ScenePreprocessor: Setting animation duration");
|
||||
anim->mDuration = last - std::min( first, 0. );
|
||||
if (anim->mDuration == -1.) {
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Setting animation duration");
|
||||
anim->mDuration = last - std::min(first, 0.);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ struct aiAnimation;
|
||||
struct aiMesh;
|
||||
|
||||
class ScenePreprocessorTest;
|
||||
namespace Assimp {
|
||||
namespace Assimp {
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
/** ScenePreprocessor: Preprocess a scene before any post-processing
|
||||
@@ -63,24 +63,21 @@ namespace Assimp {
|
||||
* importer, such as aiMesh::mPrimitiveTypes.
|
||||
*/
|
||||
// ----------------------------------------------------------------------------------
|
||||
class ASSIMP_API ScenePreprocessor
|
||||
{
|
||||
class ASSIMP_API ScenePreprocessor {
|
||||
// Make ourselves a friend of the corresponding test unit.
|
||||
friend class ::ScenePreprocessorTest;
|
||||
public:
|
||||
|
||||
public:
|
||||
// ----------------------------------------------------------------
|
||||
/** Default c'tpr. Use SetScene() to assign a scene to the object.
|
||||
*/
|
||||
ScenePreprocessor()
|
||||
: scene (NULL)
|
||||
{}
|
||||
ScenePreprocessor() :
|
||||
scene(nullptr) {}
|
||||
|
||||
/** Constructs the object and assigns a specific scene to it
|
||||
*/
|
||||
ScenePreprocessor(aiScene* _scene)
|
||||
: scene (_scene)
|
||||
{}
|
||||
ScenePreprocessor(aiScene *_scene) :
|
||||
scene(_scene) {}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
/** Assign a (new) scene to the object.
|
||||
@@ -89,37 +86,33 @@ public:
|
||||
* Call ProcessScene to have the scene preprocessed.
|
||||
* @param sc Scene to be processed.
|
||||
*/
|
||||
void SetScene (aiScene* sc) {
|
||||
void SetScene(aiScene *sc) {
|
||||
scene = sc;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
/** Preprocess the current scene
|
||||
*/
|
||||
void ProcessScene ();
|
||||
void ProcessScene();
|
||||
|
||||
protected:
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
/** Preprocess an animation in the scene
|
||||
* @param anim Anim to be preprocessed.
|
||||
*/
|
||||
void ProcessAnimation (aiAnimation* anim);
|
||||
|
||||
void ProcessAnimation(aiAnimation *anim);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
/** Preprocess a mesh in the scene
|
||||
* @param mesh Mesh to be preprocessed.
|
||||
*/
|
||||
void ProcessMesh (aiMesh* mesh);
|
||||
void ProcessMesh(aiMesh *mesh);
|
||||
|
||||
protected:
|
||||
|
||||
//! Scene we're currently working on
|
||||
aiScene* scene;
|
||||
aiScene *scene;
|
||||
};
|
||||
|
||||
|
||||
} // ! end namespace Assimp
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // include guard
|
||||
|
||||
@@ -44,30 +44,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* @brief Implementation of a little class to construct a dummy mesh for a skeleton
|
||||
*/
|
||||
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/SkeletonMeshBuilder.h>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// The constructor processes the given scene and adds a mesh there.
|
||||
SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bKnobsOnly)
|
||||
{
|
||||
SkeletonMeshBuilder::SkeletonMeshBuilder(aiScene *pScene, aiNode *root, bool bKnobsOnly) {
|
||||
// nothing to do if there's mesh data already present at the scene
|
||||
if( pScene->mNumMeshes > 0 || pScene->mRootNode == NULL)
|
||||
if (pScene->mNumMeshes > 0 || pScene->mRootNode == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!root)
|
||||
if (!root) {
|
||||
root = pScene->mRootNode;
|
||||
}
|
||||
|
||||
mKnobsOnly = bKnobsOnly;
|
||||
|
||||
// build some faces around each node
|
||||
CreateGeometry( root );
|
||||
CreateGeometry(root);
|
||||
|
||||
// create a mesh to hold all the generated faces
|
||||
pScene->mNumMeshes = 1;
|
||||
pScene->mMeshes = new aiMesh*[1];
|
||||
pScene->mMeshes = new aiMesh *[1];
|
||||
pScene->mMeshes[0] = CreateMesh();
|
||||
// and install it at the root node
|
||||
root->mNumMeshes = 1;
|
||||
@@ -75,154 +76,146 @@ SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bK
|
||||
root->mMeshes[0] = 0;
|
||||
|
||||
// create a dummy material for the mesh
|
||||
if(pScene->mNumMaterials==0){
|
||||
pScene->mNumMaterials = 1;
|
||||
pScene->mMaterials = new aiMaterial*[1];
|
||||
pScene->mMaterials[0] = CreateMaterial();
|
||||
if (pScene->mNumMaterials == 0) {
|
||||
pScene->mNumMaterials = 1;
|
||||
pScene->mMaterials = new aiMaterial *[1];
|
||||
pScene->mMaterials[0] = CreateMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Recursively builds a simple mesh representation for the given node
|
||||
void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
|
||||
{
|
||||
void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
|
||||
// add a joint entry for the node.
|
||||
const unsigned int vertexStartIndex = static_cast<unsigned int>(mVertices.size());
|
||||
|
||||
// now build the geometry.
|
||||
if( pNode->mNumChildren > 0 && !mKnobsOnly)
|
||||
{
|
||||
if (pNode->mNumChildren > 0 && !mKnobsOnly) {
|
||||
// If the node has children, we build little pointers to each of them
|
||||
for( unsigned int a = 0; a < pNode->mNumChildren; a++)
|
||||
{
|
||||
for (unsigned int a = 0; a < pNode->mNumChildren; a++) {
|
||||
// find a suitable coordinate system
|
||||
const aiMatrix4x4& childTransform = pNode->mChildren[a]->mTransformation;
|
||||
aiVector3D childpos( childTransform.a4, childTransform.b4, childTransform.c4);
|
||||
const aiMatrix4x4 &childTransform = pNode->mChildren[a]->mTransformation;
|
||||
aiVector3D childpos(childTransform.a4, childTransform.b4, childTransform.c4);
|
||||
ai_real distanceToChild = childpos.Length();
|
||||
if( distanceToChild < 0.0001)
|
||||
if (distanceToChild < 0.0001)
|
||||
continue;
|
||||
aiVector3D up = aiVector3D( childpos).Normalize();
|
||||
aiVector3D up = aiVector3D(childpos).Normalize();
|
||||
|
||||
aiVector3D orth( 1.0, 0.0, 0.0);
|
||||
if( std::fabs( orth * up) > 0.99)
|
||||
orth.Set( 0.0, 1.0, 0.0);
|
||||
aiVector3D orth(1.0, 0.0, 0.0);
|
||||
if (std::fabs(orth * up) > 0.99)
|
||||
orth.Set(0.0, 1.0, 0.0);
|
||||
|
||||
aiVector3D front = (up ^ orth).Normalize();
|
||||
aiVector3D side = (front ^ up).Normalize();
|
||||
|
||||
unsigned int localVertexStart = static_cast<unsigned int>(mVertices.size());
|
||||
mVertices.push_back( -front * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back( childpos);
|
||||
mVertices.push_back( -side * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back( -side * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back( childpos);
|
||||
mVertices.push_back( front * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back( front * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back( childpos);
|
||||
mVertices.push_back( side * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back( side * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back( childpos);
|
||||
mVertices.push_back( -front * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back(-front * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back(childpos);
|
||||
mVertices.push_back(-side * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back(-side * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back(childpos);
|
||||
mVertices.push_back(front * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back(front * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back(childpos);
|
||||
mVertices.push_back(side * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back(side * distanceToChild * (ai_real)0.1);
|
||||
mVertices.push_back(childpos);
|
||||
mVertices.push_back(-front * distanceToChild * (ai_real)0.1);
|
||||
|
||||
mFaces.push_back( Face( localVertexStart + 0, localVertexStart + 1, localVertexStart + 2));
|
||||
mFaces.push_back( Face( localVertexStart + 3, localVertexStart + 4, localVertexStart + 5));
|
||||
mFaces.push_back( Face( localVertexStart + 6, localVertexStart + 7, localVertexStart + 8));
|
||||
mFaces.push_back( Face( localVertexStart + 9, localVertexStart + 10, localVertexStart + 11));
|
||||
mFaces.push_back(Face(localVertexStart + 0, localVertexStart + 1, localVertexStart + 2));
|
||||
mFaces.push_back(Face(localVertexStart + 3, localVertexStart + 4, localVertexStart + 5));
|
||||
mFaces.push_back(Face(localVertexStart + 6, localVertexStart + 7, localVertexStart + 8));
|
||||
mFaces.push_back(Face(localVertexStart + 9, localVertexStart + 10, localVertexStart + 11));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// if the node has no children, it's an end node. Put a little knob there instead
|
||||
aiVector3D ownpos( pNode->mTransformation.a4, pNode->mTransformation.b4, pNode->mTransformation.c4);
|
||||
ai_real sizeEstimate = ownpos.Length() * ai_real( 0.18 );
|
||||
aiVector3D ownpos(pNode->mTransformation.a4, pNode->mTransformation.b4, pNode->mTransformation.c4);
|
||||
ai_real sizeEstimate = ownpos.Length() * ai_real(0.18);
|
||||
|
||||
mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
|
||||
mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
|
||||
mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
|
||||
mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
|
||||
mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
|
||||
mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
|
||||
mVertices.push_back(aiVector3D(-sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, sizeEstimate, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, 0.0, -sizeEstimate));
|
||||
mVertices.push_back(aiVector3D(0.0, sizeEstimate, 0.0));
|
||||
mVertices.push_back(aiVector3D(sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, 0.0, -sizeEstimate));
|
||||
mVertices.push_back(aiVector3D(sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, -sizeEstimate, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, 0.0, -sizeEstimate));
|
||||
mVertices.push_back(aiVector3D(0.0, -sizeEstimate, 0.0));
|
||||
mVertices.push_back(aiVector3D(-sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, 0.0, -sizeEstimate));
|
||||
|
||||
mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
|
||||
mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
|
||||
mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
|
||||
mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
|
||||
mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
|
||||
mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back(aiVector3D(-sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, 0.0, sizeEstimate));
|
||||
mVertices.push_back(aiVector3D(0.0, sizeEstimate, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, sizeEstimate, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, 0.0, sizeEstimate));
|
||||
mVertices.push_back(aiVector3D(sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back(aiVector3D(sizeEstimate, 0.0, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, 0.0, sizeEstimate));
|
||||
mVertices.push_back(aiVector3D(0.0, -sizeEstimate, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, -sizeEstimate, 0.0));
|
||||
mVertices.push_back(aiVector3D(0.0, 0.0, sizeEstimate));
|
||||
mVertices.push_back(aiVector3D(-sizeEstimate, 0.0, 0.0));
|
||||
|
||||
mFaces.push_back( Face( vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2));
|
||||
mFaces.push_back( Face( vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5));
|
||||
mFaces.push_back( Face( vertexStartIndex + 6, vertexStartIndex + 7, vertexStartIndex + 8));
|
||||
mFaces.push_back( Face( vertexStartIndex + 9, vertexStartIndex + 10, vertexStartIndex + 11));
|
||||
mFaces.push_back( Face( vertexStartIndex + 12, vertexStartIndex + 13, vertexStartIndex + 14));
|
||||
mFaces.push_back( Face( vertexStartIndex + 15, vertexStartIndex + 16, vertexStartIndex + 17));
|
||||
mFaces.push_back( Face( vertexStartIndex + 18, vertexStartIndex + 19, vertexStartIndex + 20));
|
||||
mFaces.push_back( Face( vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23));
|
||||
mFaces.push_back(Face(vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2));
|
||||
mFaces.push_back(Face(vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5));
|
||||
mFaces.push_back(Face(vertexStartIndex + 6, vertexStartIndex + 7, vertexStartIndex + 8));
|
||||
mFaces.push_back(Face(vertexStartIndex + 9, vertexStartIndex + 10, vertexStartIndex + 11));
|
||||
mFaces.push_back(Face(vertexStartIndex + 12, vertexStartIndex + 13, vertexStartIndex + 14));
|
||||
mFaces.push_back(Face(vertexStartIndex + 15, vertexStartIndex + 16, vertexStartIndex + 17));
|
||||
mFaces.push_back(Face(vertexStartIndex + 18, vertexStartIndex + 19, vertexStartIndex + 20));
|
||||
mFaces.push_back(Face(vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23));
|
||||
}
|
||||
|
||||
unsigned int numVertices = static_cast<unsigned int>(mVertices.size() - vertexStartIndex);
|
||||
if( numVertices > 0)
|
||||
{
|
||||
if (numVertices > 0) {
|
||||
// create a bone affecting all the newly created vertices
|
||||
aiBone* bone = new aiBone;
|
||||
mBones.push_back( bone);
|
||||
aiBone *bone = new aiBone;
|
||||
mBones.push_back(bone);
|
||||
bone->mName = pNode->mName;
|
||||
|
||||
// calculate the bone offset matrix by concatenating the inverse transformations of all parents
|
||||
bone->mOffsetMatrix = aiMatrix4x4( pNode->mTransformation).Inverse();
|
||||
for( aiNode* parent = pNode->mParent; parent != NULL; parent = parent->mParent)
|
||||
bone->mOffsetMatrix = aiMatrix4x4( parent->mTransformation).Inverse() * bone->mOffsetMatrix;
|
||||
bone->mOffsetMatrix = aiMatrix4x4(pNode->mTransformation).Inverse();
|
||||
for (aiNode *parent = pNode->mParent; parent != nullptr; parent = parent->mParent)
|
||||
bone->mOffsetMatrix = aiMatrix4x4(parent->mTransformation).Inverse() * bone->mOffsetMatrix;
|
||||
|
||||
// add all the vertices to the bone's influences
|
||||
bone->mNumWeights = numVertices;
|
||||
bone->mWeights = new aiVertexWeight[numVertices];
|
||||
for( unsigned int a = 0; a < numVertices; a++)
|
||||
bone->mWeights[a] = aiVertexWeight( vertexStartIndex + a, 1.0);
|
||||
for (unsigned int a = 0; a < numVertices; a++)
|
||||
bone->mWeights[a] = aiVertexWeight(vertexStartIndex + a, 1.0);
|
||||
|
||||
// HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
|
||||
// them to the array, but I'm tired now and I'm annoyed.
|
||||
aiMatrix4x4 boneToMeshTransform = aiMatrix4x4( bone->mOffsetMatrix).Inverse();
|
||||
for( unsigned int a = vertexStartIndex; a < mVertices.size(); a++)
|
||||
aiMatrix4x4 boneToMeshTransform = aiMatrix4x4(bone->mOffsetMatrix).Inverse();
|
||||
for (unsigned int a = vertexStartIndex; a < mVertices.size(); a++)
|
||||
mVertices[a] = boneToMeshTransform * mVertices[a];
|
||||
}
|
||||
|
||||
// and finally recurse into the children list
|
||||
for( unsigned int a = 0; a < pNode->mNumChildren; a++)
|
||||
CreateGeometry( pNode->mChildren[a]);
|
||||
for (unsigned int a = 0; a < pNode->mNumChildren; a++)
|
||||
CreateGeometry(pNode->mChildren[a]);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Creates the mesh from the internally accumulated stuff and returns it.
|
||||
aiMesh* SkeletonMeshBuilder::CreateMesh()
|
||||
{
|
||||
aiMesh* mesh = new aiMesh();
|
||||
aiMesh *SkeletonMeshBuilder::CreateMesh() {
|
||||
aiMesh *mesh = new aiMesh();
|
||||
|
||||
// add points
|
||||
mesh->mNumVertices = static_cast<unsigned int>(mVertices.size());
|
||||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||
std::copy( mVertices.begin(), mVertices.end(), mesh->mVertices);
|
||||
std::copy(mVertices.begin(), mVertices.end(), mesh->mVertices);
|
||||
|
||||
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
||||
|
||||
// add faces
|
||||
mesh->mNumFaces = static_cast<unsigned int>(mFaces.size());
|
||||
mesh->mFaces = new aiFace[mesh->mNumFaces];
|
||||
for( unsigned int a = 0; a < mesh->mNumFaces; a++)
|
||||
{
|
||||
const Face& inface = mFaces[a];
|
||||
aiFace& outface = mesh->mFaces[a];
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; a++) {
|
||||
const Face &inface = mFaces[a];
|
||||
aiFace &outface = mesh->mFaces[a];
|
||||
outface.mNumIndices = 3;
|
||||
outface.mIndices = new unsigned int[3];
|
||||
outface.mIndices[0] = inface.mIndices[0];
|
||||
@@ -232,10 +225,10 @@ aiMesh* SkeletonMeshBuilder::CreateMesh()
|
||||
// Compute per-face normals ... we don't want the bones to be smoothed ... they're built to visualize
|
||||
// the skeleton, so it's good if there's a visual difference to the rest of the geometry
|
||||
aiVector3D nor = ((mVertices[inface.mIndices[2]] - mVertices[inface.mIndices[0]]) ^
|
||||
(mVertices[inface.mIndices[1]] - mVertices[inface.mIndices[0]]));
|
||||
(mVertices[inface.mIndices[1]] - mVertices[inface.mIndices[0]]));
|
||||
|
||||
if (nor.Length() < 1e-5) /* ensure that FindInvalidData won't remove us ...*/
|
||||
nor = aiVector3D(1.0,0.0,0.0);
|
||||
nor = aiVector3D(1.0, 0.0, 0.0);
|
||||
|
||||
for (unsigned int n = 0; n < 3; ++n)
|
||||
mesh->mNormals[inface.mIndices[n]] = nor;
|
||||
@@ -243,8 +236,8 @@ aiMesh* SkeletonMeshBuilder::CreateMesh()
|
||||
|
||||
// add the bones
|
||||
mesh->mNumBones = static_cast<unsigned int>(mBones.size());
|
||||
mesh->mBones = new aiBone*[mesh->mNumBones];
|
||||
std::copy( mBones.begin(), mBones.end(), mesh->mBones);
|
||||
mesh->mBones = new aiBone *[mesh->mNumBones];
|
||||
std::copy(mBones.begin(), mBones.end(), mesh->mBones);
|
||||
|
||||
// default
|
||||
mesh->mMaterialIndex = 0;
|
||||
@@ -254,17 +247,16 @@ aiMesh* SkeletonMeshBuilder::CreateMesh()
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Creates a dummy material and returns it.
|
||||
aiMaterial* SkeletonMeshBuilder::CreateMaterial()
|
||||
{
|
||||
aiMaterial* matHelper = new aiMaterial;
|
||||
aiMaterial *SkeletonMeshBuilder::CreateMaterial() {
|
||||
aiMaterial *matHelper = new aiMaterial;
|
||||
|
||||
// Name
|
||||
aiString matName( std::string( "SkeletonMaterial"));
|
||||
matHelper->AddProperty( &matName, AI_MATKEY_NAME);
|
||||
aiString matName(std::string("SkeletonMaterial"));
|
||||
matHelper->AddProperty(&matName, AI_MATKEY_NAME);
|
||||
|
||||
// Prevent backface culling
|
||||
const int no_cull = 1;
|
||||
matHelper->AddProperty(&no_cull,1,AI_MATKEY_TWOSIDED);
|
||||
matHelper->AddProperty(&no_cull, 1, AI_MATKEY_TWOSIDED);
|
||||
|
||||
return matHelper;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -50,71 +48,60 @@ using namespace Assimp;
|
||||
|
||||
// CHAR_BIT seems to be defined under MVSC, but not under GCC. Pray that the correct value is 8.
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# pragma warning(disable : 4127)
|
||||
#endif // _WIN32
|
||||
const aiVector3D PlaneInit(0.8523f, 0.34321f, 0.5736f);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructs a spatially sorted representation from the given position array.
|
||||
SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
|
||||
unsigned int pElementOffset)
|
||||
|
||||
// define the reference plane. We choose some arbitrary vector away from all basic axises
|
||||
// in the hope that no model spreads all its vertices along this plane.
|
||||
: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
|
||||
{
|
||||
// define the reference plane. We choose some arbitrary vector away from all basic axises
|
||||
// in the hope that no model spreads all its vertices along this plane.
|
||||
SpatialSort::SpatialSort(const aiVector3D *pPositions, unsigned int pNumPositions, unsigned int pElementOffset) :
|
||||
mPlaneNormal(PlaneInit) {
|
||||
mPlaneNormal.Normalize();
|
||||
Fill(pPositions,pNumPositions,pElementOffset);
|
||||
Fill(pPositions, pNumPositions, pElementOffset);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SpatialSort :: SpatialSort()
|
||||
: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
|
||||
{
|
||||
SpatialSort::SpatialSort() :
|
||||
mPlaneNormal(PlaneInit) {
|
||||
mPlaneNormal.Normalize();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor
|
||||
SpatialSort::~SpatialSort()
|
||||
{
|
||||
// nothing to do here, everything destructs automatically
|
||||
SpatialSort::~SpatialSort() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SpatialSort::Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
|
||||
unsigned int pElementOffset,
|
||||
bool pFinalize /*= true */)
|
||||
{
|
||||
void SpatialSort::Fill(const aiVector3D *pPositions, unsigned int pNumPositions,
|
||||
unsigned int pElementOffset,
|
||||
bool pFinalize /*= true */) {
|
||||
mPositions.clear();
|
||||
Append(pPositions,pNumPositions,pElementOffset,pFinalize);
|
||||
Append(pPositions, pNumPositions, pElementOffset, pFinalize);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SpatialSort :: Finalize()
|
||||
{
|
||||
std::sort( mPositions.begin(), mPositions.end());
|
||||
void SpatialSort::Finalize() {
|
||||
std::sort(mPositions.begin(), mPositions.end());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositions,
|
||||
unsigned int pElementOffset,
|
||||
bool pFinalize /*= true */)
|
||||
{
|
||||
void SpatialSort::Append(const aiVector3D *pPositions, unsigned int pNumPositions,
|
||||
unsigned int pElementOffset,
|
||||
bool pFinalize /*= true */) {
|
||||
// store references to all given positions along with their distance to the reference plane
|
||||
const size_t initial = mPositions.size();
|
||||
mPositions.reserve(initial + (pFinalize?pNumPositions:pNumPositions*2));
|
||||
for( unsigned int a = 0; a < pNumPositions; a++)
|
||||
{
|
||||
const char* tempPointer = reinterpret_cast<const char*> (pPositions);
|
||||
const aiVector3D* vec = reinterpret_cast<const aiVector3D*> (tempPointer + a * pElementOffset);
|
||||
mPositions.reserve(initial + (pFinalize ? pNumPositions : pNumPositions * 2));
|
||||
for (unsigned int a = 0; a < pNumPositions; a++) {
|
||||
const char *tempPointer = reinterpret_cast<const char *>(pPositions);
|
||||
const aiVector3D *vec = reinterpret_cast<const aiVector3D *>(tempPointer + a * pElementOffset);
|
||||
|
||||
// store position by index and distance
|
||||
ai_real distance = *vec * mPlaneNormal;
|
||||
mPositions.push_back( Entry( static_cast<unsigned int>(a+initial), *vec, distance));
|
||||
mPositions.push_back(Entry(static_cast<unsigned int>(a + initial), *vec, distance));
|
||||
}
|
||||
|
||||
if (pFinalize) {
|
||||
@@ -125,9 +112,8 @@ void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositio
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns an iterator for all positions close to the given position.
|
||||
void SpatialSort::FindPositions( const aiVector3D& pPosition,
|
||||
ai_real pRadius, std::vector<unsigned int>& poResults) const
|
||||
{
|
||||
void SpatialSort::FindPositions(const aiVector3D &pPosition,
|
||||
ai_real pRadius, std::vector<unsigned int> &poResults) const {
|
||||
const ai_real dist = pPosition * mPlaneNormal;
|
||||
const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
|
||||
|
||||
@@ -135,19 +121,18 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
|
||||
poResults.clear();
|
||||
|
||||
// quick check for positions outside the range
|
||||
if( mPositions.size() == 0)
|
||||
if (mPositions.size() == 0)
|
||||
return;
|
||||
if( maxDist < mPositions.front().mDistance)
|
||||
if (maxDist < mPositions.front().mDistance)
|
||||
return;
|
||||
if( minDist > mPositions.back().mDistance)
|
||||
if (minDist > mPositions.back().mDistance)
|
||||
return;
|
||||
|
||||
// do a binary search for the minimal distance to start the iteration there
|
||||
unsigned int index = (unsigned int)mPositions.size() / 2;
|
||||
unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
|
||||
while( binaryStepSize > 1)
|
||||
{
|
||||
if( mPositions[index].mDistance < minDist)
|
||||
while (binaryStepSize > 1) {
|
||||
if (mPositions[index].mDistance < minDist)
|
||||
index += binaryStepSize;
|
||||
else
|
||||
index -= binaryStepSize;
|
||||
@@ -157,21 +142,20 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
|
||||
|
||||
// depending on the direction of the last step we need to single step a bit back or forth
|
||||
// to find the actual beginning element of the range
|
||||
while( index > 0 && mPositions[index].mDistance > minDist)
|
||||
while (index > 0 && mPositions[index].mDistance > minDist)
|
||||
index--;
|
||||
while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
|
||||
while (index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
|
||||
index++;
|
||||
|
||||
// Mow start iterating from there until the first position lays outside of the distance range.
|
||||
// Add all positions inside the distance range within the given radius to the result aray
|
||||
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
|
||||
const ai_real pSquared = pRadius*pRadius;
|
||||
while( it->mDistance < maxDist)
|
||||
{
|
||||
if( (it->mPosition - pPosition).SquareLength() < pSquared)
|
||||
poResults.push_back( it->mIndex);
|
||||
const ai_real pSquared = pRadius * pRadius;
|
||||
while (it->mDistance < maxDist) {
|
||||
if ((it->mPosition - pPosition).SquareLength() < pSquared)
|
||||
poResults.push_back(it->mIndex);
|
||||
++it;
|
||||
if( it == mPositions.end())
|
||||
if (it == mPositions.end())
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -180,70 +164,70 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
|
||||
|
||||
namespace {
|
||||
|
||||
// Binary, signed-integer representation of a single-precision floating-point value.
|
||||
// IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are
|
||||
// ordered the same way when their bits are reinterpreted as sign-magnitude integers."
|
||||
// This allows us to convert all floating-point numbers to signed integers of arbitrary size
|
||||
// and then use them to work with ULPs (Units in the Last Place, for high-precision
|
||||
// computations) or to compare them (integer comparisons are faster than floating-point
|
||||
// comparisons on many platforms).
|
||||
typedef ai_int BinFloat;
|
||||
// Binary, signed-integer representation of a single-precision floating-point value.
|
||||
// IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are
|
||||
// ordered the same way when their bits are reinterpreted as sign-magnitude integers."
|
||||
// This allows us to convert all floating-point numbers to signed integers of arbitrary size
|
||||
// and then use them to work with ULPs (Units in the Last Place, for high-precision
|
||||
// computations) or to compare them (integer comparisons are faster than floating-point
|
||||
// comparisons on many platforms).
|
||||
typedef ai_int BinFloat;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Converts the bit pattern of a floating-point number to its signed integer representation.
|
||||
BinFloat ToBinary( const ai_real & pValue) {
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Converts the bit pattern of a floating-point number to its signed integer representation.
|
||||
BinFloat ToBinary(const ai_real &pValue) {
|
||||
|
||||
// If this assertion fails, signed int is not big enough to store a float on your platform.
|
||||
// Please correct the declaration of BinFloat a few lines above - but do it in a portable,
|
||||
// #ifdef'd manner!
|
||||
static_assert( sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
|
||||
// If this assertion fails, signed int is not big enough to store a float on your platform.
|
||||
// Please correct the declaration of BinFloat a few lines above - but do it in a portable,
|
||||
// #ifdef'd manner!
|
||||
static_assert(sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
|
||||
|
||||
#if defined( _MSC_VER)
|
||||
// If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
|
||||
// code has just become legacy code! Find out the current value of _MSC_VER and modify
|
||||
// the #if above so it evaluates false on the current and all upcoming VC versions (or
|
||||
// on the current platform, if LP64 or LLP64 are still used on other platforms).
|
||||
static_assert( sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
|
||||
#if defined(_MSC_VER)
|
||||
// If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
|
||||
// code has just become legacy code! Find out the current value of _MSC_VER and modify
|
||||
// the #if above so it evaluates false on the current and all upcoming VC versions (or
|
||||
// on the current platform, if LP64 or LLP64 are still used on other platforms).
|
||||
static_assert(sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
|
||||
|
||||
// This works best on Visual C++, but other compilers have their problems with it.
|
||||
const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
|
||||
#else
|
||||
// On many compilers, reinterpreting a float address as an integer causes aliasing
|
||||
// problems. This is an ugly but more or less safe way of doing it.
|
||||
union {
|
||||
ai_real asFloat;
|
||||
BinFloat asBin;
|
||||
} conversion;
|
||||
conversion.asBin = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
|
||||
conversion.asFloat = pValue;
|
||||
const BinFloat binValue = conversion.asBin;
|
||||
#endif
|
||||
// This works best on Visual C++, but other compilers have their problems with it.
|
||||
const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
|
||||
//::memcpy(&binValue, &pValue, sizeof(pValue));
|
||||
//return binValue;
|
||||
#else
|
||||
// On many compilers, reinterpreting a float address as an integer causes aliasing
|
||||
// problems. This is an ugly but more or less safe way of doing it.
|
||||
union {
|
||||
ai_real asFloat;
|
||||
BinFloat asBin;
|
||||
} conversion;
|
||||
conversion.asBin = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
|
||||
conversion.asFloat = pValue;
|
||||
const BinFloat binValue = conversion.asBin;
|
||||
#endif
|
||||
|
||||
// floating-point numbers are of sign-magnitude format, so find out what signed number
|
||||
// representation we must convert negative values to.
|
||||
// See http://en.wikipedia.org/wiki/Signed_number_representations.
|
||||
// floating-point numbers are of sign-magnitude format, so find out what signed number
|
||||
// representation we must convert negative values to.
|
||||
// See http://en.wikipedia.org/wiki/Signed_number_representations.
|
||||
|
||||
// Two's complement?
|
||||
if( (-42 == (~42 + 1)) && (binValue & 0x80000000))
|
||||
return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
|
||||
// One's complement?
|
||||
else if ( (-42 == ~42) && (binValue & 0x80000000))
|
||||
return BinFloat(-0) - binValue;
|
||||
// Sign-magnitude?
|
||||
else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary
|
||||
return binValue;
|
||||
else
|
||||
return binValue;
|
||||
}
|
||||
// Two's complement?
|
||||
const bool DefaultValue = ((-42 == (~42 + 1)) && (binValue & 0x80000000));
|
||||
const bool OneComplement = ((-42 == ~42) && (binValue & 0x80000000));
|
||||
|
||||
if (DefaultValue)
|
||||
return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
|
||||
// One's complement?
|
||||
else if (OneComplement)
|
||||
return BinFloat(-0) - binValue;
|
||||
// Sign-magnitude? -0 = 1000... binary
|
||||
return binValue;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Fills an array with indices of all positions identical to the given position. In opposite to
|
||||
// FindPositions(), not an epsilon is used but a (very low) tolerance of four floating-point units.
|
||||
void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
|
||||
std::vector<unsigned int>& poResults) const
|
||||
{
|
||||
void SpatialSort::FindIdenticalPositions(const aiVector3D &pPosition, std::vector<unsigned int> &poResults) const {
|
||||
// Epsilons have a huge disadvantage: they are of constant precision, while floating-point
|
||||
// values are of log2 precision. If you apply e=0.01 to 100, the epsilon is rather small, but
|
||||
// if you apply it to 0.001, it is enormous.
|
||||
@@ -269,20 +253,19 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
|
||||
|
||||
// Convert the plane distance to its signed integer representation so the ULPs tolerance can be
|
||||
// applied. For some reason, VC won't optimize two calls of the bit pattern conversion.
|
||||
const BinFloat minDistBinary = ToBinary( pPosition * mPlaneNormal) - distanceToleranceInULPs;
|
||||
const BinFloat minDistBinary = ToBinary(pPosition * mPlaneNormal) - distanceToleranceInULPs;
|
||||
const BinFloat maxDistBinary = minDistBinary + 2 * distanceToleranceInULPs;
|
||||
|
||||
// clear the array in this strange fashion because a simple clear() would also deallocate
|
||||
// the array which we want to avoid
|
||||
poResults.resize( 0 );
|
||||
poResults.resize(0);
|
||||
|
||||
// do a binary search for the minimal distance to start the iteration there
|
||||
unsigned int index = (unsigned int)mPositions.size() / 2;
|
||||
unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
|
||||
while( binaryStepSize > 1)
|
||||
{
|
||||
while (binaryStepSize > 1) {
|
||||
// Ugly, but conditional jumps are faster with integers than with floats
|
||||
if( minDistBinary > ToBinary(mPositions[index].mDistance))
|
||||
if (minDistBinary > ToBinary(mPositions[index].mDistance))
|
||||
index += binaryStepSize;
|
||||
else
|
||||
index -= binaryStepSize;
|
||||
@@ -292,20 +275,19 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
|
||||
|
||||
// depending on the direction of the last step we need to single step a bit back or forth
|
||||
// to find the actual beginning element of the range
|
||||
while( index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance) )
|
||||
while (index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance))
|
||||
index--;
|
||||
while( index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance))
|
||||
while (index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance))
|
||||
index++;
|
||||
|
||||
// Now start iterating from there until the first position lays outside of the distance range.
|
||||
// Add all positions inside the distance range within the tolerance to the result array
|
||||
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
|
||||
while( ToBinary(it->mDistance) < maxDistBinary)
|
||||
{
|
||||
if( distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
|
||||
while (ToBinary(it->mDistance) < maxDistBinary) {
|
||||
if (distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
|
||||
poResults.push_back(it->mIndex);
|
||||
++it;
|
||||
if( it == mPositions.end())
|
||||
if (it == mPositions.end())
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -313,22 +295,19 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill, ai_real pRadius) const
|
||||
{
|
||||
fill.resize(mPositions.size(),UINT_MAX);
|
||||
unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int> &fill, ai_real pRadius) const {
|
||||
fill.resize(mPositions.size(), UINT_MAX);
|
||||
ai_real dist, maxDist;
|
||||
|
||||
unsigned int t=0;
|
||||
const ai_real pSquared = pRadius*pRadius;
|
||||
unsigned int t = 0;
|
||||
const ai_real pSquared = pRadius * pRadius;
|
||||
for (size_t i = 0; i < mPositions.size();) {
|
||||
dist = mPositions[i].mPosition * mPlaneNormal;
|
||||
maxDist = dist + pRadius;
|
||||
|
||||
fill[mPositions[i].mIndex] = t;
|
||||
const aiVector3D& oldpos = mPositions[i].mPosition;
|
||||
for (++i; i < fill.size() && mPositions[i].mDistance < maxDist
|
||||
&& (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i)
|
||||
{
|
||||
const aiVector3D &oldpos = mPositions[i].mPosition;
|
||||
for (++i; i < fill.size() && mPositions[i].mDistance < maxDist && (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i) {
|
||||
fill[mPositions[i].mIndex] = t;
|
||||
}
|
||||
++t;
|
||||
@@ -338,7 +317,7 @@ unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill,
|
||||
|
||||
// debug invariant: mPositions[i].mIndex values must range from 0 to mPositions.size()-1
|
||||
for (size_t i = 0; i < fill.size(); ++i) {
|
||||
ai_assert(fill[i]<mPositions.size());
|
||||
ai_assert(fill[i] < mPositions.size());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
@@ -48,70 +47,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assimp/StandardShapes.h>
|
||||
#include <assimp/StringComparison.h>
|
||||
#include <stddef.h>
|
||||
#include <assimp/Defines.h>
|
||||
#include <assimp/StringComparison.h>
|
||||
#include <assimp/mesh.h>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Assimp {
|
||||
|
||||
|
||||
# define ADD_TRIANGLE(n0,n1,n2) \
|
||||
positions.push_back(n0); \
|
||||
positions.push_back(n1); \
|
||||
#define ADD_TRIANGLE(n0, n1, n2) \
|
||||
positions.push_back(n0); \
|
||||
positions.push_back(n1); \
|
||||
positions.push_back(n2);
|
||||
|
||||
# define ADD_PENTAGON(n0,n1,n2,n3,n4) \
|
||||
if (polygons) \
|
||||
{ \
|
||||
#define ADD_PENTAGON(n0, n1, n2, n3, n4) \
|
||||
if (polygons) { \
|
||||
positions.push_back(n0); \
|
||||
positions.push_back(n1); \
|
||||
positions.push_back(n2); \
|
||||
positions.push_back(n3); \
|
||||
positions.push_back(n4); \
|
||||
} else { \
|
||||
ADD_TRIANGLE(n0, n1, n2) \
|
||||
ADD_TRIANGLE(n0, n2, n3) \
|
||||
ADD_TRIANGLE(n0, n3, n4) \
|
||||
}
|
||||
|
||||
#define ADD_QUAD(n0, n1, n2, n3) \
|
||||
if (polygons) { \
|
||||
positions.push_back(n0); \
|
||||
positions.push_back(n1); \
|
||||
positions.push_back(n2); \
|
||||
positions.push_back(n3); \
|
||||
positions.push_back(n4); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ADD_TRIANGLE(n0, n1, n2) \
|
||||
ADD_TRIANGLE(n0, n2, n3) \
|
||||
ADD_TRIANGLE(n0, n3, n4) \
|
||||
}
|
||||
|
||||
# define ADD_QUAD(n0,n1,n2,n3) \
|
||||
if (polygons) \
|
||||
{ \
|
||||
positions.push_back(n0); \
|
||||
positions.push_back(n1); \
|
||||
positions.push_back(n2); \
|
||||
positions.push_back(n3); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
} else { \
|
||||
ADD_TRIANGLE(n0, n1, n2) \
|
||||
ADD_TRIANGLE(n0, n2, n3) \
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Fast subdivision for a mesh whose verts have a magnitude of 1
|
||||
void Subdivide(std::vector<aiVector3D>& positions)
|
||||
{
|
||||
void Subdivide(std::vector<aiVector3D> &positions) {
|
||||
// assume this to be constant - (fixme: must be 1.0? I think so)
|
||||
const ai_real fl1 = positions[0].Length();
|
||||
|
||||
unsigned int origSize = (unsigned int)positions.size();
|
||||
for (unsigned int i = 0 ; i < origSize ; i+=3)
|
||||
{
|
||||
aiVector3D& tv0 = positions[i];
|
||||
aiVector3D& tv1 = positions[i+1];
|
||||
aiVector3D& tv2 = positions[i+2];
|
||||
for (unsigned int i = 0; i < origSize; i += 3) {
|
||||
aiVector3D &tv0 = positions[i];
|
||||
aiVector3D &tv1 = positions[i + 1];
|
||||
aiVector3D &tv2 = positions[i + 2];
|
||||
|
||||
aiVector3D a = tv0, b = tv1, c = tv2;
|
||||
aiVector3D v1 = aiVector3D(a.x+b.x, a.y+b.y, a.z+b.z).Normalize()*fl1;
|
||||
aiVector3D v2 = aiVector3D(a.x+c.x, a.y+c.y, a.z+c.z).Normalize()*fl1;
|
||||
aiVector3D v3 = aiVector3D(b.x+c.x, b.y+c.y, b.z+c.z).Normalize()*fl1;
|
||||
aiVector3D v1 = aiVector3D(a.x + b.x, a.y + b.y, a.z + b.z).Normalize() * fl1;
|
||||
aiVector3D v2 = aiVector3D(a.x + c.x, a.y + c.y, a.z + c.z).Normalize() * fl1;
|
||||
aiVector3D v3 = aiVector3D(b.x + c.x, b.y + c.y, b.z + c.z).Normalize() * fl1;
|
||||
|
||||
tv0 = v1; tv1 = v3; tv2 = v2; // overwrite the original
|
||||
tv0 = v1;
|
||||
tv1 = v3;
|
||||
tv2 = v2; // overwrite the original
|
||||
ADD_TRIANGLE(v1, v2, a);
|
||||
ADD_TRIANGLE(v2, v3, c);
|
||||
ADD_TRIANGLE(v3, v1, b);
|
||||
@@ -120,32 +110,33 @@ void Subdivide(std::vector<aiVector3D>& positions)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Construct a mesh from given vertex positions
|
||||
aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions,
|
||||
unsigned int numIndices)
|
||||
{
|
||||
if (positions.empty() || !numIndices) return NULL;
|
||||
aiMesh *StandardShapes::MakeMesh(const std::vector<aiVector3D> &positions,
|
||||
unsigned int numIndices) {
|
||||
if (positions.empty() || !numIndices) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Determine which kinds of primitives the mesh consists of
|
||||
aiMesh* out = new aiMesh();
|
||||
aiMesh *out = new aiMesh();
|
||||
switch (numIndices) {
|
||||
case 1:
|
||||
out->mPrimitiveTypes = aiPrimitiveType_POINT;
|
||||
break;
|
||||
case 2:
|
||||
out->mPrimitiveTypes = aiPrimitiveType_LINE;
|
||||
break;
|
||||
case 3:
|
||||
out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||
break;
|
||||
default:
|
||||
out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
|
||||
break;
|
||||
case 1:
|
||||
out->mPrimitiveTypes = aiPrimitiveType_POINT;
|
||||
break;
|
||||
case 2:
|
||||
out->mPrimitiveTypes = aiPrimitiveType_LINE;
|
||||
break;
|
||||
case 3:
|
||||
out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||
break;
|
||||
default:
|
||||
out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
|
||||
break;
|
||||
};
|
||||
|
||||
out->mNumFaces = (unsigned int)positions.size() / numIndices;
|
||||
out->mFaces = new aiFace[out->mNumFaces];
|
||||
for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i) {
|
||||
aiFace& f = out->mFaces[i];
|
||||
for (unsigned int i = 0, a = 0; i < out->mNumFaces; ++i) {
|
||||
aiFace &f = out->mFaces[i];
|
||||
f.mNumIndices = numIndices;
|
||||
f.mIndices = new unsigned int[numIndices];
|
||||
for (unsigned int j = 0; i < numIndices; ++i, ++a) {
|
||||
@@ -154,113 +145,108 @@ aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions,
|
||||
}
|
||||
out->mNumVertices = (unsigned int)positions.size();
|
||||
out->mVertices = new aiVector3D[out->mNumVertices];
|
||||
::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D));
|
||||
::memcpy(out->mVertices, &positions[0], out->mNumVertices * sizeof(aiVector3D));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Construct a mesh with a specific shape (callback)
|
||||
aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
|
||||
std::vector<aiVector3D>&))
|
||||
{
|
||||
aiMesh *StandardShapes::MakeMesh(unsigned int (*GenerateFunc)(
|
||||
std::vector<aiVector3D> &)) {
|
||||
std::vector<aiVector3D> temp;
|
||||
unsigned num = (*GenerateFunc)(temp);
|
||||
return MakeMesh(temp,num);
|
||||
return MakeMesh(temp, num);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Construct a mesh with a specific shape (callback)
|
||||
aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
|
||||
std::vector<aiVector3D>&, bool))
|
||||
{
|
||||
aiMesh *StandardShapes::MakeMesh(unsigned int (*GenerateFunc)(
|
||||
std::vector<aiVector3D> &, bool)) {
|
||||
std::vector<aiVector3D> temp;
|
||||
unsigned num = (*GenerateFunc)(temp,true);
|
||||
return MakeMesh(temp,num);
|
||||
unsigned num = (*GenerateFunc)(temp, true);
|
||||
return MakeMesh(temp, num);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Construct a mesh with a specific shape (callback)
|
||||
aiMesh* StandardShapes::MakeMesh (unsigned int num, void (*GenerateFunc)(
|
||||
unsigned int,std::vector<aiVector3D>&))
|
||||
{
|
||||
aiMesh *StandardShapes::MakeMesh(unsigned int num, void (*GenerateFunc)(
|
||||
unsigned int, std::vector<aiVector3D> &)) {
|
||||
std::vector<aiVector3D> temp;
|
||||
(*GenerateFunc)(num,temp);
|
||||
return MakeMesh(temp,3);
|
||||
(*GenerateFunc)(num, temp);
|
||||
return MakeMesh(temp, 3);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build an incosahedron with points.magnitude == 1
|
||||
unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions)
|
||||
{
|
||||
positions.reserve(positions.size()+60);
|
||||
unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D> &positions) {
|
||||
positions.reserve(positions.size() + 60);
|
||||
|
||||
const ai_real t = ( ai_real( 1.0 )+ ai_real( 2.236067977 ) ) / ai_real( 2.0 );
|
||||
const ai_real s = std::sqrt(ai_real(1.0) + t*t);
|
||||
const ai_real t = (ai_real(1.0) + ai_real(2.236067977)) / ai_real(2.0);
|
||||
const ai_real s = std::sqrt(ai_real(1.0) + t * t);
|
||||
|
||||
const aiVector3D v0 = aiVector3D(t,1.0, 0.0)/s;
|
||||
const aiVector3D v1 = aiVector3D(-t,1.0, 0.0)/s;
|
||||
const aiVector3D v2 = aiVector3D(t,-1.0, 0.0)/s;
|
||||
const aiVector3D v3 = aiVector3D(-t,-1.0, 0.0)/s;
|
||||
const aiVector3D v4 = aiVector3D(1.0, 0.0, t)/s;
|
||||
const aiVector3D v5 = aiVector3D(1.0, 0.0,-t)/s;
|
||||
const aiVector3D v6 = aiVector3D(-1.0, 0.0,t)/s;
|
||||
const aiVector3D v7 = aiVector3D(-1.0, 0.0,-t)/s;
|
||||
const aiVector3D v8 = aiVector3D(0.0, t, 1.0)/s;
|
||||
const aiVector3D v9 = aiVector3D(0.0,-t, 1.0)/s;
|
||||
const aiVector3D v10 = aiVector3D(0.0, t,-1.0)/s;
|
||||
const aiVector3D v11 = aiVector3D(0.0,-t,-1.0)/s;
|
||||
const aiVector3D v0 = aiVector3D(t, 1.0, 0.0) / s;
|
||||
const aiVector3D v1 = aiVector3D(-t, 1.0, 0.0) / s;
|
||||
const aiVector3D v2 = aiVector3D(t, -1.0, 0.0) / s;
|
||||
const aiVector3D v3 = aiVector3D(-t, -1.0, 0.0) / s;
|
||||
const aiVector3D v4 = aiVector3D(1.0, 0.0, t) / s;
|
||||
const aiVector3D v5 = aiVector3D(1.0, 0.0, -t) / s;
|
||||
const aiVector3D v6 = aiVector3D(-1.0, 0.0, t) / s;
|
||||
const aiVector3D v7 = aiVector3D(-1.0, 0.0, -t) / s;
|
||||
const aiVector3D v8 = aiVector3D(0.0, t, 1.0) / s;
|
||||
const aiVector3D v9 = aiVector3D(0.0, -t, 1.0) / s;
|
||||
const aiVector3D v10 = aiVector3D(0.0, t, -1.0) / s;
|
||||
const aiVector3D v11 = aiVector3D(0.0, -t, -1.0) / s;
|
||||
|
||||
ADD_TRIANGLE(v0,v8,v4);
|
||||
ADD_TRIANGLE(v0,v5,v10);
|
||||
ADD_TRIANGLE(v2,v4,v9);
|
||||
ADD_TRIANGLE(v2,v11,v5);
|
||||
ADD_TRIANGLE(v0, v8, v4);
|
||||
ADD_TRIANGLE(v0, v5, v10);
|
||||
ADD_TRIANGLE(v2, v4, v9);
|
||||
ADD_TRIANGLE(v2, v11, v5);
|
||||
|
||||
ADD_TRIANGLE(v1,v6,v8);
|
||||
ADD_TRIANGLE(v1,v10,v7);
|
||||
ADD_TRIANGLE(v3,v9,v6);
|
||||
ADD_TRIANGLE(v3,v7,v11);
|
||||
ADD_TRIANGLE(v1, v6, v8);
|
||||
ADD_TRIANGLE(v1, v10, v7);
|
||||
ADD_TRIANGLE(v3, v9, v6);
|
||||
ADD_TRIANGLE(v3, v7, v11);
|
||||
|
||||
ADD_TRIANGLE(v0,v10,v8);
|
||||
ADD_TRIANGLE(v1,v8,v10);
|
||||
ADD_TRIANGLE(v2,v9,v11);
|
||||
ADD_TRIANGLE(v3,v11,v9);
|
||||
ADD_TRIANGLE(v0, v10, v8);
|
||||
ADD_TRIANGLE(v1, v8, v10);
|
||||
ADD_TRIANGLE(v2, v9, v11);
|
||||
ADD_TRIANGLE(v3, v11, v9);
|
||||
|
||||
ADD_TRIANGLE(v4,v2,v0);
|
||||
ADD_TRIANGLE(v5,v0,v2);
|
||||
ADD_TRIANGLE(v6,v1,v3);
|
||||
ADD_TRIANGLE(v7,v3,v1);
|
||||
ADD_TRIANGLE(v4, v2, v0);
|
||||
ADD_TRIANGLE(v5, v0, v2);
|
||||
ADD_TRIANGLE(v6, v1, v3);
|
||||
ADD_TRIANGLE(v7, v3, v1);
|
||||
|
||||
ADD_TRIANGLE(v8,v6,v4);
|
||||
ADD_TRIANGLE(v9,v4,v6);
|
||||
ADD_TRIANGLE(v10,v5,v7);
|
||||
ADD_TRIANGLE(v11,v7,v5);
|
||||
ADD_TRIANGLE(v8, v6, v4);
|
||||
ADD_TRIANGLE(v9, v4, v6);
|
||||
ADD_TRIANGLE(v10, v5, v7);
|
||||
ADD_TRIANGLE(v11, v7, v5);
|
||||
return 3;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build a dodecahedron with points.magnitude == 1
|
||||
unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions,
|
||||
bool polygons /*= false*/)
|
||||
{
|
||||
positions.reserve(positions.size()+108);
|
||||
unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D> &positions,
|
||||
bool polygons /*= false*/) {
|
||||
positions.reserve(positions.size() + 108);
|
||||
|
||||
const ai_real a = ai_real( 1.0 ) / ai_real(1.7320508);
|
||||
const ai_real b = std::sqrt(( ai_real( 3.0 )- ai_real( 2.23606797))/ ai_real( 6.0) );
|
||||
const ai_real c = std::sqrt(( ai_real( 3.0 )+ ai_real( 2.23606797f))/ ai_real( 6.0) );
|
||||
const ai_real a = ai_real(1.0) / ai_real(1.7320508);
|
||||
const ai_real b = std::sqrt((ai_real(3.0) - ai_real(2.23606797)) / ai_real(6.0));
|
||||
const ai_real c = std::sqrt((ai_real(3.0) + ai_real(2.23606797f)) / ai_real(6.0));
|
||||
|
||||
const aiVector3D v0 = aiVector3D(a,a,a);
|
||||
const aiVector3D v1 = aiVector3D(a,a,-a);
|
||||
const aiVector3D v2 = aiVector3D(a,-a,a);
|
||||
const aiVector3D v3 = aiVector3D(a,-a,-a);
|
||||
const aiVector3D v4 = aiVector3D(-a,a,a);
|
||||
const aiVector3D v5 = aiVector3D(-a,a,-a);
|
||||
const aiVector3D v6 = aiVector3D(-a,-a,a);
|
||||
const aiVector3D v7 = aiVector3D(-a,-a,-a);
|
||||
const aiVector3D v8 = aiVector3D(b,c,0.0);
|
||||
const aiVector3D v9 = aiVector3D(-b,c,0.0);
|
||||
const aiVector3D v10 = aiVector3D(b,-c,0.0);
|
||||
const aiVector3D v11 = aiVector3D(-b,-c,0.0);
|
||||
const aiVector3D v0 = aiVector3D(a, a, a);
|
||||
const aiVector3D v1 = aiVector3D(a, a, -a);
|
||||
const aiVector3D v2 = aiVector3D(a, -a, a);
|
||||
const aiVector3D v3 = aiVector3D(a, -a, -a);
|
||||
const aiVector3D v4 = aiVector3D(-a, a, a);
|
||||
const aiVector3D v5 = aiVector3D(-a, a, -a);
|
||||
const aiVector3D v6 = aiVector3D(-a, -a, a);
|
||||
const aiVector3D v7 = aiVector3D(-a, -a, -a);
|
||||
const aiVector3D v8 = aiVector3D(b, c, 0.0);
|
||||
const aiVector3D v9 = aiVector3D(-b, c, 0.0);
|
||||
const aiVector3D v10 = aiVector3D(b, -c, 0.0);
|
||||
const aiVector3D v11 = aiVector3D(-b, -c, 0.0);
|
||||
const aiVector3D v12 = aiVector3D(c, 0.0, b);
|
||||
const aiVector3D v13 = aiVector3D(c, 0.0, -b);
|
||||
const aiVector3D v14 = aiVector3D(-c, 0.0, b);
|
||||
@@ -288,74 +274,71 @@ unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build an octahedron with points.magnitude == 1
|
||||
unsigned int StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions)
|
||||
{
|
||||
positions.reserve(positions.size()+24);
|
||||
unsigned int StandardShapes::MakeOctahedron(std::vector<aiVector3D> &positions) {
|
||||
positions.reserve(positions.size() + 24);
|
||||
|
||||
const aiVector3D v0 = aiVector3D(1.0, 0.0, 0.0) ;
|
||||
const aiVector3D v1 = aiVector3D(-1.0, 0.0, 0.0);
|
||||
const aiVector3D v2 = aiVector3D(0.0, 1.0, 0.0);
|
||||
const aiVector3D v3 = aiVector3D(0.0, -1.0, 0.0);
|
||||
const aiVector3D v4 = aiVector3D(0.0, 0.0, 1.0);
|
||||
const aiVector3D v5 = aiVector3D(0.0, 0.0, -1.0);
|
||||
const aiVector3D v0 = aiVector3D(1.0, 0.0, 0.0);
|
||||
const aiVector3D v1 = aiVector3D(-1.0, 0.0, 0.0);
|
||||
const aiVector3D v2 = aiVector3D(0.0, 1.0, 0.0);
|
||||
const aiVector3D v3 = aiVector3D(0.0, -1.0, 0.0);
|
||||
const aiVector3D v4 = aiVector3D(0.0, 0.0, 1.0);
|
||||
const aiVector3D v5 = aiVector3D(0.0, 0.0, -1.0);
|
||||
|
||||
ADD_TRIANGLE(v4,v0,v2);
|
||||
ADD_TRIANGLE(v4,v2,v1);
|
||||
ADD_TRIANGLE(v4,v1,v3);
|
||||
ADD_TRIANGLE(v4,v3,v0);
|
||||
ADD_TRIANGLE(v4, v0, v2);
|
||||
ADD_TRIANGLE(v4, v2, v1);
|
||||
ADD_TRIANGLE(v4, v1, v3);
|
||||
ADD_TRIANGLE(v4, v3, v0);
|
||||
|
||||
ADD_TRIANGLE(v5,v2,v0);
|
||||
ADD_TRIANGLE(v5,v1,v2);
|
||||
ADD_TRIANGLE(v5,v3,v1);
|
||||
ADD_TRIANGLE(v5,v0,v3);
|
||||
ADD_TRIANGLE(v5, v2, v0);
|
||||
ADD_TRIANGLE(v5, v1, v2);
|
||||
ADD_TRIANGLE(v5, v3, v1);
|
||||
ADD_TRIANGLE(v5, v0, v3);
|
||||
return 3;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build a tetrahedron with points.magnitude == 1
|
||||
unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions)
|
||||
{
|
||||
positions.reserve(positions.size()+9);
|
||||
unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D> &positions) {
|
||||
positions.reserve(positions.size() + 9);
|
||||
|
||||
const ai_real invThree = ai_real( 1.0 ) / ai_real( 3.0 );
|
||||
const ai_real a = ai_real( 1.41421 ) * invThree;
|
||||
const ai_real b = ai_real( 2.4494 ) * invThree;
|
||||
const ai_real invThree = ai_real(1.0) / ai_real(3.0);
|
||||
const ai_real a = ai_real(1.41421) * invThree;
|
||||
const ai_real b = ai_real(2.4494) * invThree;
|
||||
|
||||
const aiVector3D v0 = aiVector3D(0.0,0.0,1.0);
|
||||
const aiVector3D v1 = aiVector3D(2*a,0,-invThree );
|
||||
const aiVector3D v2 = aiVector3D(-a,b,-invThree );
|
||||
const aiVector3D v3 = aiVector3D(-a,-b,-invThree );
|
||||
const aiVector3D v0 = aiVector3D(0.0, 0.0, 1.0);
|
||||
const aiVector3D v1 = aiVector3D(2 * a, 0, -invThree);
|
||||
const aiVector3D v2 = aiVector3D(-a, b, -invThree);
|
||||
const aiVector3D v3 = aiVector3D(-a, -b, -invThree);
|
||||
|
||||
ADD_TRIANGLE(v0,v1,v2);
|
||||
ADD_TRIANGLE(v0,v2,v3);
|
||||
ADD_TRIANGLE(v0,v3,v1);
|
||||
ADD_TRIANGLE(v1,v3,v2);
|
||||
ADD_TRIANGLE(v0, v1, v2);
|
||||
ADD_TRIANGLE(v0, v2, v3);
|
||||
ADD_TRIANGLE(v0, v3, v1);
|
||||
ADD_TRIANGLE(v1, v3, v2);
|
||||
return 3;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build a hexahedron with points.magnitude == 1
|
||||
unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
|
||||
bool polygons /*= false*/)
|
||||
{
|
||||
positions.reserve(positions.size()+36);
|
||||
const ai_real length = ai_real(1.0)/ai_real(1.73205080);
|
||||
unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D> &positions,
|
||||
bool polygons /*= false*/) {
|
||||
positions.reserve(positions.size() + 36);
|
||||
const ai_real length = ai_real(1.0) / ai_real(1.73205080);
|
||||
|
||||
const aiVector3D v0 = aiVector3D(-1.0,-1.0,-1.0)*length;
|
||||
const aiVector3D v1 = aiVector3D(1.0,-1.0,-1.0)*length;
|
||||
const aiVector3D v2 = aiVector3D(1.0,1.0,-1.0)*length;
|
||||
const aiVector3D v3 = aiVector3D(-1.0,1.0,-1.0)*length;
|
||||
const aiVector3D v4 = aiVector3D(-1.0,-1.0,1.0)*length;
|
||||
const aiVector3D v5 = aiVector3D(1.0,-1.0,1.0)*length;
|
||||
const aiVector3D v6 = aiVector3D(1.0,1.0,1.0)*length;
|
||||
const aiVector3D v7 = aiVector3D(-1.0,1.0,1.0)*length;
|
||||
const aiVector3D v0 = aiVector3D(-1.0, -1.0, -1.0) * length;
|
||||
const aiVector3D v1 = aiVector3D(1.0, -1.0, -1.0) * length;
|
||||
const aiVector3D v2 = aiVector3D(1.0, 1.0, -1.0) * length;
|
||||
const aiVector3D v3 = aiVector3D(-1.0, 1.0, -1.0) * length;
|
||||
const aiVector3D v4 = aiVector3D(-1.0, -1.0, 1.0) * length;
|
||||
const aiVector3D v5 = aiVector3D(1.0, -1.0, 1.0) * length;
|
||||
const aiVector3D v6 = aiVector3D(1.0, 1.0, 1.0) * length;
|
||||
const aiVector3D v7 = aiVector3D(-1.0, 1.0, 1.0) * length;
|
||||
|
||||
ADD_QUAD(v0,v3,v2,v1);
|
||||
ADD_QUAD(v0,v1,v5,v4);
|
||||
ADD_QUAD(v0,v4,v7,v3);
|
||||
ADD_QUAD(v6,v5,v1,v2);
|
||||
ADD_QUAD(v6,v2,v3,v7);
|
||||
ADD_QUAD(v6,v7,v4,v5);
|
||||
ADD_QUAD(v0, v3, v2, v1);
|
||||
ADD_QUAD(v0, v1, v5, v4);
|
||||
ADD_QUAD(v0, v4, v7, v3);
|
||||
ADD_QUAD(v6, v5, v1, v2);
|
||||
ADD_QUAD(v6, v2, v3, v7);
|
||||
ADD_QUAD(v6, v7, v4, v5);
|
||||
return (polygons ? 4 : 3);
|
||||
}
|
||||
|
||||
@@ -366,28 +349,26 @@ unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Create a subdivision sphere
|
||||
void StandardShapes::MakeSphere(unsigned int tess,
|
||||
std::vector<aiVector3D>& positions)
|
||||
{
|
||||
void StandardShapes::MakeSphere(unsigned int tess,
|
||||
std::vector<aiVector3D> &positions) {
|
||||
// Reserve enough storage. Every subdivision
|
||||
// splits each triangle in 4, the icosahedron consists of 60 verts
|
||||
positions.reserve(positions.size()+60 * integer_pow(4, tess));
|
||||
positions.reserve(positions.size() + 60 * integer_pow(4, tess));
|
||||
|
||||
// Construct an icosahedron to start with
|
||||
MakeIcosahedron(positions);
|
||||
|
||||
// ... and subdivide it until the requested output
|
||||
// tessellation is reached
|
||||
for (unsigned int i = 0; i<tess;++i)
|
||||
for (unsigned int i = 0; i < tess; ++i)
|
||||
Subdivide(positions);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build a cone
|
||||
void StandardShapes::MakeCone(ai_real height,ai_real radius1,
|
||||
ai_real radius2,unsigned int tess,
|
||||
std::vector<aiVector3D>& positions,bool bOpen /*= false */)
|
||||
{
|
||||
void StandardShapes::MakeCone(ai_real height, ai_real radius1,
|
||||
ai_real radius2, unsigned int tess,
|
||||
std::vector<aiVector3D> &positions, bool bOpen /*= false */) {
|
||||
// Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE
|
||||
if (tess < 3 || !height)
|
||||
return;
|
||||
@@ -401,39 +382,37 @@ void StandardShapes::MakeCone(ai_real height,ai_real radius1,
|
||||
ai_real halfHeight = height / ai_real(2.0);
|
||||
|
||||
// radius1 is always the smaller one
|
||||
if (radius2 > radius1)
|
||||
{
|
||||
std::swap(radius2,radius1);
|
||||
if (radius2 > radius1) {
|
||||
std::swap(radius2, radius1);
|
||||
halfHeight = -halfHeight;
|
||||
}
|
||||
else old = SIZE_MAX;
|
||||
} else
|
||||
old = SIZE_MAX;
|
||||
|
||||
// Use a large epsilon to check whether the cone is pointy
|
||||
if (radius1 < (radius2-radius1)*10e-3)radius1 = 0.0;
|
||||
if (radius1 < (radius2 - radius1) * 10e-3) radius1 = 0.0;
|
||||
|
||||
// We will need 3*2 verts per segment + 3*2 verts per segment
|
||||
// if the cone is closed
|
||||
const unsigned int mem = tess*6 + (!bOpen ? tess*3 * (radius1 ? 2 : 1) : 0);
|
||||
positions.reserve(positions.size () + mem);
|
||||
const unsigned int mem = tess * 6 + (!bOpen ? tess * 3 * (radius1 ? 2 : 1) : 0);
|
||||
positions.reserve(positions.size() + mem);
|
||||
|
||||
// Now construct all segments
|
||||
const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess;
|
||||
const ai_real angle_max = (ai_real)AI_MATH_TWO_PI;
|
||||
const ai_real angle_max = (ai_real)AI_MATH_TWO_PI;
|
||||
|
||||
ai_real s = 1.0; // std::cos(angle == 0);
|
||||
ai_real t = 0.0; // std::sin(angle == 0);
|
||||
|
||||
for (ai_real angle = 0.0; angle < angle_max; )
|
||||
{
|
||||
const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 );
|
||||
const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 );
|
||||
for (ai_real angle = 0.0; angle < angle_max;) {
|
||||
const aiVector3D v1 = aiVector3D(s * radius1, -halfHeight, t * radius1);
|
||||
const aiVector3D v2 = aiVector3D(s * radius2, halfHeight, t * radius2);
|
||||
|
||||
const ai_real next = angle + angle_delta;
|
||||
ai_real s2 = std::cos(next);
|
||||
ai_real t2 = std::sin(next);
|
||||
|
||||
const aiVector3D v3 = aiVector3D (s2 * radius2, halfHeight, t2 * radius2 );
|
||||
const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 );
|
||||
const aiVector3D v3 = aiVector3D(s2 * radius2, halfHeight, t2 * radius2);
|
||||
const aiVector3D v4 = aiVector3D(s2 * radius1, -halfHeight, t2 * radius1);
|
||||
|
||||
positions.push_back(v1);
|
||||
positions.push_back(v2);
|
||||
@@ -442,21 +421,17 @@ void StandardShapes::MakeCone(ai_real height,ai_real radius1,
|
||||
positions.push_back(v1);
|
||||
positions.push_back(v3);
|
||||
|
||||
if (!bOpen)
|
||||
{
|
||||
if (!bOpen) {
|
||||
// generate the end 'cap'
|
||||
positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2 ));
|
||||
positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2 ));
|
||||
positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2));
|
||||
positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2));
|
||||
positions.push_back(aiVector3D(0.0, halfHeight, 0.0));
|
||||
|
||||
|
||||
if (radius1)
|
||||
{
|
||||
if (radius1) {
|
||||
// generate the other end 'cap'
|
||||
positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1 ));
|
||||
positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1 ));
|
||||
positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1));
|
||||
positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1));
|
||||
positions.push_back(aiVector3D(0.0, -halfHeight, 0.0));
|
||||
|
||||
}
|
||||
}
|
||||
s = s2;
|
||||
@@ -465,9 +440,9 @@ void StandardShapes::MakeCone(ai_real height,ai_real radius1,
|
||||
}
|
||||
|
||||
// Need to flip face order?
|
||||
if ( SIZE_MAX != old ) {
|
||||
for (size_t p = old; p < positions.size();p += 3) {
|
||||
std::swap(positions[p],positions[p+1]);
|
||||
if (SIZE_MAX != old) {
|
||||
for (size_t p = old; p < positions.size(); p += 3) {
|
||||
std::swap(positions[p], positions[p + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -475,8 +450,7 @@ void StandardShapes::MakeCone(ai_real height,ai_real radius1,
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build a circle
|
||||
void StandardShapes::MakeCircle(ai_real radius, unsigned int tess,
|
||||
std::vector<aiVector3D>& positions)
|
||||
{
|
||||
std::vector<aiVector3D> &positions) {
|
||||
// Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE
|
||||
if (tess < 3 || !radius)
|
||||
return;
|
||||
@@ -484,24 +458,23 @@ void StandardShapes::MakeCircle(ai_real radius, unsigned int tess,
|
||||
radius = std::fabs(radius);
|
||||
|
||||
// We will need 3 vertices per segment
|
||||
positions.reserve(positions.size()+tess*3);
|
||||
positions.reserve(positions.size() + tess * 3);
|
||||
|
||||
const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess;
|
||||
const ai_real angle_max = (ai_real)AI_MATH_TWO_PI;
|
||||
const ai_real angle_max = (ai_real)AI_MATH_TWO_PI;
|
||||
|
||||
ai_real s = 1.0; // std::cos(angle == 0);
|
||||
ai_real t = 0.0; // std::sin(angle == 0);
|
||||
|
||||
for (ai_real angle = 0.0; angle < angle_max; )
|
||||
{
|
||||
positions.push_back(aiVector3D(s * radius,0.0,t * radius));
|
||||
for (ai_real angle = 0.0; angle < angle_max;) {
|
||||
positions.push_back(aiVector3D(s * radius, 0.0, t * radius));
|
||||
angle += angle_delta;
|
||||
s = std::cos(angle);
|
||||
t = std::sin(angle);
|
||||
positions.push_back(aiVector3D(s * radius,0.0,t * radius));
|
||||
positions.push_back(aiVector3D(s * radius, 0.0, t * radius));
|
||||
|
||||
positions.push_back(aiVector3D(0.0,0.0,0.0));
|
||||
positions.push_back(aiVector3D(0.0, 0.0, 0.0));
|
||||
}
|
||||
}
|
||||
|
||||
} // ! Assimp
|
||||
} // namespace Assimp
|
||||
|
||||
@@ -54,7 +54,7 @@ using namespace Assimp;
|
||||
void mydummy() {}
|
||||
|
||||
#ifdef _WIN32
|
||||
# pragma warning( disable : 4709 )
|
||||
#pragma warning(disable : 4709)
|
||||
#endif // _WIN32
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Subdivider stub class to implement the Catmull-Clarke subdivision algorithm. The
|
||||
@@ -63,24 +63,22 @@ void mydummy() {}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
class CatmullClarkSubdivider : public Subdivider {
|
||||
public:
|
||||
void Subdivide (aiMesh* mesh, aiMesh*& out, unsigned int num, bool discard_input);
|
||||
void Subdivide (aiMesh** smesh, size_t nmesh,
|
||||
aiMesh** out, unsigned int num, bool discard_input);
|
||||
void Subdivide(aiMesh *mesh, aiMesh *&out, unsigned int num, bool discard_input);
|
||||
void Subdivide(aiMesh **smesh, size_t nmesh,
|
||||
aiMesh **out, unsigned int num, bool discard_input);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Intermediate description of an edge between two corners of a polygon*/
|
||||
// ---------------------------------------------------------------------------
|
||||
struct Edge
|
||||
{
|
||||
Edge()
|
||||
: ref(0)
|
||||
{}
|
||||
struct Edge {
|
||||
Edge() :
|
||||
ref(0) {}
|
||||
Vertex edge_point, midpoint;
|
||||
unsigned int ref;
|
||||
};
|
||||
|
||||
typedef std::vector<unsigned int> UIntVector;
|
||||
typedef std::map<uint64_t,Edge> EdgeMap;
|
||||
typedef std::map<uint64_t, Edge> EdgeMap;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Hashing function to derive an index into an #EdgeMap from two given
|
||||
@@ -94,80 +92,72 @@ public:
|
||||
// invariant id0<id1 to identify an edge - else two hashes would refer
|
||||
// to the same edge.
|
||||
// ---------------------------------------------------------------------------
|
||||
#define MAKE_EDGE_HASH(id0,id1) (eh_tmp0__=id0,eh_tmp1__=id1,\
|
||||
(eh_tmp0__<eh_tmp1__?std::swap(eh_tmp0__,eh_tmp1__):mydummy()),(uint64_t)eh_tmp0__^((uint64_t)eh_tmp1__<<32u))
|
||||
#define MAKE_EDGE_HASH(id0, id1) (eh_tmp0__ = id0, eh_tmp1__ = id1, \
|
||||
(eh_tmp0__ < eh_tmp1__ ? std::swap(eh_tmp0__, eh_tmp1__) : mydummy()), (uint64_t)eh_tmp0__ ^ ((uint64_t)eh_tmp1__ << 32u))
|
||||
|
||||
|
||||
#define INIT_EDGE_HASH_TEMPORARIES()\
|
||||
#define INIT_EDGE_HASH_TEMPORARIES() \
|
||||
unsigned int eh_tmp0__, eh_tmp1__;
|
||||
|
||||
private:
|
||||
void InternSubdivide (const aiMesh* const * smesh,
|
||||
size_t nmesh,aiMesh** out, unsigned int num);
|
||||
void InternSubdivide(const aiMesh *const *smesh,
|
||||
size_t nmesh, aiMesh **out, unsigned int num);
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Construct a subdivider of a specific type
|
||||
Subdivider* Subdivider::Create (Algorithm algo)
|
||||
{
|
||||
switch (algo)
|
||||
{
|
||||
Subdivider *Subdivider::Create(Algorithm algo) {
|
||||
switch (algo) {
|
||||
case CATMULL_CLARKE:
|
||||
return new CatmullClarkSubdivider();
|
||||
};
|
||||
|
||||
ai_assert(false);
|
||||
return NULL; // shouldn't happen
|
||||
|
||||
return nullptr; // shouldn't happen
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Call the Catmull Clark subdivision algorithm for one mesh
|
||||
void CatmullClarkSubdivider::Subdivide (
|
||||
aiMesh* mesh,
|
||||
aiMesh*& out,
|
||||
unsigned int num,
|
||||
bool discard_input
|
||||
)
|
||||
{
|
||||
void CatmullClarkSubdivider::Subdivide(
|
||||
aiMesh *mesh,
|
||||
aiMesh *&out,
|
||||
unsigned int num,
|
||||
bool discard_input) {
|
||||
ai_assert(mesh != out);
|
||||
|
||||
Subdivide(&mesh,1,&out,num,discard_input);
|
||||
|
||||
Subdivide(&mesh, 1, &out, num, discard_input);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Call the Catmull Clark subdivision algorithm for multiple meshes
|
||||
void CatmullClarkSubdivider::Subdivide (
|
||||
aiMesh** smesh,
|
||||
size_t nmesh,
|
||||
aiMesh** out,
|
||||
unsigned int num,
|
||||
bool discard_input
|
||||
)
|
||||
{
|
||||
ai_assert( NULL != smesh );
|
||||
ai_assert( NULL != out );
|
||||
void CatmullClarkSubdivider::Subdivide(
|
||||
aiMesh **smesh,
|
||||
size_t nmesh,
|
||||
aiMesh **out,
|
||||
unsigned int num,
|
||||
bool discard_input) {
|
||||
ai_assert(nullptr != smesh);
|
||||
ai_assert(nullptr != out);
|
||||
|
||||
// course, both regions may not overlap
|
||||
ai_assert(smesh<out || smesh+nmesh>out+nmesh);
|
||||
ai_assert(smesh < out || smesh + nmesh > out + nmesh);
|
||||
if (!num) {
|
||||
// No subdivision at all. Need to copy all the meshes .. argh.
|
||||
if (discard_input) {
|
||||
for (size_t s = 0; s < nmesh; ++s) {
|
||||
out[s] = smesh[s];
|
||||
smesh[s] = NULL;
|
||||
smesh[s] = nullptr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for (size_t s = 0; s < nmesh; ++s) {
|
||||
SceneCombiner::Copy(out+s,smesh[s]);
|
||||
SceneCombiner::Copy(out + s, smesh[s]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<aiMesh*> inmeshes;
|
||||
std::vector<aiMesh*> outmeshes;
|
||||
std::vector<aiMesh *> inmeshes;
|
||||
std::vector<aiMesh *> outmeshes;
|
||||
std::vector<unsigned int> maptbl;
|
||||
|
||||
inmeshes.reserve(nmesh);
|
||||
@@ -178,34 +168,35 @@ void CatmullClarkSubdivider::Subdivide (
|
||||
// number of edge cases the subdivider is forced to deal with. Line and
|
||||
// point meshes are simply passed through.
|
||||
for (size_t s = 0; s < nmesh; ++s) {
|
||||
aiMesh* i = smesh[s];
|
||||
aiMesh *i = smesh[s];
|
||||
// FIX - mPrimitiveTypes might not yet be initialized
|
||||
if (i->mPrimitiveTypes && (i->mPrimitiveTypes & (aiPrimitiveType_LINE|aiPrimitiveType_POINT))==i->mPrimitiveTypes) {
|
||||
ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Skipping pure line/point mesh");
|
||||
if (i->mPrimitiveTypes && (i->mPrimitiveTypes & (aiPrimitiveType_LINE | aiPrimitiveType_POINT)) == i->mPrimitiveTypes) {
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("Catmull-Clark Subdivider: Skipping pure line/point mesh");
|
||||
|
||||
if (discard_input) {
|
||||
out[s] = i;
|
||||
smesh[s] = NULL;
|
||||
}
|
||||
else {
|
||||
SceneCombiner::Copy(out+s,i);
|
||||
smesh[s] = nullptr;
|
||||
} else {
|
||||
SceneCombiner::Copy(out + s, i);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
outmeshes.push_back(NULL);inmeshes.push_back(i);
|
||||
outmeshes.push_back(nullptr);
|
||||
inmeshes.push_back(i);
|
||||
maptbl.push_back(static_cast<unsigned int>(s));
|
||||
}
|
||||
|
||||
// Do the actual subdivision on the preallocated storage. InternSubdivide
|
||||
// *always* assumes that enough storage is available, it does not bother
|
||||
// checking any ranges.
|
||||
ai_assert(inmeshes.size()==outmeshes.size()&&inmeshes.size()==maptbl.size());
|
||||
ai_assert(inmeshes.size() == outmeshes.size());
|
||||
ai_assert(inmeshes.size() == maptbl.size());
|
||||
if (inmeshes.empty()) {
|
||||
ASSIMP_LOG_WARN("Catmull-Clark Subdivider: Pure point/line scene, I can't do anything");
|
||||
return;
|
||||
}
|
||||
InternSubdivide(&inmeshes.front(),inmeshes.size(),&outmeshes.front(),num);
|
||||
InternSubdivide(&inmeshes.front(), inmeshes.size(), &outmeshes.front(), num);
|
||||
for (unsigned int i = 0; i < maptbl.size(); ++i) {
|
||||
ai_assert(nullptr != outmeshes[i]);
|
||||
out[maptbl[i]] = outmeshes[i];
|
||||
@@ -229,14 +220,14 @@ void CatmullClarkSubdivider::Subdivide (
|
||||
// in-place unless 'smesh' and 'out' are equal (no strange overlaps or reorderings).
|
||||
// Previous data is replaced/deleted then.
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CatmullClarkSubdivider::InternSubdivide (
|
||||
const aiMesh* const * smesh,
|
||||
size_t nmesh,
|
||||
aiMesh** out,
|
||||
unsigned int num
|
||||
)
|
||||
{
|
||||
ai_assert(NULL != smesh && NULL != out);
|
||||
void CatmullClarkSubdivider::InternSubdivide(
|
||||
const aiMesh *const *smesh,
|
||||
size_t nmesh,
|
||||
aiMesh **out,
|
||||
unsigned int num) {
|
||||
ai_assert(nullptr != smesh);
|
||||
ai_assert(nullptr != out);
|
||||
|
||||
INIT_EDGE_HASH_TEMPORARIES();
|
||||
|
||||
// no subdivision requested or end of recursive refinement
|
||||
@@ -251,25 +242,24 @@ void CatmullClarkSubdivider::InternSubdivide (
|
||||
// 0. Offset table to index all meshes continuously, generate a spatially
|
||||
// sorted representation of all vertices in all meshes.
|
||||
// ---------------------------------------------------------------------
|
||||
typedef std::pair<unsigned int,unsigned int> IntPair;
|
||||
typedef std::pair<unsigned int, unsigned int> IntPair;
|
||||
std::vector<IntPair> moffsets(nmesh);
|
||||
unsigned int totfaces = 0, totvert = 0;
|
||||
for (size_t t = 0; t < nmesh; ++t) {
|
||||
const aiMesh* mesh = smesh[t];
|
||||
const aiMesh *mesh = smesh[t];
|
||||
|
||||
spatial.Append(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D),false);
|
||||
moffsets[t] = IntPair(totfaces,totvert);
|
||||
spatial.Append(mesh->mVertices, mesh->mNumVertices, sizeof(aiVector3D), false);
|
||||
moffsets[t] = IntPair(totfaces, totvert);
|
||||
|
||||
totfaces += mesh->mNumFaces;
|
||||
totvert += mesh->mNumVertices;
|
||||
totvert += mesh->mNumVertices;
|
||||
}
|
||||
|
||||
spatial.Finalize();
|
||||
const unsigned int num_unique = spatial.GenerateMappingTable(maptbl,ComputePositionEpsilon(smesh,nmesh));
|
||||
const unsigned int num_unique = spatial.GenerateMappingTable(maptbl, ComputePositionEpsilon(smesh, nmesh));
|
||||
|
||||
|
||||
#define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second+vert_idx)
|
||||
#define FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first+face_idx)
|
||||
#define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second + vert_idx)
|
||||
#define FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first + face_idx)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// 1. Compute the centroid point for all faces
|
||||
@@ -277,14 +267,13 @@ void CatmullClarkSubdivider::InternSubdivide (
|
||||
std::vector<Vertex> centroids(totfaces);
|
||||
unsigned int nfacesout = 0;
|
||||
for (size_t t = 0, n = 0; t < nmesh; ++t) {
|
||||
const aiMesh* mesh = smesh[t];
|
||||
for (unsigned int i = 0; i < mesh->mNumFaces;++i,++n)
|
||||
{
|
||||
const aiFace& face = mesh->mFaces[i];
|
||||
Vertex& c = centroids[n];
|
||||
const aiMesh *mesh = smesh[t];
|
||||
for (unsigned int i = 0; i < mesh->mNumFaces; ++i, ++n) {
|
||||
const aiFace &face = mesh->mFaces[i];
|
||||
Vertex &c = centroids[n];
|
||||
|
||||
for (unsigned int a = 0; a < face.mNumIndices;++a) {
|
||||
c += Vertex(mesh,face.mIndices[a]);
|
||||
for (unsigned int a = 0; a < face.mNumIndices; ++a) {
|
||||
c += Vertex(mesh, face.mIndices[a]);
|
||||
}
|
||||
|
||||
c /= static_cast<float>(face.mNumIndices);
|
||||
@@ -293,297 +282,297 @@ void CatmullClarkSubdivider::InternSubdivide (
|
||||
}
|
||||
|
||||
{
|
||||
// we want edges to go away before the recursive calls so begin a new scope
|
||||
EdgeMap edges;
|
||||
// we want edges to go away before the recursive calls so begin a new scope
|
||||
EdgeMap edges;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// 2. Set each edge point to be the average of all neighbouring
|
||||
// face points and original points. Every edge exists twice
|
||||
// if there is a neighboring face.
|
||||
// ---------------------------------------------------------------------
|
||||
for (size_t t = 0; t < nmesh; ++t) {
|
||||
const aiMesh* mesh = smesh[t];
|
||||
// ---------------------------------------------------------------------
|
||||
// 2. Set each edge point to be the average of all neighbouring
|
||||
// face points and original points. Every edge exists twice
|
||||
// if there is a neighboring face.
|
||||
// ---------------------------------------------------------------------
|
||||
for (size_t t = 0; t < nmesh; ++t) {
|
||||
const aiMesh *mesh = smesh[t];
|
||||
|
||||
for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
|
||||
const aiFace& face = mesh->mFaces[i];
|
||||
for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
|
||||
const aiFace &face = mesh->mFaces[i];
|
||||
|
||||
for (unsigned int p =0; p< face.mNumIndices; ++p) {
|
||||
const unsigned int id[] = {
|
||||
face.mIndices[p],
|
||||
face.mIndices[p==face.mNumIndices-1?0:p+1]
|
||||
};
|
||||
const unsigned int mp[] = {
|
||||
maptbl[FLATTEN_VERTEX_IDX(t,id[0])],
|
||||
maptbl[FLATTEN_VERTEX_IDX(t,id[1])]
|
||||
};
|
||||
for (unsigned int p = 0; p < face.mNumIndices; ++p) {
|
||||
const unsigned int id[] = {
|
||||
face.mIndices[p],
|
||||
face.mIndices[p == face.mNumIndices - 1 ? 0 : p + 1]
|
||||
};
|
||||
const unsigned int mp[] = {
|
||||
maptbl[FLATTEN_VERTEX_IDX(t, id[0])],
|
||||
maptbl[FLATTEN_VERTEX_IDX(t, id[1])]
|
||||
};
|
||||
|
||||
Edge& e = edges[MAKE_EDGE_HASH(mp[0],mp[1])];
|
||||
e.ref++;
|
||||
if (e.ref<=2) {
|
||||
if (e.ref==1) { // original points (end points) - add only once
|
||||
e.edge_point = e.midpoint = Vertex(mesh,id[0])+Vertex(mesh,id[1]);
|
||||
e.midpoint *= 0.5f;
|
||||
Edge &e = edges[MAKE_EDGE_HASH(mp[0], mp[1])];
|
||||
e.ref++;
|
||||
if (e.ref <= 2) {
|
||||
if (e.ref == 1) { // original points (end points) - add only once
|
||||
e.edge_point = e.midpoint = Vertex(mesh, id[0]) + Vertex(mesh, id[1]);
|
||||
e.midpoint *= 0.5f;
|
||||
}
|
||||
e.edge_point += centroids[FLATTEN_FACE_IDX(t, i)];
|
||||
}
|
||||
e.edge_point += centroids[FLATTEN_FACE_IDX(t,i)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// 3. Normalize edge points
|
||||
// ---------------------------------------------------------------------
|
||||
{unsigned int bad_cnt = 0;
|
||||
for (EdgeMap::iterator it = edges.begin(); it != edges.end(); ++it) {
|
||||
if ((*it).second.ref < 2) {
|
||||
ai_assert((*it).second.ref);
|
||||
++bad_cnt;
|
||||
}
|
||||
(*it).second.edge_point *= 1.f/((*it).second.ref+2.f);
|
||||
}
|
||||
// ---------------------------------------------------------------------
|
||||
// 3. Normalize edge points
|
||||
// ---------------------------------------------------------------------
|
||||
{
|
||||
unsigned int bad_cnt = 0;
|
||||
for (EdgeMap::iterator it = edges.begin(); it != edges.end(); ++it) {
|
||||
if ((*it).second.ref < 2) {
|
||||
ai_assert((*it).second.ref);
|
||||
++bad_cnt;
|
||||
}
|
||||
(*it).second.edge_point *= 1.f / ((*it).second.ref + 2.f);
|
||||
}
|
||||
|
||||
if (bad_cnt) {
|
||||
// Report the number of bad edges. bad edges are referenced by less than two
|
||||
// faces in the mesh. They occur at outer model boundaries in non-closed
|
||||
// shapes.
|
||||
ASSIMP_LOG_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ",
|
||||
static_cast<unsigned int>(edges.size()), " edges). ");
|
||||
}}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// 4. Compute a vertex-face adjacency table. We can't reuse the code
|
||||
// from VertexTriangleAdjacency because we need the table for multiple
|
||||
// meshes and out vertex indices need to be mapped to distinct values
|
||||
// first.
|
||||
// ---------------------------------------------------------------------
|
||||
UIntVector faceadjac(nfacesout), cntadjfac(maptbl.size(),0), ofsadjvec(maptbl.size()+1,0); {
|
||||
for (size_t t = 0; t < nmesh; ++t) {
|
||||
const aiMesh* const minp = smesh[t];
|
||||
for (unsigned int i = 0; i < minp->mNumFaces; ++i) {
|
||||
|
||||
const aiFace& f = minp->mFaces[i];
|
||||
for (unsigned int n = 0; n < f.mNumIndices; ++n) {
|
||||
++cntadjfac[maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]];
|
||||
if (bad_cnt) {
|
||||
// Report the number of bad edges. bad edges are referenced by less than two
|
||||
// faces in the mesh. They occur at outer model boundaries in non-closed
|
||||
// shapes.
|
||||
ASSIMP_LOG_VERBOSE_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ",
|
||||
static_cast<unsigned int>(edges.size()), " edges). ");
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int cur = 0;
|
||||
for (size_t i = 0; i < cntadjfac.size(); ++i) {
|
||||
ofsadjvec[i+1] = cur;
|
||||
cur += cntadjfac[i];
|
||||
}
|
||||
for (size_t t = 0; t < nmesh; ++t) {
|
||||
const aiMesh* const minp = smesh[t];
|
||||
for (unsigned int i = 0; i < minp->mNumFaces; ++i) {
|
||||
|
||||
const aiFace& f = minp->mFaces[i];
|
||||
for (unsigned int n = 0; n < f.mNumIndices; ++n) {
|
||||
faceadjac[ofsadjvec[1+maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]++] = FLATTEN_FACE_IDX(t,i);
|
||||
// ---------------------------------------------------------------------
|
||||
// 4. Compute a vertex-face adjacency table. We can't reuse the code
|
||||
// from VertexTriangleAdjacency because we need the table for multiple
|
||||
// meshes and out vertex indices need to be mapped to distinct values
|
||||
// first.
|
||||
// ---------------------------------------------------------------------
|
||||
UIntVector faceadjac(nfacesout), cntadjfac(maptbl.size(), 0), ofsadjvec(maptbl.size() + 1, 0);
|
||||
{
|
||||
for (size_t t = 0; t < nmesh; ++t) {
|
||||
const aiMesh *const minp = smesh[t];
|
||||
for (unsigned int i = 0; i < minp->mNumFaces; ++i) {
|
||||
|
||||
const aiFace &f = minp->mFaces[i];
|
||||
for (unsigned int n = 0; n < f.mNumIndices; ++n) {
|
||||
++cntadjfac[maptbl[FLATTEN_VERTEX_IDX(t, f.mIndices[n])]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int cur = 0;
|
||||
for (size_t i = 0; i < cntadjfac.size(); ++i) {
|
||||
ofsadjvec[i + 1] = cur;
|
||||
cur += cntadjfac[i];
|
||||
}
|
||||
for (size_t t = 0; t < nmesh; ++t) {
|
||||
const aiMesh *const minp = smesh[t];
|
||||
for (unsigned int i = 0; i < minp->mNumFaces; ++i) {
|
||||
|
||||
// check the other way round for consistency
|
||||
const aiFace &f = minp->mFaces[i];
|
||||
for (unsigned int n = 0; n < f.mNumIndices; ++n) {
|
||||
faceadjac[ofsadjvec[1 + maptbl[FLATTEN_VERTEX_IDX(t, f.mIndices[n])]]++] = FLATTEN_FACE_IDX(t, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check the other way round for consistency
|
||||
#ifdef ASSIMP_BUILD_DEBUG
|
||||
|
||||
for (size_t t = 0; t < ofsadjvec.size()-1; ++t) {
|
||||
for (unsigned int m = 0; m < cntadjfac[t]; ++m) {
|
||||
const unsigned int fidx = faceadjac[ofsadjvec[t]+m];
|
||||
ai_assert(fidx < totfaces);
|
||||
for (size_t n = 1; n < nmesh; ++n) {
|
||||
for (size_t t = 0; t < ofsadjvec.size() - 1; ++t) {
|
||||
for (unsigned int m = 0; m < cntadjfac[t]; ++m) {
|
||||
const unsigned int fidx = faceadjac[ofsadjvec[t] + m];
|
||||
ai_assert(fidx < totfaces);
|
||||
for (size_t n = 1; n < nmesh; ++n) {
|
||||
|
||||
if (moffsets[n].first > fidx) {
|
||||
const aiMesh* msh = smesh[--n];
|
||||
const aiFace& f = msh->mFaces[fidx-moffsets[n].first];
|
||||
if (moffsets[n].first > fidx) {
|
||||
const aiMesh *msh = smesh[--n];
|
||||
const aiFace &f = msh->mFaces[fidx - moffsets[n].first];
|
||||
|
||||
bool haveit = false;
|
||||
for (unsigned int i = 0; i < f.mNumIndices; ++i) {
|
||||
if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) {
|
||||
haveit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ai_assert(haveit);
|
||||
if (!haveit) {
|
||||
ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Index not used");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#define GET_ADJACENT_FACES_AND_CNT(vidx,fstartout,numout) \
|
||||
fstartout = &faceadjac[ofsadjvec[vidx]], numout = cntadjfac[vidx]
|
||||
|
||||
typedef std::pair<bool,Vertex> TouchedOVertex;
|
||||
std::vector<TouchedOVertex > new_points(num_unique,TouchedOVertex(false,Vertex()));
|
||||
// ---------------------------------------------------------------------
|
||||
// 5. Spawn a quad from each face point to the corresponding edge points
|
||||
// the original points being the fourth quad points.
|
||||
// ---------------------------------------------------------------------
|
||||
for (size_t t = 0; t < nmesh; ++t) {
|
||||
const aiMesh* const minp = smesh[t];
|
||||
aiMesh* const mout = out[t] = new aiMesh();
|
||||
|
||||
for (unsigned int a = 0; a < minp->mNumFaces; ++a) {
|
||||
mout->mNumFaces += minp->mFaces[a].mNumIndices;
|
||||
}
|
||||
|
||||
// We need random access to the old face buffer, so reuse is not possible.
|
||||
mout->mFaces = new aiFace[mout->mNumFaces];
|
||||
|
||||
mout->mNumVertices = mout->mNumFaces*4;
|
||||
mout->mVertices = new aiVector3D[mout->mNumVertices];
|
||||
|
||||
// quads only, keep material index
|
||||
mout->mPrimitiveTypes = aiPrimitiveType_POLYGON;
|
||||
mout->mMaterialIndex = minp->mMaterialIndex;
|
||||
|
||||
if (minp->HasNormals()) {
|
||||
mout->mNormals = new aiVector3D[mout->mNumVertices];
|
||||
}
|
||||
|
||||
if (minp->HasTangentsAndBitangents()) {
|
||||
mout->mTangents = new aiVector3D[mout->mNumVertices];
|
||||
mout->mBitangents = new aiVector3D[mout->mNumVertices];
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; minp->HasTextureCoords(i); ++i) {
|
||||
mout->mTextureCoords[i] = new aiVector3D[mout->mNumVertices];
|
||||
mout->mNumUVComponents[i] = minp->mNumUVComponents[i];
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; minp->HasVertexColors(i); ++i) {
|
||||
mout->mColors[i] = new aiColor4D[mout->mNumVertices];
|
||||
}
|
||||
|
||||
mout->mNumVertices = mout->mNumFaces<<2u;
|
||||
for (unsigned int i = 0, v = 0, n = 0; i < minp->mNumFaces;++i) {
|
||||
|
||||
const aiFace& face = minp->mFaces[i];
|
||||
for (unsigned int a = 0; a < face.mNumIndices;++a) {
|
||||
|
||||
// Get a clean new face.
|
||||
aiFace& faceOut = mout->mFaces[n++];
|
||||
faceOut.mIndices = new unsigned int [faceOut.mNumIndices = 4];
|
||||
|
||||
// Spawn a new quadrilateral (ccw winding) for this original point between:
|
||||
// a) face centroid
|
||||
centroids[FLATTEN_FACE_IDX(t,i)].SortBack(mout,faceOut.mIndices[0]=v++);
|
||||
|
||||
// b) adjacent edge on the left, seen from the centroid
|
||||
const Edge& e0 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])],
|
||||
maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a==face.mNumIndices-1?0:a+1])
|
||||
])]; // fixme: replace with mod face.mNumIndices?
|
||||
|
||||
// c) adjacent edge on the right, seen from the centroid
|
||||
const Edge& e1 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])],
|
||||
maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[!a?face.mNumIndices-1:a-1])
|
||||
])]; // fixme: replace with mod face.mNumIndices?
|
||||
|
||||
e0.edge_point.SortBack(mout,faceOut.mIndices[3]=v++);
|
||||
e1.edge_point.SortBack(mout,faceOut.mIndices[1]=v++);
|
||||
|
||||
// d= original point P with distinct index i
|
||||
// F := 0
|
||||
// R := 0
|
||||
// n := 0
|
||||
// for each face f containing i
|
||||
// F := F+ centroid of f
|
||||
// R := R+ midpoint of edge of f from i to i+1
|
||||
// n := n+1
|
||||
//
|
||||
// (F+2R+(n-3)P)/n
|
||||
const unsigned int org = maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])];
|
||||
TouchedOVertex& ov = new_points[org];
|
||||
|
||||
if (!ov.first) {
|
||||
ov.first = true;
|
||||
|
||||
const unsigned int* adj; unsigned int cnt;
|
||||
GET_ADJACENT_FACES_AND_CNT(org,adj,cnt);
|
||||
|
||||
if (cnt < 3) {
|
||||
ov.second = Vertex(minp,face.mIndices[a]);
|
||||
}
|
||||
else {
|
||||
|
||||
Vertex F,R;
|
||||
for (unsigned int o = 0; o < cnt; ++o) {
|
||||
ai_assert(adj[o] < totfaces);
|
||||
F += centroids[adj[o]];
|
||||
|
||||
// adj[0] is a global face index - search the face in the mesh list
|
||||
const aiMesh* mp = NULL;
|
||||
size_t nidx;
|
||||
|
||||
if (adj[o] < moffsets[0].first) {
|
||||
mp = smesh[nidx=0];
|
||||
}
|
||||
else {
|
||||
for (nidx = 1; nidx<= nmesh; ++nidx) {
|
||||
if (nidx == nmesh ||moffsets[nidx].first > adj[o]) {
|
||||
mp = smesh[--nidx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ai_assert(adj[o]-moffsets[nidx].first < mp->mNumFaces);
|
||||
const aiFace& f = mp->mFaces[adj[o]-moffsets[nidx].first];
|
||||
bool haveit = false;
|
||||
|
||||
// find our original point in the face
|
||||
for (unsigned int m = 0; m < f.mNumIndices; ++m) {
|
||||
if (maptbl[FLATTEN_VERTEX_IDX(nidx,f.mIndices[m])] == org) {
|
||||
|
||||
// add *both* edges. this way, we can be sure that we add
|
||||
// *all* adjacent edges to R. In a closed shape, every
|
||||
// edge is added twice - so we simply leave out the
|
||||
// factor 2.f in the amove formula and get the right
|
||||
// result.
|
||||
|
||||
const Edge& c0 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX(
|
||||
nidx,f.mIndices[!m?f.mNumIndices-1:m-1])])];
|
||||
// fixme: replace with mod face.mNumIndices?
|
||||
|
||||
const Edge& c1 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX(
|
||||
nidx,f.mIndices[m==f.mNumIndices-1?0:m+1])])];
|
||||
// fixme: replace with mod face.mNumIndices?
|
||||
R += c0.midpoint+c1.midpoint;
|
||||
|
||||
for (unsigned int i = 0; i < f.mNumIndices; ++i) {
|
||||
if (maptbl[FLATTEN_VERTEX_IDX(n, f.mIndices[i])] == (unsigned int)t) {
|
||||
haveit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// this invariant *must* hold if the vertex-to-face adjacency table is valid
|
||||
ai_assert(haveit);
|
||||
if ( !haveit ) {
|
||||
ASSIMP_LOG_WARN( "OBJ: no name for material library specified." );
|
||||
if (!haveit) {
|
||||
ASSIMP_LOG_VERBOSE_DEBUG("Catmull-Clark Subdivider: Index not used");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const float div = static_cast<float>(cnt), divsq = 1.f/(div*div);
|
||||
ov.second = Vertex(minp,face.mIndices[a])*((div-3.f) / div) + R*divsq + F*divsq;
|
||||
}
|
||||
}
|
||||
ov.second.SortBack(mout,faceOut.mIndices[2]=v++);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#define GET_ADJACENT_FACES_AND_CNT(vidx, fstartout, numout) \
|
||||
fstartout = &faceadjac[ofsadjvec[vidx]], numout = cntadjfac[vidx]
|
||||
|
||||
typedef std::pair<bool, Vertex> TouchedOVertex;
|
||||
std::vector<TouchedOVertex> new_points(num_unique, TouchedOVertex(false, Vertex()));
|
||||
// ---------------------------------------------------------------------
|
||||
// 5. Spawn a quad from each face point to the corresponding edge points
|
||||
// the original points being the fourth quad points.
|
||||
// ---------------------------------------------------------------------
|
||||
for (size_t t = 0; t < nmesh; ++t) {
|
||||
const aiMesh *const minp = smesh[t];
|
||||
aiMesh *const mout = out[t] = new aiMesh();
|
||||
|
||||
for (unsigned int a = 0; a < minp->mNumFaces; ++a) {
|
||||
mout->mNumFaces += minp->mFaces[a].mNumIndices;
|
||||
}
|
||||
|
||||
// We need random access to the old face buffer, so reuse is not possible.
|
||||
mout->mFaces = new aiFace[mout->mNumFaces];
|
||||
|
||||
mout->mNumVertices = mout->mNumFaces * 4;
|
||||
mout->mVertices = new aiVector3D[mout->mNumVertices];
|
||||
|
||||
// quads only, keep material index
|
||||
mout->mPrimitiveTypes = aiPrimitiveType_POLYGON;
|
||||
mout->mMaterialIndex = minp->mMaterialIndex;
|
||||
|
||||
if (minp->HasNormals()) {
|
||||
mout->mNormals = new aiVector3D[mout->mNumVertices];
|
||||
}
|
||||
|
||||
if (minp->HasTangentsAndBitangents()) {
|
||||
mout->mTangents = new aiVector3D[mout->mNumVertices];
|
||||
mout->mBitangents = new aiVector3D[mout->mNumVertices];
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; minp->HasTextureCoords(i); ++i) {
|
||||
mout->mTextureCoords[i] = new aiVector3D[mout->mNumVertices];
|
||||
mout->mNumUVComponents[i] = minp->mNumUVComponents[i];
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; minp->HasVertexColors(i); ++i) {
|
||||
mout->mColors[i] = new aiColor4D[mout->mNumVertices];
|
||||
}
|
||||
|
||||
mout->mNumVertices = mout->mNumFaces << 2u;
|
||||
for (unsigned int i = 0, v = 0, n = 0; i < minp->mNumFaces; ++i) {
|
||||
|
||||
const aiFace &face = minp->mFaces[i];
|
||||
for (unsigned int a = 0; a < face.mNumIndices; ++a) {
|
||||
|
||||
// Get a clean new face.
|
||||
aiFace &faceOut = mout->mFaces[n++];
|
||||
faceOut.mIndices = new unsigned int[faceOut.mNumIndices = 4];
|
||||
|
||||
// Spawn a new quadrilateral (ccw winding) for this original point between:
|
||||
// a) face centroid
|
||||
centroids[FLATTEN_FACE_IDX(t, i)].SortBack(mout, faceOut.mIndices[0] = v++);
|
||||
|
||||
// b) adjacent edge on the left, seen from the centroid
|
||||
const Edge &e0 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[a])],
|
||||
maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[a == face.mNumIndices - 1 ? 0 : a + 1])])]; // fixme: replace with mod face.mNumIndices?
|
||||
|
||||
// c) adjacent edge on the right, seen from the centroid
|
||||
const Edge &e1 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[a])],
|
||||
maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[!a ? face.mNumIndices - 1 : a - 1])])]; // fixme: replace with mod face.mNumIndices?
|
||||
|
||||
e0.edge_point.SortBack(mout, faceOut.mIndices[3] = v++);
|
||||
e1.edge_point.SortBack(mout, faceOut.mIndices[1] = v++);
|
||||
|
||||
// d= original point P with distinct index i
|
||||
// F := 0
|
||||
// R := 0
|
||||
// n := 0
|
||||
// for each face f containing i
|
||||
// F := F+ centroid of f
|
||||
// R := R+ midpoint of edge of f from i to i+1
|
||||
// n := n+1
|
||||
//
|
||||
// (F+2R+(n-3)P)/n
|
||||
const unsigned int org = maptbl[FLATTEN_VERTEX_IDX(t, face.mIndices[a])];
|
||||
TouchedOVertex &ov = new_points[org];
|
||||
|
||||
if (!ov.first) {
|
||||
ov.first = true;
|
||||
|
||||
const unsigned int *adj;
|
||||
unsigned int cnt;
|
||||
GET_ADJACENT_FACES_AND_CNT(org, adj, cnt);
|
||||
|
||||
if (cnt < 3) {
|
||||
ov.second = Vertex(minp, face.mIndices[a]);
|
||||
} else {
|
||||
|
||||
Vertex F, R;
|
||||
for (unsigned int o = 0; o < cnt; ++o) {
|
||||
ai_assert(adj[o] < totfaces);
|
||||
F += centroids[adj[o]];
|
||||
|
||||
// adj[0] is a global face index - search the face in the mesh list
|
||||
const aiMesh *mp = nullptr;
|
||||
size_t nidx;
|
||||
|
||||
if (adj[o] < moffsets[0].first) {
|
||||
mp = smesh[nidx = 0];
|
||||
} else {
|
||||
for (nidx = 1; nidx <= nmesh; ++nidx) {
|
||||
if (nidx == nmesh || moffsets[nidx].first > adj[o]) {
|
||||
mp = smesh[--nidx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ai_assert(adj[o] - moffsets[nidx].first < mp->mNumFaces);
|
||||
const aiFace &f = mp->mFaces[adj[o] - moffsets[nidx].first];
|
||||
bool haveit = false;
|
||||
|
||||
// find our original point in the face
|
||||
for (unsigned int m = 0; m < f.mNumIndices; ++m) {
|
||||
if (maptbl[FLATTEN_VERTEX_IDX(nidx, f.mIndices[m])] == org) {
|
||||
|
||||
// add *both* edges. this way, we can be sure that we add
|
||||
// *all* adjacent edges to R. In a closed shape, every
|
||||
// edge is added twice - so we simply leave out the
|
||||
// factor 2.f in the amove formula and get the right
|
||||
// result.
|
||||
|
||||
const Edge &c0 = edges[MAKE_EDGE_HASH(org, maptbl[FLATTEN_VERTEX_IDX(
|
||||
nidx, f.mIndices[!m ? f.mNumIndices - 1 : m - 1])])];
|
||||
// fixme: replace with mod face.mNumIndices?
|
||||
|
||||
const Edge &c1 = edges[MAKE_EDGE_HASH(org, maptbl[FLATTEN_VERTEX_IDX(
|
||||
nidx, f.mIndices[m == f.mNumIndices - 1 ? 0 : m + 1])])];
|
||||
// fixme: replace with mod face.mNumIndices?
|
||||
R += c0.midpoint + c1.midpoint;
|
||||
|
||||
haveit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// this invariant *must* hold if the vertex-to-face adjacency table is valid
|
||||
ai_assert(haveit);
|
||||
if (!haveit) {
|
||||
ASSIMP_LOG_WARN("OBJ: no name for material library specified.");
|
||||
}
|
||||
}
|
||||
|
||||
const float div = static_cast<float>(cnt), divsq = 1.f / (div * div);
|
||||
ov.second = Vertex(minp, face.mIndices[a]) * ((div - 3.f) / div) + R * divsq + F * divsq;
|
||||
}
|
||||
}
|
||||
ov.second.SortBack(mout, faceOut.mIndices[2] = v++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end of scope for edges, freeing its memory
|
||||
} // end of scope for edges, freeing its memory
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// 7. Apply the next subdivision step.
|
||||
// ---------------------------------------------------------------------
|
||||
if (num != 1) {
|
||||
std::vector<aiMesh*> tmp(nmesh);
|
||||
InternSubdivide (out,nmesh,&tmp.front(),num-1);
|
||||
std::vector<aiMesh *> tmp(nmesh);
|
||||
InternSubdivide(out, nmesh, &tmp.front(), num - 1);
|
||||
for (size_t i = 0; i < nmesh; ++i) {
|
||||
delete out[i];
|
||||
out[i] = tmp[i];
|
||||
|
||||
@@ -41,58 +41,51 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TargetAnimation.h"
|
||||
#include <algorithm>
|
||||
#include <assimp/ai_assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
KeyIterator::KeyIterator(const std::vector<aiVectorKey>* _objPos,
|
||||
const std::vector<aiVectorKey>* _targetObjPos,
|
||||
const aiVector3D* defaultObjectPos /*= NULL*/,
|
||||
const aiVector3D* defaultTargetPos /*= NULL*/)
|
||||
|
||||
: reachedEnd (false)
|
||||
, curTime (-1.)
|
||||
, objPos (_objPos)
|
||||
, targetObjPos (_targetObjPos)
|
||||
, nextObjPos (0)
|
||||
, nextTargetObjPos(0)
|
||||
{
|
||||
KeyIterator::KeyIterator(const std::vector<aiVectorKey> *_objPos,
|
||||
const std::vector<aiVectorKey> *_targetObjPos,
|
||||
const aiVector3D *defaultObjectPos /*= nullptr*/,
|
||||
const aiVector3D *defaultTargetPos /*= nullptr*/) :
|
||||
reachedEnd(false),
|
||||
curTime(-1.),
|
||||
objPos(_objPos),
|
||||
targetObjPos(_targetObjPos),
|
||||
nextObjPos(0),
|
||||
nextTargetObjPos(0) {
|
||||
// Generate default transformation tracks if necessary
|
||||
if (!objPos || objPos->empty())
|
||||
{
|
||||
if (!objPos || objPos->empty()) {
|
||||
defaultObjPos.resize(1);
|
||||
defaultObjPos.front().mTime = 10e10;
|
||||
defaultObjPos.front().mTime = 10e10;
|
||||
|
||||
if (defaultObjectPos)
|
||||
defaultObjPos.front().mValue = *defaultObjectPos;
|
||||
|
||||
objPos = & defaultObjPos;
|
||||
objPos = &defaultObjPos;
|
||||
}
|
||||
if (!targetObjPos || targetObjPos->empty())
|
||||
{
|
||||
if (!targetObjPos || targetObjPos->empty()) {
|
||||
defaultTargetObjPos.resize(1);
|
||||
defaultTargetObjPos.front().mTime = 10e10;
|
||||
defaultTargetObjPos.front().mTime = 10e10;
|
||||
|
||||
if (defaultTargetPos)
|
||||
defaultTargetObjPos.front().mValue = *defaultTargetPos;
|
||||
|
||||
targetObjPos = & defaultTargetObjPos;
|
||||
targetObjPos = &defaultTargetObjPos;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
inline T Interpolate(const T& one, const T& two, ai_real val)
|
||||
{
|
||||
return one + (two-one)*val;
|
||||
inline T Interpolate(const T &one, const T &two, ai_real val) {
|
||||
return one + (two - one) * val;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void KeyIterator::operator ++()
|
||||
{
|
||||
void KeyIterator::operator++() {
|
||||
// If we are already at the end of all keyframes, return
|
||||
if (reachedEnd) {
|
||||
return;
|
||||
@@ -100,113 +93,102 @@ void KeyIterator::operator ++()
|
||||
|
||||
// Now search in all arrays for the time value closest
|
||||
// to our current position on the time line
|
||||
double d0,d1;
|
||||
double d0, d1;
|
||||
|
||||
d0 = objPos->at ( std::min ( nextObjPos, static_cast<unsigned int>(objPos->size()-1)) ).mTime;
|
||||
d1 = targetObjPos->at( std::min ( nextTargetObjPos, static_cast<unsigned int>(targetObjPos->size()-1)) ).mTime;
|
||||
d0 = objPos->at(std::min(nextObjPos, static_cast<unsigned int>(objPos->size() - 1))).mTime;
|
||||
d1 = targetObjPos->at(std::min(nextTargetObjPos, static_cast<unsigned int>(targetObjPos->size() - 1))).mTime;
|
||||
|
||||
// Easiest case - all are identical. In this
|
||||
// case we don't need to interpolate so we can
|
||||
// return earlier
|
||||
if ( d0 == d1 )
|
||||
{
|
||||
if (d0 == d1) {
|
||||
curTime = d0;
|
||||
curPosition = objPos->at(nextObjPos).mValue;
|
||||
curTargetPosition = targetObjPos->at(nextTargetObjPos).mValue;
|
||||
|
||||
// increment counters
|
||||
if (objPos->size() != nextObjPos-1)
|
||||
if (objPos->size() != nextObjPos - 1)
|
||||
++nextObjPos;
|
||||
|
||||
if (targetObjPos->size() != nextTargetObjPos-1)
|
||||
if (targetObjPos->size() != nextTargetObjPos - 1)
|
||||
++nextTargetObjPos;
|
||||
}
|
||||
|
||||
// An object position key is closest to us
|
||||
else if (d0 < d1)
|
||||
{
|
||||
else if (d0 < d1) {
|
||||
curTime = d0;
|
||||
|
||||
// interpolate the other
|
||||
if (1 == targetObjPos->size() || !nextTargetObjPos) {
|
||||
curTargetPosition = targetObjPos->at(0).mValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const aiVectorKey& last = targetObjPos->at(nextTargetObjPos);
|
||||
const aiVectorKey& first = targetObjPos->at(nextTargetObjPos-1);
|
||||
} else {
|
||||
const aiVectorKey &last = targetObjPos->at(nextTargetObjPos);
|
||||
const aiVectorKey &first = targetObjPos->at(nextTargetObjPos - 1);
|
||||
|
||||
curTargetPosition = Interpolate(first.mValue, last.mValue, (ai_real) (
|
||||
(curTime-first.mTime) / (last.mTime-first.mTime) ));
|
||||
curTargetPosition = Interpolate(first.mValue, last.mValue, (ai_real)((curTime - first.mTime) / (last.mTime - first.mTime)));
|
||||
}
|
||||
|
||||
if (objPos->size() != nextObjPos-1)
|
||||
if (objPos->size() != nextObjPos - 1)
|
||||
++nextObjPos;
|
||||
}
|
||||
// A target position key is closest to us
|
||||
else
|
||||
{
|
||||
else {
|
||||
curTime = d1;
|
||||
|
||||
// interpolate the other
|
||||
if (1 == objPos->size() || !nextObjPos) {
|
||||
curPosition = objPos->at(0).mValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const aiVectorKey& last = objPos->at(nextObjPos);
|
||||
const aiVectorKey& first = objPos->at(nextObjPos-1);
|
||||
} else {
|
||||
const aiVectorKey &last = objPos->at(nextObjPos);
|
||||
const aiVectorKey &first = objPos->at(nextObjPos - 1);
|
||||
|
||||
curPosition = Interpolate(first.mValue, last.mValue, (ai_real) (
|
||||
(curTime-first.mTime) / (last.mTime-first.mTime)));
|
||||
curPosition = Interpolate(first.mValue, last.mValue, (ai_real)((curTime - first.mTime) / (last.mTime - first.mTime)));
|
||||
}
|
||||
|
||||
if (targetObjPos->size() != nextTargetObjPos-1)
|
||||
if (targetObjPos->size() != nextTargetObjPos - 1)
|
||||
++nextTargetObjPos;
|
||||
}
|
||||
|
||||
if (nextObjPos >= objPos->size()-1 &&
|
||||
nextTargetObjPos >= targetObjPos->size()-1)
|
||||
{
|
||||
if (nextObjPos >= objPos->size() - 1 &&
|
||||
nextTargetObjPos >= targetObjPos->size() - 1) {
|
||||
// We reached the very last keyframe
|
||||
reachedEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TargetAnimationHelper::SetTargetAnimationChannel (
|
||||
const std::vector<aiVectorKey>* _targetPositions)
|
||||
{
|
||||
ai_assert(NULL != _targetPositions);
|
||||
void TargetAnimationHelper::SetTargetAnimationChannel(
|
||||
const std::vector<aiVectorKey> *_targetPositions) {
|
||||
ai_assert(nullptr != _targetPositions);
|
||||
|
||||
targetPositions = _targetPositions;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TargetAnimationHelper::SetMainAnimationChannel (
|
||||
const std::vector<aiVectorKey>* _objectPositions)
|
||||
{
|
||||
ai_assert(NULL != _objectPositions);
|
||||
void TargetAnimationHelper::SetMainAnimationChannel(
|
||||
const std::vector<aiVectorKey> *_objectPositions) {
|
||||
ai_assert(nullptr != _objectPositions);
|
||||
|
||||
objectPositions = _objectPositions;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TargetAnimationHelper::SetFixedMainAnimationChannel(
|
||||
const aiVector3D& fixed)
|
||||
{
|
||||
objectPositions = NULL; // just to avoid confusion
|
||||
const aiVector3D &fixed) {
|
||||
objectPositions = nullptr; // just to avoid confusion
|
||||
fixedMain = fixed;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TargetAnimationHelper::Process(std::vector<aiVectorKey>* distanceTrack)
|
||||
{
|
||||
ai_assert(NULL != targetPositions && NULL != distanceTrack);
|
||||
void TargetAnimationHelper::Process(std::vector<aiVectorKey> *distanceTrack) {
|
||||
ai_assert(nullptr != targetPositions);
|
||||
ai_assert(nullptr != distanceTrack);
|
||||
|
||||
// TODO: in most cases we won't need the extra array
|
||||
std::vector<aiVectorKey> real;
|
||||
std::vector<aiVectorKey> real;
|
||||
|
||||
std::vector<aiVectorKey>* fill = (distanceTrack == objectPositions ? &real : distanceTrack);
|
||||
fill->reserve(std::max( objectPositions->size(), targetPositions->size() ));
|
||||
std::vector<aiVectorKey> *fill = (distanceTrack == objectPositions ? &real : distanceTrack);
|
||||
fill->reserve(std::max(objectPositions->size(), targetPositions->size()));
|
||||
|
||||
// Iterate through all object keys and interpolate their values if necessary.
|
||||
// Then get the corresponding target position, compute the difference
|
||||
@@ -214,28 +196,24 @@ void TargetAnimationHelper::Process(std::vector<aiVectorKey>* distanceTrack)
|
||||
// that rotates the base vector of the object coordinate system at that time
|
||||
// to match the diff vector.
|
||||
|
||||
KeyIterator iter(objectPositions,targetPositions,&fixedMain);
|
||||
for (;!iter.Finished();++iter)
|
||||
{
|
||||
const aiVector3D& position = iter.GetCurPosition();
|
||||
const aiVector3D& tposition = iter.GetCurTargetPosition();
|
||||
KeyIterator iter(objectPositions, targetPositions, &fixedMain);
|
||||
for (; !iter.Finished(); ++iter) {
|
||||
const aiVector3D &position = iter.GetCurPosition();
|
||||
const aiVector3D &tposition = iter.GetCurTargetPosition();
|
||||
|
||||
// diff vector
|
||||
aiVector3D diff = tposition - position;
|
||||
ai_real f = diff.Length();
|
||||
|
||||
// output distance vector
|
||||
if (f)
|
||||
{
|
||||
if (f) {
|
||||
fill->push_back(aiVectorKey());
|
||||
aiVectorKey& v = fill->back();
|
||||
v.mTime = iter.GetCurTime();
|
||||
aiVectorKey &v = fill->back();
|
||||
v.mTime = iter.GetCurTime();
|
||||
v.mValue = diff;
|
||||
|
||||
diff /= f;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// FIXME: handle this
|
||||
}
|
||||
|
||||
|
||||
@@ -48,9 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <assimp/anim.h>
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Helper class to iterate through all keys in an animation channel.
|
||||
@@ -58,55 +56,44 @@ namespace Assimp {
|
||||
* Missing tracks are interpolated. This is a helper class for
|
||||
* TargetAnimationHelper, but it can be freely used for other purposes.
|
||||
*/
|
||||
class KeyIterator
|
||||
{
|
||||
class KeyIterator {
|
||||
public:
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** Constructs a new key iterator
|
||||
*
|
||||
* @param _objPos Object position track. May be NULL.
|
||||
* @param _targetObjPos Target object position track. May be NULL.
|
||||
* @param _objPos Object position track. May be nullptr.
|
||||
* @param _targetObjPos Target object position track. May be nullptr.
|
||||
* @param defaultObjectPos Default object position to be used if
|
||||
* no animated track is available. May be NULL.
|
||||
* no animated track is available. May be nullptr.
|
||||
* @param defaultTargetPos Default target position to be used if
|
||||
* no animated track is available. May be NULL.
|
||||
* no animated track is available. May be nullptr.
|
||||
*/
|
||||
KeyIterator(const std::vector<aiVectorKey>* _objPos,
|
||||
const std::vector<aiVectorKey>* _targetObjPos,
|
||||
const aiVector3D* defaultObjectPos = NULL,
|
||||
const aiVector3D* defaultTargetPos = NULL);
|
||||
KeyIterator(const std::vector<aiVectorKey> *_objPos,
|
||||
const std::vector<aiVectorKey> *_targetObjPos,
|
||||
const aiVector3D *defaultObjectPos = nullptr,
|
||||
const aiVector3D *defaultTargetPos = nullptr);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** Returns true if all keys have been processed
|
||||
*/
|
||||
bool Finished() const
|
||||
{return reachedEnd;}
|
||||
bool Finished() const { return reachedEnd; }
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** Increment the iterator
|
||||
*/
|
||||
void operator++();
|
||||
inline void operator++(int)
|
||||
{return ++(*this);}
|
||||
|
||||
|
||||
inline void operator++(int) { return ++(*this); }
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** Getters to retrieve the current state of the iterator
|
||||
*/
|
||||
inline const aiVector3D& GetCurPosition() const
|
||||
{return curPosition;}
|
||||
inline const aiVector3D &GetCurPosition() const { return curPosition; }
|
||||
|
||||
inline const aiVector3D& GetCurTargetPosition() const
|
||||
{return curTargetPosition;}
|
||||
inline const aiVector3D &GetCurTargetPosition() const { return curTargetPosition; }
|
||||
|
||||
inline double GetCurTime() const
|
||||
{return curTime;}
|
||||
inline double GetCurTime() const { return curTime; }
|
||||
|
||||
private:
|
||||
|
||||
//! Did we reach the end?
|
||||
bool reachedEnd;
|
||||
|
||||
@@ -116,10 +103,10 @@ private:
|
||||
double curTime;
|
||||
|
||||
//! Input tracks and the next key to process
|
||||
const std::vector<aiVectorKey>* objPos,*targetObjPos;
|
||||
const std::vector<aiVectorKey> *objPos, *targetObjPos;
|
||||
|
||||
unsigned int nextObjPos, nextTargetObjPos;
|
||||
std::vector<aiVectorKey> defaultObjPos,defaultTargetObjPos;
|
||||
std::vector<aiVectorKey> defaultObjPos, defaultTargetObjPos;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -130,15 +117,13 @@ private:
|
||||
* channel for the camera/spot light itself and a separate position
|
||||
* animation channels specifying the position of the camera/spot light
|
||||
* look-at target */
|
||||
class TargetAnimationHelper
|
||||
{
|
||||
class TargetAnimationHelper {
|
||||
public:
|
||||
|
||||
TargetAnimationHelper()
|
||||
: targetPositions (NULL)
|
||||
, objectPositions (NULL)
|
||||
{}
|
||||
|
||||
TargetAnimationHelper() :
|
||||
targetPositions(nullptr),
|
||||
objectPositions(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** Sets the target animation channel
|
||||
@@ -147,37 +132,30 @@ public:
|
||||
* target at a specific position.
|
||||
*
|
||||
* @param targetPositions Translation channel*/
|
||||
void SetTargetAnimationChannel (const
|
||||
std::vector<aiVectorKey>* targetPositions);
|
||||
|
||||
void SetTargetAnimationChannel(const std::vector<aiVectorKey> *targetPositions);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** Sets the main animation channel
|
||||
*
|
||||
* @param objectPositions Translation channel */
|
||||
void SetMainAnimationChannel ( const
|
||||
std::vector<aiVectorKey>* objectPositions);
|
||||
void SetMainAnimationChannel(const std::vector<aiVectorKey> *objectPositions);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** Sets the main animation channel to a fixed value
|
||||
*
|
||||
* @param fixed Fixed value for the main animation channel*/
|
||||
void SetFixedMainAnimationChannel(const aiVector3D& fixed);
|
||||
|
||||
void SetFixedMainAnimationChannel(const aiVector3D &fixed);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
/** Computes final animation channels
|
||||
* @param distanceTrack Receive camera translation keys ... != NULL. */
|
||||
void Process( std::vector<aiVectorKey>* distanceTrack );
|
||||
|
||||
* @param distanceTrack Receive camera translation keys ... != nullptr. */
|
||||
void Process(std::vector<aiVectorKey> *distanceTrack);
|
||||
|
||||
private:
|
||||
|
||||
const std::vector<aiVectorKey>* targetPositions,*objectPositions;
|
||||
const std::vector<aiVectorKey> *targetPositions, *objectPositions;
|
||||
aiVector3D fixedMain;
|
||||
};
|
||||
|
||||
|
||||
} // ! end namespace Assimp
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // include guard
|
||||
|
||||
@@ -52,46 +52,44 @@ using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
|
||||
unsigned int iNumFaces,
|
||||
unsigned int iNumVertices /*= 0*/,
|
||||
bool bComputeNumTriangles /*= false*/)
|
||||
{
|
||||
unsigned int iNumFaces,
|
||||
unsigned int iNumVertices /*= 0*/,
|
||||
bool bComputeNumTriangles /*= false*/) {
|
||||
// compute the number of referenced vertices if it wasn't specified by the caller
|
||||
const aiFace* const pcFaceEnd = pcFaces + iNumFaces;
|
||||
if (0 == iNumVertices) {
|
||||
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
|
||||
ai_assert( nullptr != pcFace );
|
||||
const aiFace *const pcFaceEnd = pcFaces + iNumFaces;
|
||||
if (0 == iNumVertices) {
|
||||
for (aiFace *pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
|
||||
ai_assert(nullptr != pcFace);
|
||||
ai_assert(3 == pcFace->mNumIndices);
|
||||
iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
|
||||
iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
|
||||
iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]);
|
||||
iNumVertices = std::max(iNumVertices, pcFace->mIndices[0]);
|
||||
iNumVertices = std::max(iNumVertices, pcFace->mIndices[1]);
|
||||
iNumVertices = std::max(iNumVertices, pcFace->mIndices[2]);
|
||||
}
|
||||
}
|
||||
|
||||
mNumVertices = iNumVertices + 1;
|
||||
|
||||
unsigned int* pi;
|
||||
unsigned int *pi;
|
||||
|
||||
// allocate storage
|
||||
if (bComputeNumTriangles) {
|
||||
pi = mLiveTriangles = new unsigned int[iNumVertices+1];
|
||||
::memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1));
|
||||
mOffsetTable = new unsigned int[iNumVertices+2]+1;
|
||||
if (bComputeNumTriangles) {
|
||||
pi = mLiveTriangles = new unsigned int[iNumVertices + 1];
|
||||
::memset(mLiveTriangles, 0, sizeof(unsigned int) * (iNumVertices + 1));
|
||||
mOffsetTable = new unsigned int[iNumVertices + 2] + 1;
|
||||
} else {
|
||||
pi = mOffsetTable = new unsigned int[iNumVertices+2]+1;
|
||||
::memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1));
|
||||
mLiveTriangles = NULL; // important, otherwise the d'tor would crash
|
||||
pi = mOffsetTable = new unsigned int[iNumVertices + 2] + 1;
|
||||
::memset(mOffsetTable, 0, sizeof(unsigned int) * (iNumVertices + 1));
|
||||
mLiveTriangles = nullptr; // important, otherwise the d'tor would crash
|
||||
}
|
||||
|
||||
// get a pointer to the end of the buffer
|
||||
unsigned int* piEnd = pi+iNumVertices;
|
||||
unsigned int *piEnd = pi + iNumVertices;
|
||||
*piEnd++ = 0u;
|
||||
|
||||
// first pass: compute the number of faces referencing each vertex
|
||||
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace)
|
||||
{
|
||||
for (aiFace *pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
|
||||
unsigned nind = pcFace->mNumIndices;
|
||||
unsigned * ind = pcFace->mIndices;
|
||||
unsigned *ind = pcFace->mIndices;
|
||||
if (nind > 0) pi[ind[0]]++;
|
||||
if (nind > 1) pi[ind[1]]++;
|
||||
if (nind > 2) pi[ind[2]]++;
|
||||
@@ -99,8 +97,8 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
|
||||
|
||||
// second pass: compute the final offset table
|
||||
unsigned int iSum = 0;
|
||||
unsigned int* piCurOut = this->mOffsetTable;
|
||||
for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut) {
|
||||
unsigned int *piCurOut = this->mOffsetTable;
|
||||
for (unsigned int *piCur = pi; piCur != piEnd; ++piCur, ++piCurOut) {
|
||||
|
||||
unsigned int iLastSum = iSum;
|
||||
iSum += *piCur;
|
||||
@@ -111,9 +109,9 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
|
||||
// third pass: compute the final table
|
||||
this->mAdjacencyTable = new unsigned int[iSum];
|
||||
iSum = 0;
|
||||
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum) {
|
||||
for (aiFace *pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace, ++iSum) {
|
||||
unsigned nind = pcFace->mNumIndices;
|
||||
unsigned * ind = pcFace->mIndices;
|
||||
unsigned *ind = pcFace->mIndices;
|
||||
|
||||
if (nind > 0) mAdjacencyTable[pi[ind[0]]++] = iSum;
|
||||
if (nind > 1) mAdjacencyTable[pi[ind[1]]++] = iSum;
|
||||
@@ -125,8 +123,7 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
|
||||
*mOffsetTable = 0u;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
VertexTriangleAdjacency::~VertexTriangleAdjacency()
|
||||
{
|
||||
VertexTriangleAdjacency::~VertexTriangleAdjacency() {
|
||||
// delete allocated storage
|
||||
delete[] mOffsetTable;
|
||||
delete[] mAdjacencyTable;
|
||||
|
||||
@@ -248,15 +248,18 @@ ZipFile::~ZipFile() {
|
||||
size_t ZipFile::Read(void *pvBuffer, size_t pSize, size_t pCount) {
|
||||
// Should be impossible
|
||||
ai_assert(m_Buffer != nullptr);
|
||||
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
|
||||
ai_assert(nullptr != pvBuffer);
|
||||
ai_assert(0 != pSize);
|
||||
ai_assert(0 != pCount);
|
||||
|
||||
// Clip down to file size
|
||||
size_t byteSize = pSize * pCount;
|
||||
if ((byteSize + m_SeekPtr) > m_Size) {
|
||||
pCount = (m_Size - m_SeekPtr) / pSize;
|
||||
byteSize = pSize * pCount;
|
||||
if (byteSize == 0)
|
||||
if (byteSize == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::memcpy(pvBuffer, m_Buffer.get() + m_SeekPtr, byteSize);
|
||||
|
||||
Reference in New Issue
Block a user