replace NULL and avoid ai_assert with more than 2 tests.

This commit is contained in:
Kim Kulling
2020-06-23 21:05:42 +02:00
659 changed files with 30283 additions and 48642 deletions

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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" );

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.);
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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];

View File

@@ -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
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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);