next fixed warnings
parent
fb3c3048a5
commit
920535165d
|
@ -341,6 +341,20 @@ struct Texture {
|
|||
mTextureBlend = get_qnan();
|
||||
}
|
||||
|
||||
Texture(const Texture &other) :
|
||||
mTextureBlend(other.mTextureBlend),
|
||||
mMapName(other.mMapName),
|
||||
mOffsetU(other.mOffsetU),
|
||||
mOffsetV(other.mOffsetV),
|
||||
mScaleU(other.mScaleU),
|
||||
mScaleV(other.mScaleV),
|
||||
mRotation(other.mRotation),
|
||||
mMapMode(other.mMapMode),
|
||||
bPrivate(other.bPrivate),
|
||||
iUVSrc(other.iUVSrc) {
|
||||
// empty
|
||||
}
|
||||
|
||||
Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)),
|
||||
mMapName(std::move(mMapName)),
|
||||
mOffsetU(std::move(mOffsetU)),
|
||||
|
@ -400,18 +414,29 @@ struct Texture {
|
|||
/** Helper structure representing a 3ds material */
|
||||
struct Material {
|
||||
//! Default constructor has been deleted
|
||||
Material() = delete;
|
||||
|
||||
//! Constructor with explicit name
|
||||
explicit Material(const std::string &name) :
|
||||
mName(name), mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)) // FIX ... we won't want object to be black
|
||||
,
|
||||
Material() :
|
||||
mName(),
|
||||
mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
|
||||
mSpecularExponent(ai_real(0.0)),
|
||||
mShininessStrength(ai_real(1.0)),
|
||||
mShading(Discreet3DS::Gouraud),
|
||||
mTransparency(ai_real(1.0)),
|
||||
mBumpHeight(ai_real(1.0)),
|
||||
mTwoSided(false) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Constructor with explicit name
|
||||
explicit Material(const std::string &name) :
|
||||
mName(name),
|
||||
mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
|
||||
mSpecularExponent(ai_real(0.0)),
|
||||
mShininessStrength(ai_real(1.0)),
|
||||
mShading(Discreet3DS::Gouraud),
|
||||
mTransparency(ai_real(1.0)),
|
||||
mBumpHeight(ai_real(1.0)),
|
||||
mTwoSided(false) {
|
||||
// empty
|
||||
}
|
||||
|
||||
Material(const Material &other) = default;
|
||||
|
@ -468,7 +493,9 @@ struct Material {
|
|||
return *this;
|
||||
}
|
||||
|
||||
virtual ~Material() {}
|
||||
virtual ~Material() {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Name of the material
|
||||
std::string mName;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Open Asset Import Library (assimp)
|
||||
|
@ -6,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,
|
||||
|
@ -80,46 +77,59 @@ static const aiImporterDesc desc = {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// skip to the next token
|
||||
#define AI_AC_SKIP_TO_NEXT_TOKEN() \
|
||||
if (!SkipSpaces(&buffer)) { \
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); \
|
||||
continue; \
|
||||
inline
|
||||
const char *AcSkipToNextToken( const char *buffer ) {
|
||||
if (!SkipSpaces( &buffer )) {
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL");
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// read a string (may be enclosed in double quotation marks). buffer must point to "
|
||||
#define AI_AC_GET_STRING(out) \
|
||||
if (*buffer == '\0') { \
|
||||
throw DeadlyImportError("AC3D: Unexpected EOF in string"); \
|
||||
} \
|
||||
++buffer; \
|
||||
const char *sz = buffer; \
|
||||
while ('\"' != *buffer) { \
|
||||
if (IsLineEnd(*buffer)) { \
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); \
|
||||
out = "ERROR"; \
|
||||
break; \
|
||||
} \
|
||||
++buffer; \
|
||||
} \
|
||||
if (IsLineEnd(*buffer)) continue; \
|
||||
out = std::string(sz, (unsigned int)(buffer - sz)); \
|
||||
inline
|
||||
const char *AcGetString(const char *buffer, std::string &out) {
|
||||
if (*buffer == '\0') {
|
||||
throw DeadlyImportError("AC3D: Unexpected EOF in string");
|
||||
}
|
||||
++buffer;
|
||||
const char *sz = buffer;
|
||||
while ('\"' != *buffer) {
|
||||
if (IsLineEnd(*buffer)) {
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string");
|
||||
out = "ERROR";
|
||||
break;
|
||||
}
|
||||
++buffer;
|
||||
}
|
||||
if (IsLineEnd(*buffer)) {
|
||||
return buffer;
|
||||
}
|
||||
out = std::string(sz, (unsigned int)(buffer - sz));
|
||||
++buffer;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// read 1 to n floats prefixed with an optional predefined identifier
|
||||
#define AI_AC_CHECKED_LOAD_FLOAT_ARRAY(name, name_length, num, out) \
|
||||
AI_AC_SKIP_TO_NEXT_TOKEN(); \
|
||||
if (name_length) { \
|
||||
if (strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { \
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " name " was expected."); \
|
||||
continue; \
|
||||
} \
|
||||
buffer += name_length + 1; \
|
||||
} \
|
||||
for (unsigned int _i = 0; _i < num; ++_i) { \
|
||||
AI_AC_SKIP_TO_NEXT_TOKEN(); \
|
||||
buffer = fast_atoreal_move<float>(buffer, ((float *)out)[_i]); \
|
||||
template<class T>
|
||||
inline
|
||||
const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name, size_t name_length, size_t num, T *out) {
|
||||
AcSkipToNextToken(buffer);
|
||||
if (0 != name_length) {
|
||||
if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) {
|
||||
ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " + std::string( name ) + " was expected.");
|
||||
return buffer;
|
||||
}
|
||||
buffer += name_length + 1;
|
||||
}
|
||||
for (unsigned int _i = 0; _i < num; ++_i) {
|
||||
AcSkipToNextToken(buffer);
|
||||
buffer = fast_atoreal_move<float>(buffer, ((float *)out)[_i]);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -222,7 +232,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
|
|||
return;
|
||||
} else if (TokenMatch(buffer, "name", 4)) {
|
||||
SkipSpaces(&buffer);
|
||||
AI_AC_GET_STRING(obj.name);
|
||||
buffer = AcGetString(buffer, obj.name);
|
||||
|
||||
// If this is a light source, we'll also need to store
|
||||
// the name of the node in it.
|
||||
|
@ -231,21 +241,21 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
|
|||
}
|
||||
} else if (TokenMatch(buffer, "texture", 7)) {
|
||||
SkipSpaces(&buffer);
|
||||
AI_AC_GET_STRING(obj.texture);
|
||||
buffer = AcGetString(buffer, obj.texture);
|
||||
} else if (TokenMatch(buffer, "texrep", 6)) {
|
||||
SkipSpaces(&buffer);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 2, &obj.texRepeat);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texRepeat);
|
||||
if (!obj.texRepeat.x || !obj.texRepeat.y)
|
||||
obj.texRepeat = aiVector2D(1.f, 1.f);
|
||||
} else if (TokenMatch(buffer, "texoff", 6)) {
|
||||
SkipSpaces(&buffer);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 2, &obj.texOffset);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texOffset);
|
||||
} else if (TokenMatch(buffer, "rot", 3)) {
|
||||
SkipSpaces(&buffer);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 9, &obj.rotation);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 9, &obj.rotation);
|
||||
} else if (TokenMatch(buffer, "loc", 3)) {
|
||||
SkipSpaces(&buffer);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 3, &obj.translation);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &obj.translation);
|
||||
} else if (TokenMatch(buffer, "subdiv", 6)) {
|
||||
SkipSpaces(&buffer);
|
||||
obj.subDiv = strtoul10(buffer, &buffer);
|
||||
|
@ -271,7 +281,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
|
|||
}
|
||||
obj.vertices.push_back(aiVector3D());
|
||||
aiVector3D &v = obj.vertices.back();
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 3, &v.x);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &v.x);
|
||||
}
|
||||
} else if (TokenMatch(buffer, "numsurf", 7)) {
|
||||
SkipSpaces(&buffer);
|
||||
|
@ -331,10 +341,9 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
|
|||
|
||||
entry.first = strtoul10(buffer, &buffer);
|
||||
SkipSpaces(&buffer);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 2, &entry.second);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &entry.second);
|
||||
}
|
||||
} else {
|
||||
|
||||
--buffer; // make sure the line is processed a second time
|
||||
break;
|
||||
}
|
||||
|
@ -496,7 +505,9 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
|||
const size_t oldm = meshes.size();
|
||||
for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end();
|
||||
cit != cend; ++cit, ++mat) {
|
||||
if (!(*cit).first) continue;
|
||||
if (!(*cit).first) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// allocate a new aiMesh object
|
||||
*pip++ = (unsigned int)meshes.size();
|
||||
|
@ -541,7 +552,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
|
|||
unsigned int type = (*it).flags & 0xf;
|
||||
if (!type) {
|
||||
aiFace &face = *faces++;
|
||||
if ((face.mNumIndices = (unsigned int)src.entries.size())) {
|
||||
face.mNumIndices = (unsigned int)src.entries.size();
|
||||
if (0 != face.mNumIndices) {
|
||||
face.mIndices = new unsigned int[face.mNumIndices];
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i, ++vertices) {
|
||||
const Surface::SurfaceEntry &entry = src.entries[i];
|
||||
|
@ -726,18 +738,18 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
|
|||
// manually parse the material ... sscanf would use the buldin atof ...
|
||||
// Format: (name) rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f
|
||||
|
||||
AI_AC_SKIP_TO_NEXT_TOKEN();
|
||||
buffer = AcSkipToNextToken(buffer);
|
||||
if ('\"' == *buffer) {
|
||||
AI_AC_GET_STRING(mat.name);
|
||||
AI_AC_SKIP_TO_NEXT_TOKEN();
|
||||
buffer = AcGetString(buffer, mat.name);
|
||||
buffer = AcSkipToNextToken(buffer);
|
||||
}
|
||||
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb", 3, 3, &mat.rgb);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb", 3, 3, &mat.amb);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis", 4, 3, &mat.emis);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec", 4, 3, &mat.spec);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi", 3, 1, &mat.shin);
|
||||
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans", 5, 1, &mat.trans);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "rgb", 3, 3, &mat.rgb);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "amb", 3, 3, &mat.amb);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "emis", 4, 3, &mat.emis);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "spec", 4, 3, &mat.spec);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "shi", 3, 1, &mat.shin);
|
||||
buffer = TAcCheckedLoadFloatArray(buffer, "trans", 5, 1, &mat.trans);
|
||||
}
|
||||
LoadObjectSection(rootObjects);
|
||||
}
|
||||
|
|
|
@ -68,8 +68,6 @@ public:
|
|||
AC3DImporter();
|
||||
~AC3DImporter();
|
||||
|
||||
|
||||
|
||||
// Represents an AC3D material
|
||||
struct Material
|
||||
{
|
||||
|
@ -245,8 +243,6 @@ private:
|
|||
aiMaterial& matDest);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
// points to the next data line
|
||||
const char* buffer;
|
||||
|
||||
|
|
|
@ -429,7 +429,7 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
|
|||
name.length = 1+ ASSIMP_itoa10(name.data+1,static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(conv_data.textures->size()));
|
||||
|
||||
conv_data.textures->push_back(new aiTexture());
|
||||
aiTexture* tex = conv_data.textures->back();
|
||||
aiTexture* curTex = conv_data.textures->back();
|
||||
|
||||
// usually 'img->name' will be the original file name of the embedded textures,
|
||||
// so we can extract the file extension from it.
|
||||
|
@ -439,19 +439,19 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
|
|||
--s;
|
||||
}
|
||||
|
||||
tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
|
||||
tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
|
||||
tex->achFormatHint[2] = s+3>e ? '\0' : ::tolower( s[3] );
|
||||
tex->achFormatHint[3] = '\0';
|
||||
curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower(s[1]);
|
||||
curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower(s[2]);
|
||||
curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower(s[3]);
|
||||
curTex->achFormatHint[3] = '\0';
|
||||
|
||||
// tex->mHeight = 0;
|
||||
tex->mWidth = img->packedfile->size;
|
||||
uint8_t* ch = new uint8_t[tex->mWidth];
|
||||
curTex->mWidth = img->packedfile->size;
|
||||
uint8_t *ch = new uint8_t[curTex->mWidth];
|
||||
|
||||
conv_data.db.reader->SetCurrentPos(static_cast<size_t>( img->packedfile->data->val));
|
||||
conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth);
|
||||
conv_data.db.reader->CopyAndAdvance(ch, curTex->mWidth);
|
||||
|
||||
tex->pcData = reinterpret_cast<aiTexel*>(ch);
|
||||
curTex->pcData = reinterpret_cast<aiTexel *>(ch);
|
||||
|
||||
LogInfo("Reading embedded texture, original file was "+std::string(img->name));
|
||||
} else {
|
||||
|
@ -1078,9 +1078,9 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
const aiFace& f = out->mFaces[out->mNumFaces++];
|
||||
|
||||
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
|
||||
for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
|
||||
vo->x = v->uv[i][0];
|
||||
vo->y = v->uv[i][1];
|
||||
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
|
||||
vo->x = v->uv[j][0];
|
||||
vo->y = v->uv[j][1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1098,8 +1098,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
vo->x = uv.uv[0];
|
||||
vo->y = uv.uv[1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// create textureCoords for every mapped tex
|
||||
for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) {
|
||||
const MLoopUV *tm = itMatTexUvMapping->second[m];
|
||||
|
@ -1139,9 +1138,9 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
const aiFace& f = out->mFaces[out->mNumFaces++];
|
||||
|
||||
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
|
||||
for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
|
||||
vo->x = v->uv[i][0];
|
||||
vo->y = v->uv[i][1];
|
||||
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
|
||||
vo->x = v->uv[j][0];
|
||||
vo->y = v->uv[j][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
|
||||
template <typename T> BlenderModifier* god() {
|
||||
template <typename T>
|
||||
BlenderModifier *god() {
|
||||
return new T();
|
||||
}
|
||||
|
||||
|
@ -71,14 +72,12 @@ static const fpCreateModifier creators[] = {
|
|||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
struct SharedModifierData : ElemBase
|
||||
{
|
||||
struct SharedModifierData : ElemBase {
|
||||
ModifierData modifier;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
|
||||
{
|
||||
void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_data, const Scene &in, const Object &orig_object) {
|
||||
size_t cnt = 0u, ful = 0u;
|
||||
|
||||
// NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
|
||||
|
@ -146,19 +145,15 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin)
|
||||
{
|
||||
bool BlenderModifier_Mirror ::IsActive(const ModifierData &modin) {
|
||||
return modin.type == ModifierData::eModifierType_Mirror;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const ElemBase &orig_modifier,
|
||||
const Scene & /*in*/,
|
||||
const Object& orig_object )
|
||||
{
|
||||
const Object &orig_object) {
|
||||
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
|
||||
const MirrorModifierData &mir = static_cast<const MirrorModifierData &>(orig_modifier);
|
||||
ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
|
||||
|
@ -178,39 +173,46 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
|
|||
|
||||
if (mir.mirror_ob) {
|
||||
const aiVector3D center(mir.mirror_ob->obmat[3][0], mir.mirror_ob->obmat[3][1], mir.mirror_ob->obmat[3][2]);
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mVertices[i];
|
||||
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
|
||||
aiVector3D &v = mesh->mVertices[j];
|
||||
|
||||
v.x = center.x + xs * (center.x - v.x);
|
||||
v.y = center.y + ys * (center.y - v.y);
|
||||
v.z = center.z + zs * (center.z - v.z);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mVertices[i];
|
||||
v.x *= xs;v.y *= ys;v.z *= zs;
|
||||
} else {
|
||||
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
|
||||
aiVector3D &v = mesh->mVertices[j];
|
||||
v.x *= xs;
|
||||
v.y *= ys;
|
||||
v.z *= zs;
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh->mNormals) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mNormals[i];
|
||||
v.x *= xs;v.y *= ys;v.z *= zs;
|
||||
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
|
||||
aiVector3D &v = mesh->mNormals[j];
|
||||
v.x *= xs;
|
||||
v.y *= ys;
|
||||
v.z *= zs;
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh->mTangents) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mTangents[i];
|
||||
v.x *= xs;v.y *= ys;v.z *= zs;
|
||||
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
|
||||
aiVector3D &v = mesh->mTangents[j];
|
||||
v.x *= xs;
|
||||
v.y *= ys;
|
||||
v.z *= zs;
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh->mBitangents) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mBitangents[i];
|
||||
v.x *= xs;v.y *= ys;v.z *= zs;
|
||||
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
|
||||
aiVector3D &v = mesh->mBitangents[j];
|
||||
v.x *= xs;
|
||||
v.y *= ys;
|
||||
v.z *= zs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,16 +220,17 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
|
|||
const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
|
||||
|
||||
for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||
aiVector3D& v = mesh->mTextureCoords[n][i];
|
||||
v.x *= us;v.y *= vs;
|
||||
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
|
||||
aiVector3D &v = mesh->mTextureCoords[n][j];
|
||||
v.x *= us;
|
||||
v.y *= vs;
|
||||
}
|
||||
}
|
||||
|
||||
// Only reverse the winding order if an odd number of axes were mirrored.
|
||||
if (xs * ys * zs < 0) {
|
||||
for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
|
||||
aiFace& face = mesh->mFaces[i];
|
||||
for (unsigned int j = 0; j < mesh->mNumFaces; ++j ) {
|
||||
aiFace &face = mesh->mFaces[j];
|
||||
for (unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
|
||||
std::swap(face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
|
||||
}
|
||||
|
@ -250,23 +253,20 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
|
||||
{
|
||||
bool BlenderModifier_Subdivision ::IsActive(const ModifierData &modin) {
|
||||
return modin.type == ModifierData::eModifierType_Subsurf;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data, const ElemBase &orig_modifier,
|
||||
const Scene & /*in*/,
|
||||
const Object& orig_object )
|
||||
{
|
||||
const Object &orig_object) {
|
||||
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
|
||||
const SubsurfModifierData &mir = static_cast<const SubsurfModifierData &>(orig_modifier);
|
||||
ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
|
||||
|
||||
Subdivider::Algorithm algo;
|
||||
switch (mir.subdivType)
|
||||
{
|
||||
switch (mir.subdivType) {
|
||||
case SubsurfModifierData::TYPE_CatmullClarke:
|
||||
algo = Subdivider::CATMULL_CLARKE;
|
||||
break;
|
||||
|
|
|
@ -1015,8 +1015,8 @@ void COBImporter::ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const
|
|||
// XXX backface culling flag is 0x10 in flags
|
||||
|
||||
// hole?
|
||||
bool hole;
|
||||
if ((hole = (reader.GetI1() & 0x08) != 0)) {
|
||||
bool hole = (reader.GetI1() & 0x08) != 0;
|
||||
if ( hole ) {
|
||||
// XXX Basically this should just work fine - then triangulator
|
||||
// should output properly triangulated data even for polygons
|
||||
// with holes. Test data specific to COB is needed to confirm it.
|
||||
|
|
|
@ -75,10 +75,10 @@ struct Face
|
|||
|
||||
// ------------------
|
||||
/** COB chunk header information */
|
||||
const unsigned int NO_SIZE = UINT_MAX;
|
||||
|
||||
struct ChunkInfo
|
||||
{
|
||||
enum {NO_SIZE=UINT_MAX};
|
||||
|
||||
ChunkInfo ()
|
||||
: id (0)
|
||||
, parent_id (0)
|
||||
|
|
|
@ -714,8 +714,8 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent)
|
|||
else if (IsElement("sampler"))
|
||||
{
|
||||
// read the ID to assign the corresponding collada channel afterwards.
|
||||
int indexID = GetAttribute("id");
|
||||
std::string id = mReader->getAttributeValue(indexID);
|
||||
int indexId = GetAttribute("id");
|
||||
std::string id = mReader->getAttributeValue(indexId);
|
||||
ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
|
||||
|
||||
// have it read into a channel
|
||||
|
@ -3339,13 +3339,12 @@ void ColladaParser::TestClosing(const char* pName) {
|
|||
// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
|
||||
int ColladaParser::GetAttribute(const char* pAttr) const {
|
||||
int index = TestAttribute(pAttr);
|
||||
if (index != -1) {
|
||||
return index;
|
||||
if (index == -1) {
|
||||
ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
|
||||
}
|
||||
|
||||
// attribute not found -> throw an exception
|
||||
ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
|
||||
return -1;
|
||||
return index;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -428,8 +428,8 @@ void Document::ReadPropertyTemplates()
|
|||
const ElementCollection otypes = sdefs.GetCollection("ObjectType");
|
||||
for(ElementMap::const_iterator it = otypes.first; it != otypes.second; ++it) {
|
||||
const Element& el = *(*it).second;
|
||||
const Scope* sc = el.Compound();
|
||||
if(!sc) {
|
||||
const Scope* curSc = el.Compound();
|
||||
if (!curSc) {
|
||||
DOMWarning("expected nested scope in ObjectType, ignoring",&el);
|
||||
continue;
|
||||
}
|
||||
|
@ -442,24 +442,24 @@ void Document::ReadPropertyTemplates()
|
|||
|
||||
const std::string& oname = ParseTokenAsString(*tok[0]);
|
||||
|
||||
const ElementCollection templs = sc->GetCollection("PropertyTemplate");
|
||||
for(ElementMap::const_iterator it = templs.first; it != templs.second; ++it) {
|
||||
const Element& el = *(*it).second;
|
||||
const Scope* sc = el.Compound();
|
||||
if(!sc) {
|
||||
const ElementCollection templs = curSc->GetCollection("PropertyTemplate");
|
||||
for (ElementMap::const_iterator elemIt = templs.first; elemIt != templs.second; ++elemIt) {
|
||||
const Element &innerEl = *(*elemIt).second;
|
||||
const Scope *innerSc = innerEl.Compound();
|
||||
if (!innerSc) {
|
||||
DOMWarning("expected nested scope in PropertyTemplate, ignoring",&el);
|
||||
continue;
|
||||
}
|
||||
|
||||
const TokenList& tok = el.Tokens();
|
||||
if(tok.empty()) {
|
||||
const TokenList &curTok = innerEl.Tokens();
|
||||
if (curTok.empty()) {
|
||||
DOMWarning("expected name for PropertyTemplate element, ignoring",&el);
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string& pname = ParseTokenAsString(*tok[0]);
|
||||
const std::string &pname = ParseTokenAsString(*curTok[0]);
|
||||
|
||||
const Element* Properties70 = (*sc)["Properties70"];
|
||||
const Element *Properties70 = (*innerSc)["Properties70"];
|
||||
if(Properties70) {
|
||||
std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>(
|
||||
*Properties70,std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable*>(NULL))
|
||||
|
@ -529,8 +529,8 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
|
|||
animationStacksResolved.reserve(animationStacks.size());
|
||||
for(uint64_t id : animationStacks) {
|
||||
LazyObject* const lazy = GetObject(id);
|
||||
const AnimationStack* stack;
|
||||
if(!lazy || !(stack = lazy->Get<AnimationStack>())) {
|
||||
const AnimationStack *stack = lazy->Get<AnimationStack>();
|
||||
if(!lazy || nullptr == stack ) {
|
||||
DOMWarning("failed to read AnimationStack object");
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
* @brief Implementation of the Industry Foundation Classes loader.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
|
||||
|
||||
#include <iterator>
|
||||
|
@ -59,24 +58,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#include "IFCLoader.h"
|
||||
#include "../STEPParser/STEPFileReader.h"
|
||||
#include "IFCLoader.h"
|
||||
|
||||
#include "IFCUtil.h"
|
||||
|
||||
#include <assimp/MemoryIOWrapper.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/importerdesc.h>
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
template<> const char* LogFunctions<IFCImporter>::Prefix()
|
||||
{
|
||||
template <>
|
||||
const char *LogFunctions<IFCImporter>::Prefix() {
|
||||
static auto prefix = "IFC: ";
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
} // namespace Assimp
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Formatter;
|
||||
|
@ -98,7 +96,6 @@ using namespace Assimp::IFC;
|
|||
|
||||
namespace {
|
||||
|
||||
|
||||
// forward declarations
|
||||
void SetUnits(ConversionData &conv);
|
||||
void SetCoordinateSpace(ConversionData &conv);
|
||||
|
@ -106,7 +103,7 @@ void ProcessSpatialStructures(ConversionData& conv);
|
|||
void MakeTreeRelative(ConversionData &conv);
|
||||
void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &conv);
|
||||
|
||||
} // anon
|
||||
} // namespace
|
||||
|
||||
static const aiImporterDesc desc = {
|
||||
"Industry Foundation Classes (IFC) Importer",
|
||||
|
@ -121,22 +118,18 @@ static const aiImporterDesc desc = {
|
|||
"ifc ifczip stp"
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
IFCImporter::IFCImporter()
|
||||
{}
|
||||
IFCImporter::IFCImporter() {}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
IFCImporter::~IFCImporter()
|
||||
{
|
||||
IFCImporter::~IFCImporter() {
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
||||
{
|
||||
bool IFCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
|
||||
const std::string &extension = GetExtension(pFile);
|
||||
if (extension == "ifc" || extension == "ifczip") {
|
||||
return true;
|
||||
|
@ -153,15 +146,13 @@ bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// List all extensions handled by this loader
|
||||
const aiImporterDesc* IFCImporter::GetInfo () const
|
||||
{
|
||||
const aiImporterDesc *IFCImporter::GetInfo() const {
|
||||
return &desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties for the loader
|
||||
void IFCImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
void IFCImporter::SetupProperties(const Importer *pImp) {
|
||||
settings.skipSpaceRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS, true);
|
||||
settings.useCustomTriangulation = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION, true);
|
||||
settings.conicSamplingAngle = std::min(std::max((float)pImp->GetPropertyFloat(AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE, AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE), 5.0f), 120.0f);
|
||||
|
@ -169,17 +160,14 @@ void IFCImporter::SetupProperties(const Importer* pImp)
|
|||
settings.skipAnnotations = true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
|
||||
{
|
||||
void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
|
||||
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile));
|
||||
if (!stream) {
|
||||
ThrowException("Could not open file for reading");
|
||||
}
|
||||
|
||||
|
||||
// if this is a ifczip file, decompress its contents first
|
||||
if (GetExtension(pFile) == "ifczip") {
|
||||
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
|
||||
|
@ -225,22 +213,19 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
|||
free(buffer);
|
||||
} while (read > 0);
|
||||
size_t filesize = fileInfo.uncompressed_size;
|
||||
if (total == 0 || size_t(total) != filesize)
|
||||
{
|
||||
if (total == 0 || size_t(total) != filesize) {
|
||||
delete[] buff;
|
||||
ThrowException("Failed to decompress IFC ZIP file");
|
||||
}
|
||||
unzCloseCurrentFile(zip);
|
||||
stream.reset(new MemoryIOStream(buff, fileInfo.uncompressed_size, true));
|
||||
break;
|
||||
|
||||
if (unzGoToNextFile(zip) == UNZ_END_OF_LIST_OF_FILE) {
|
||||
ThrowException("Found no IFC file member in IFCZIP file (1)");
|
||||
}
|
||||
break;
|
||||
|
||||
} while (true);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ThrowException("Found no IFC file member in IFCZIP file (2)");
|
||||
}
|
||||
|
||||
|
@ -336,10 +321,8 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
|||
|
||||
namespace {
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertUnit(const Schema_2x3::IfcNamedUnit& unit,ConversionData& conv)
|
||||
{
|
||||
void ConvertUnit(const Schema_2x3::IfcNamedUnit &unit, ConversionData &conv) {
|
||||
if (const Schema_2x3::IfcSIUnit *const si = unit.ToPtr<Schema_2x3::IfcSIUnit>()) {
|
||||
if (si->UnitType == "LENGTHUNIT") {
|
||||
conv.len_scale = si->Prefix ? ConvertSIPrefix(si->Prefix) : 1.f;
|
||||
|
@ -350,15 +333,13 @@ void ConvertUnit(const Schema_2x3::IfcNamedUnit& unit,ConversionData& conv)
|
|||
IFCImporter::LogWarn("expected base unit for angles to be radian");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(const Schema_2x3::IfcConversionBasedUnit* const convu = unit.ToPtr<Schema_2x3::IfcConversionBasedUnit>()) {
|
||||
} else if (const Schema_2x3::IfcConversionBasedUnit *const convu = unit.ToPtr<Schema_2x3::IfcConversionBasedUnit>()) {
|
||||
if (convu->UnitType == "PLANEANGLEUNIT") {
|
||||
try {
|
||||
conv.angle_scale = convu->ConversionFactor->ValueComponent->To<::Assimp::STEP::EXPRESS::REAL>();
|
||||
ConvertUnit(*convu->ConversionFactor->UnitComponent, conv);
|
||||
IFCImporter::LogDebug("got units used for angles");
|
||||
}
|
||||
catch(std::bad_cast&) {
|
||||
} catch (std::bad_cast &) {
|
||||
IFCImporter::LogError("skipping unknown IfcConversionBasedUnit.ValueComponent entry - expected REAL");
|
||||
}
|
||||
}
|
||||
|
@ -366,8 +347,7 @@ void ConvertUnit(const Schema_2x3::IfcNamedUnit& unit,ConversionData& conv)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType& dt,ConversionData& conv)
|
||||
{
|
||||
void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &conv) {
|
||||
try {
|
||||
const ::Assimp::STEP::EXPRESS::ENTITY &e = dt.To<::Assimp::STEP::EXPRESS::ENTITY>();
|
||||
|
||||
|
@ -377,26 +357,22 @@ void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType& dt,ConversionData& con
|
|||
}
|
||||
|
||||
ConvertUnit(unit, conv);
|
||||
}
|
||||
catch(std::bad_cast&) {
|
||||
} catch (std::bad_cast &) {
|
||||
// not entity, somehow
|
||||
IFCImporter::LogError("skipping unknown IfcUnit entry - expected entity");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SetUnits(ConversionData& conv)
|
||||
{
|
||||
void SetUnits(ConversionData &conv) {
|
||||
// see if we can determine the coordinate space used to express.
|
||||
for (size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i) {
|
||||
ConvertUnit(*conv.proj.UnitsInContext->Units[i], conv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SetCoordinateSpace(ConversionData& conv)
|
||||
{
|
||||
void SetCoordinateSpace(ConversionData &conv) {
|
||||
const Schema_2x3::IfcRepresentationContext *fav = NULL;
|
||||
for (const Schema_2x3::IfcRepresentationContext &v : conv.proj.RepresentationContexts) {
|
||||
fav = &v;
|
||||
|
@ -413,10 +389,8 @@ void SetCoordinateSpace(ConversionData& conv)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ResolveObjectPlacement(aiMatrix4x4& m, const Schema_2x3::IfcObjectPlacement& place, ConversionData& conv)
|
||||
{
|
||||
void ResolveObjectPlacement(aiMatrix4x4 &m, const Schema_2x3::IfcObjectPlacement &place, ConversionData &conv) {
|
||||
if (const Schema_2x3::IfcLocalPlacement *const local = place.ToPtr<Schema_2x3::IfcLocalPlacement>()) {
|
||||
IfcMatrix4 tmp;
|
||||
ConvertAxisPlacement(tmp, *local->RelativePlacement, conv);
|
||||
|
@ -424,19 +398,17 @@ void ResolveObjectPlacement(aiMatrix4x4& m, const Schema_2x3::IfcObjectPlacement
|
|||
m = static_cast<aiMatrix4x4>(tmp);
|
||||
|
||||
if (local->PlacementRelTo) {
|
||||
aiMatrix4x4 tmp;
|
||||
ResolveObjectPlacement(tmp,local->PlacementRelTo.Get(),conv);
|
||||
m = tmp * m;
|
||||
aiMatrix4x4 tmpM;
|
||||
ResolveObjectPlacement(tmpM, local->PlacementRelTo.Get(), conv);
|
||||
m = tmpM * m;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
IFCImporter::LogWarn("skipping unknown IfcObjectPlacement entity, type is " + place.GetClassName());
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool ProcessMappedItem(const Schema_2x3::IfcMappedItem& mapped, aiNode* nd_src, std::vector< aiNode* >& subnodes_src, unsigned int matid, ConversionData& conv)
|
||||
{
|
||||
bool ProcessMappedItem(const Schema_2x3::IfcMappedItem &mapped, aiNode *nd_src, std::vector<aiNode *> &subnodes_src, unsigned int matid, ConversionData &conv) {
|
||||
// insert a custom node here, the carthesian transform operator is simply a conventional transformation matrix
|
||||
std::unique_ptr<aiNode> nd(new aiNode());
|
||||
nd->mName.Set("IfcMappedItem");
|
||||
|
@ -467,8 +439,8 @@ bool ProcessMappedItem(const Schema_2x3::IfcMappedItem& mapped, aiNode* nd_src,
|
|||
for (const Schema_2x3::IfcRepresentationItem &item : repr.Items) {
|
||||
if (!ProcessRepresentationItem(item, localmatid, meshes, conv)) {
|
||||
IFCImporter::LogWarn("skipping mapped entity of type " + item.GetClassName() + ", no representations could be generated");
|
||||
}
|
||||
else got = true;
|
||||
} else
|
||||
got = true;
|
||||
}
|
||||
|
||||
if (!got) {
|
||||
|
@ -504,7 +476,6 @@ struct RateRepresentationPredicate {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const std::string &name = r->RepresentationIdentifier.Get();
|
||||
if (name == "MappedRepresentation") {
|
||||
if (!r->Items.empty()) {
|
||||
|
@ -557,8 +528,7 @@ struct RateRepresentationPredicate {
|
|||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ProcessProductRepresentation(const Schema_2x3::IfcProduct& el, aiNode* nd, std::vector< aiNode* >& subnodes, ConversionData& conv)
|
||||
{
|
||||
void ProcessProductRepresentation(const Schema_2x3::IfcProduct &el, aiNode *nd, std::vector<aiNode *> &subnodes, ConversionData &conv) {
|
||||
if (!el.Representation) {
|
||||
return;
|
||||
}
|
||||
|
@ -581,8 +551,7 @@ void ProcessProductRepresentation(const Schema_2x3::IfcProduct& el, aiNode* nd,
|
|||
for (const Schema_2x3::IfcRepresentationItem &item : repr->Items) {
|
||||
if (const Schema_2x3::IfcMappedItem *const geo = item.ToPtr<Schema_2x3::IfcMappedItem>()) {
|
||||
res = ProcessMappedItem(*geo, nd, subnodes, matid, conv) || res;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res = ProcessRepresentationItem(item, matid, meshes, conv) || res;
|
||||
}
|
||||
}
|
||||
|
@ -607,22 +576,19 @@ void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::Ifc
|
|||
if (const ::Assimp::STEP::EXPRESS::STRING *str = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::STRING>()) {
|
||||
std::string value = static_cast<std::string>(*str);
|
||||
properties[key] = value;
|
||||
}
|
||||
else if (const ::Assimp::STEP::EXPRESS::REAL* val = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) {
|
||||
float value = static_cast<float>(*val);
|
||||
} else if (const ::Assimp::STEP::EXPRESS::REAL *val1 = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) {
|
||||
float value = static_cast<float>(*val1);
|
||||
std::stringstream s;
|
||||
s << value;
|
||||
properties[key] = s.str();
|
||||
}
|
||||
else if (const ::Assimp::STEP::EXPRESS::INTEGER* val = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::INTEGER>()) {
|
||||
int64_t value = static_cast<int64_t>(*val);
|
||||
} else if (const ::Assimp::STEP::EXPRESS::INTEGER *val2 = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::INTEGER>()) {
|
||||
int64_t curValue = static_cast<int64_t>(*val2);
|
||||
std::stringstream s;
|
||||
s << value;
|
||||
s << curValue;
|
||||
properties[key] = s.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (const Schema_2x3::IfcPropertyListValue* const listValue = property.ToPtr<Schema_2x3::IfcPropertyListValue>()) {
|
||||
} else if (const Schema_2x3::IfcPropertyListValue *const listValue = property.ToPtr<Schema_2x3::IfcPropertyListValue>()) {
|
||||
std::stringstream ss;
|
||||
ss << "[";
|
||||
unsigned index = 0;
|
||||
|
@ -631,13 +597,11 @@ void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::Ifc
|
|||
if (const ::Assimp::STEP::EXPRESS::STRING *str = v->ToPtr<::Assimp::STEP::EXPRESS::STRING>()) {
|
||||
std::string value = static_cast<std::string>(*str);
|
||||
ss << "'" << value << "'";
|
||||
}
|
||||
else if (const ::Assimp::STEP::EXPRESS::REAL* val = v->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) {
|
||||
float value = static_cast<float>(*val);
|
||||
} else if (const ::Assimp::STEP::EXPRESS::REAL *val1 = v->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) {
|
||||
float value = static_cast<float>(*val1);
|
||||
ss << value;
|
||||
}
|
||||
else if (const ::Assimp::STEP::EXPRESS::INTEGER* val = v->ToPtr<::Assimp::STEP::EXPRESS::INTEGER>()) {
|
||||
int64_t value = static_cast<int64_t>(*val);
|
||||
} else if (const ::Assimp::STEP::EXPRESS::INTEGER *val2 = v->ToPtr<::Assimp::STEP::EXPRESS::INTEGER>()) {
|
||||
int64_t value = static_cast<int64_t>(*val2);
|
||||
ss << value;
|
||||
}
|
||||
if (index + 1 < listValue->ListValues.size()) {
|
||||
|
@ -647,25 +611,20 @@ void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::Ifc
|
|||
}
|
||||
ss << "]";
|
||||
properties[key] = ss.str();
|
||||
}
|
||||
else if (const Schema_2x3::IfcComplexProperty* const complexProp = property.ToPtr<Schema_2x3::IfcComplexProperty>()) {
|
||||
} else if (const Schema_2x3::IfcComplexProperty *const complexProp = property.ToPtr<Schema_2x3::IfcComplexProperty>()) {
|
||||
if (nest > 2) { // mostly arbitrary limit to prevent stack overflow vulnerabilities
|
||||
IFCImporter::LogError("maximum nesting level for IfcComplexProperty reached, skipping this property.");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ProcessMetadata(complexProp->HasProperties, conv, properties, key, nest + 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
properties[key] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ProcessMetadata(uint64_t relDefinesByPropertiesID, ConversionData& conv, Metadata& properties)
|
||||
{
|
||||
void ProcessMetadata(uint64_t relDefinesByPropertiesID, ConversionData &conv, Metadata &properties) {
|
||||
if (const Schema_2x3::IfcRelDefinesByProperties *const pset = conv.db.GetObject(relDefinesByPropertiesID)->ToPtr<Schema_2x3::IfcRelDefinesByProperties>()) {
|
||||
if (const Schema_2x3::IfcPropertySet *const set = conv.db.GetObject(pset->RelatingPropertyDefinition->GetID())->ToPtr<Schema_2x3::IfcPropertySet>()) {
|
||||
ProcessMetadata(set->HasProperties, conv, properties);
|
||||
|
@ -790,7 +749,6 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el
|
|||
nd_aggr->mNumChildren = 1;
|
||||
nd_aggr->mChildren = new aiNode *[1]();
|
||||
|
||||
|
||||
nd_aggr->mChildren[0] = ndnew;
|
||||
|
||||
if (openings_local.size()) {
|
||||
|
@ -872,11 +830,9 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ProcessSpatialStructures(ConversionData& conv)
|
||||
{
|
||||
void ProcessSpatialStructures(ConversionData &conv) {
|
||||
// XXX add support for multiple sites (i.e. IfcSpatialStructureElements with composition == COMPLEX)
|
||||
|
||||
|
||||
// process all products in the file. it is reasonable to assume that a
|
||||
// file that is relevant for us contains at least a site or a building.
|
||||
const STEP::DB::ObjectMapByType &map = conv.db.GetObjectsByType();
|
||||
|
@ -939,8 +895,7 @@ void ProcessSpatialStructures(ConversionData& conv)
|
|||
|
||||
if (nb_nodes == 1) {
|
||||
conv.out->mRootNode = nodes[0];
|
||||
}
|
||||
else if (nb_nodes > 1) {
|
||||
} else if (nb_nodes > 1) {
|
||||
conv.out->mRootNode = new aiNode("Root");
|
||||
conv.out->mRootNode->mParent = NULL;
|
||||
conv.out->mRootNode->mNumChildren = static_cast<unsigned int>(nb_nodes);
|
||||
|
@ -953,15 +908,13 @@ void ProcessSpatialStructures(ConversionData& conv)
|
|||
|
||||
conv.out->mRootNode->mChildren[i] = node;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
IFCImporter::ThrowException("failed to determine primary site element");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MakeTreeRelative(aiNode* start, const aiMatrix4x4& combined)
|
||||
{
|
||||
void MakeTreeRelative(aiNode *start, const aiMatrix4x4 &combined) {
|
||||
// combined is the parent's absolute transformation matrix
|
||||
const aiMatrix4x4 old = start->mTransformation;
|
||||
|
||||
|
@ -976,13 +929,10 @@ void MakeTreeRelative(aiNode* start, const aiMatrix4x4& combined)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MakeTreeRelative(ConversionData& conv)
|
||||
{
|
||||
void MakeTreeRelative(ConversionData &conv) {
|
||||
MakeTreeRelative(conv.out->mRootNode, IfcMatrix4());
|
||||
}
|
||||
|
||||
} // !anon
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
|
|
@ -362,8 +362,9 @@ void TempMesh::FixupFaceOrientation()
|
|||
{
|
||||
std::reverse(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc);
|
||||
std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
|
||||
for( size_t a = 0; a < nbvc - 1; ++a )
|
||||
std::swap(neighbour[nbvsi + a], neighbour[nbvsi + a + 1]);
|
||||
for (size_t aa = 0; aa < nbvc - 1; ++aa) {
|
||||
std::swap(neighbour[nbvsi + aa], neighbour[nbvsi + aa + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
// either way we're done with the neighbour. Mark it as done and continue checking from there recursively
|
||||
|
|
|
@ -50,12 +50,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/TinyFormatter.h>
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <memory>
|
||||
|
||||
#include <functional>
|
||||
|
||||
using namespace Assimp;
|
||||
namespace EXPRESS = STEP::EXPRESS;
|
||||
|
||||
#include <functional>
|
||||
namespace EXPRESS = STEP::EXPRESS;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = "")
|
||||
|
@ -127,8 +126,8 @@ STEP::DB* STEP::ReadFileHeader(std::shared_ptr<IOStream> stream) {
|
|||
if (list->GetSize() > 1) {
|
||||
ASSIMP_LOG_WARN(AddLineNumber("multiple schemas currently not supported",line));
|
||||
}
|
||||
const EXPRESS::STRING* string( nullptr );
|
||||
if (!list->GetSize() || !(string=dynamic_cast<const EXPRESS::STRING*>( (*list)[0].get() ))) {
|
||||
const EXPRESS::STRING *string = dynamic_cast<const EXPRESS::STRING *>((*list)[0].get());
|
||||
if (!list->GetSize() || nullptr == string ) {
|
||||
throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line);
|
||||
}
|
||||
head.fileSchema = *string;
|
||||
|
@ -539,7 +538,7 @@ void STEP::LazyObject::LazyInit() const {
|
|||
}
|
||||
|
||||
const char* acopy = args;
|
||||
std::shared_ptr<const EXPRESS::LIST> conv_args = EXPRESS::LIST::Parse(acopy,STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema());
|
||||
std::shared_ptr<const EXPRESS::LIST> conv_args = EXPRESS::LIST::Parse(acopy,(uint64_t)STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema());
|
||||
delete[] args;
|
||||
args = NULL;
|
||||
|
||||
|
|
|
@ -45,24 +45,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
* @brief Implementation of the LWO importer class
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
|
||||
|
||||
// internal headers
|
||||
#include "LWO/LWOLoader.h"
|
||||
#include "PostProcessing/ProcessHelper.h"
|
||||
#include "PostProcessing/ConvertToLHProcess.h"
|
||||
#include "PostProcessing/ProcessHelper.h"
|
||||
|
||||
#include <assimp/StringComparison.h>
|
||||
#include <assimp/SGSpatialSort.h>
|
||||
#include <assimp/ByteSwapper.h>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/SGSpatialSort.h>
|
||||
#include <assimp/StringComparison.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
@ -81,8 +80,8 @@ static const aiImporterDesc desc = {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
LWOImporter::LWOImporter()
|
||||
: mIsLWO2(),
|
||||
LWOImporter::LWOImporter() :
|
||||
mIsLWO2(),
|
||||
mIsLXOB(),
|
||||
mLayers(),
|
||||
mCurLayer(),
|
||||
|
@ -91,22 +90,23 @@ LWOImporter::LWOImporter()
|
|||
mSurfaces(),
|
||||
mFileBuffer(),
|
||||
fileSize(),
|
||||
pScene(),
|
||||
mScene(nullptr),
|
||||
configSpeedFlag(),
|
||||
configLayerIndex(),
|
||||
hasNamedLayer()
|
||||
{}
|
||||
hasNamedLayer() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
LWOImporter::~LWOImporter()
|
||||
{}
|
||||
LWOImporter::~LWOImporter() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
||||
{
|
||||
const std::string extension = GetExtension(pFile);
|
||||
bool LWOImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool checkSig) const {
|
||||
const std::string extension = GetExtension(file);
|
||||
if (extension == "lwo" || extension == "lxo") {
|
||||
return true;
|
||||
}
|
||||
|
@ -117,15 +117,14 @@ bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
|
|||
tokens[0] = AI_LWO_FOURCC_LWOB;
|
||||
tokens[1] = AI_LWO_FOURCC_LWO2;
|
||||
tokens[2] = AI_LWO_FOURCC_LXOB;
|
||||
return CheckMagicToken(pIOHandler,pFile,tokens,3,8);
|
||||
return CheckMagicToken(pIOHandler, file, tokens, 3, 8);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties
|
||||
void LWOImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
void LWOImporter::SetupProperties(const Importer *pImp) {
|
||||
configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0) ? true : false);
|
||||
configLayerIndex = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY, UINT_MAX);
|
||||
configLayerName = pImp->GetPropertyString(AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY, "");
|
||||
|
@ -133,8 +132,7 @@ void LWOImporter::SetupProperties(const Importer* pImp)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get list of file extensions
|
||||
const aiImporterDesc* LWOImporter::GetInfo () const
|
||||
{
|
||||
const aiImporterDesc *LWOImporter::GetInfo() const {
|
||||
return &desc;
|
||||
}
|
||||
|
||||
|
@ -142,21 +140,22 @@ const aiImporterDesc* LWOImporter::GetInfo () const
|
|||
// Imports the given file into the given scene structure.
|
||||
void LWOImporter::InternReadFile(const std::string &pFile,
|
||||
aiScene *pScene,
|
||||
IOSystem* pIOHandler)
|
||||
{
|
||||
IOSystem *pIOHandler) {
|
||||
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
|
||||
|
||||
// Check whether we can read from the file
|
||||
if( file.get() == NULL)
|
||||
if (file.get() == nullptr) {
|
||||
throw DeadlyImportError("Failed to open LWO file " + pFile + ".");
|
||||
}
|
||||
|
||||
if((this->fileSize = (unsigned int)file->FileSize()) < 12)
|
||||
if ((this->fileSize = (unsigned int)file->FileSize()) < 12) {
|
||||
throw DeadlyImportError("LWO: The file is too small to contain the IFF header");
|
||||
}
|
||||
|
||||
// Allocate storage and copy the contents of the file to a memory buffer
|
||||
std::vector<uint8_t> mBuffer(fileSize);
|
||||
file->Read(&mBuffer[0], 1, fileSize);
|
||||
this->pScene = pScene;
|
||||
this->mScene = pScene;
|
||||
|
||||
// Determine the type of the file
|
||||
uint32_t fileType;
|
||||
|
@ -186,7 +185,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
mLayers->push_back(Layer());
|
||||
mCurLayer = &mLayers->back();
|
||||
mCurLayer->mName = "<LWODefault>";
|
||||
mCurLayer->mIndex = -1;
|
||||
mCurLayer->mIndex = (uint16_t) -1;
|
||||
|
||||
// old lightwave file format (prior to v6)
|
||||
if (AI_LWO_FOURCC_LWOB == fileType) {
|
||||
|
@ -207,8 +206,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
ASSIMP_LOG_INFO("LWO file format: LXOB (Modo)");
|
||||
}
|
||||
// we don't know this format
|
||||
else
|
||||
{
|
||||
else {
|
||||
char szBuff[5];
|
||||
szBuff[0] = (char)(fileType >> 24u);
|
||||
szBuff[1] = (char)(fileType >> 16u);
|
||||
|
@ -235,8 +233,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
|
||||
if (configLayerName.length() && !hasNamedLayer) {
|
||||
throw DeadlyImportError("LWO2: Unable to find the requested layer: "
|
||||
+ configLayerName);
|
||||
throw DeadlyImportError("LWO2: Unable to find the requested layer: " + configLayerName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,8 +268,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
|
||||
unsigned int idx = (*it).surfaceIndex;
|
||||
if (idx >= mTags->size())
|
||||
{
|
||||
if (idx >= mTags->size()) {
|
||||
ASSIMP_LOG_WARN("LWO: Invalid face surface index");
|
||||
idx = UINT_MAX;
|
||||
}
|
||||
|
@ -291,8 +287,8 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
if (UINT_MAX == iDefaultSurface) {
|
||||
pSorted.erase(pSorted.end() - 1);
|
||||
}
|
||||
for (unsigned int p = 0,i = 0;i < mSurfaces->size();++i) {
|
||||
SortedRep& sorted = pSorted[i];
|
||||
for (unsigned int p = 0, j = 0; j < mSurfaces->size(); ++j) {
|
||||
SortedRep &sorted = pSorted[j];
|
||||
if (sorted.empty())
|
||||
continue;
|
||||
|
||||
|
@ -307,9 +303,9 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
mesh->mNumVertices += layer.mFaces[*it].mNumIndices;
|
||||
}
|
||||
|
||||
aiVector3D *nrm = NULL, * pv = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||
aiVector3D *nrm = nullptr, *pv = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||
aiFace *pf = mesh->mFaces = new aiFace[mesh->mNumFaces];
|
||||
mesh->mMaterialIndex = i;
|
||||
mesh->mMaterialIndex = j;
|
||||
|
||||
// find out which vertex color channels and which texture coordinate
|
||||
// channels are really required by the material attached to this mesh
|
||||
|
@ -325,8 +321,8 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
#endif
|
||||
|
||||
FindUVChannels(_mSurfaces[i],sorted,layer,vUVChannelIndices);
|
||||
FindVCChannels(_mSurfaces[i],sorted,layer,vVColorIndices);
|
||||
FindUVChannels(_mSurfaces[j], sorted, layer, vUVChannelIndices);
|
||||
FindVCChannels(_mSurfaces[j], sorted, layer, vVColorIndices);
|
||||
|
||||
// allocate storage for UV and CV channels
|
||||
aiVector3D *pvUV[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||
|
@ -341,8 +337,9 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
mesh->mNumUVComponents[0] = 2;
|
||||
}
|
||||
|
||||
if (layer.mNormals.name.length())
|
||||
if (layer.mNormals.name.length()) {
|
||||
nrm = mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
||||
}
|
||||
|
||||
aiColor4D *pvVC[AI_MAX_NUMBER_OF_COLOR_SETS];
|
||||
for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS; ++mui) {
|
||||
|
@ -415,7 +412,8 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
pf->mIndices = face.mIndices;
|
||||
pf->mNumIndices = face.mNumIndices;
|
||||
unsigned int** p = (unsigned int**)&face.mIndices;*p = NULL; // HACK: make sure it won't be deleted
|
||||
unsigned int **facePtr = (unsigned int **)&face.mIndices;
|
||||
*facePtr = nullptr; // HACK: make sure it won't be deleted
|
||||
pf++;
|
||||
}
|
||||
|
||||
|
@ -424,8 +422,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
// Step here since it wouldn't handle smoothing groups correctly for LWO.
|
||||
// So we use a separate implementation.
|
||||
ComputeNormals(mesh, smoothingGroups, _mSurfaces[i]);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ASSIMP_LOG_DEBUG("LWO2: No need to compute normals, they're already there");
|
||||
}
|
||||
++p;
|
||||
|
@ -470,8 +467,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector<unsigned int> &smoothingGroups,
|
||||
const LWO::Surface& surface)
|
||||
{
|
||||
const LWO::Surface &surface) {
|
||||
// Allocate output storage
|
||||
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
||||
|
||||
|
@ -510,11 +506,9 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
|
|||
// Now generate the spatial sort tree
|
||||
SGSpatialSort sSort;
|
||||
std::vector<unsigned int>::const_iterator it = smoothingGroups.begin();
|
||||
for( begin = mesh->mFaces; begin != end; ++begin, ++it)
|
||||
{
|
||||
for (begin = mesh->mFaces; begin != end; ++begin, ++it) {
|
||||
aiFace &face = *begin;
|
||||
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
|
||||
unsigned int tt = face.mIndices[i];
|
||||
sSort.Add(mesh->mVertices[tt], tt, *it);
|
||||
}
|
||||
|
@ -532,14 +526,12 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
|
|||
for (begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
|
||||
const aiFace &face = *begin;
|
||||
unsigned int *beginIdx = face.mIndices, *const endIdx = face.mIndices + face.mNumIndices;
|
||||
for (; beginIdx != endIdx; ++beginIdx)
|
||||
{
|
||||
for (; beginIdx != endIdx; ++beginIdx) {
|
||||
unsigned int idx = *beginIdx;
|
||||
sSort.FindPositions(mesh->mVertices[idx], *it, posEpsilon, poResult, true);
|
||||
std::vector<unsigned int>::const_iterator a, end = poResult.end();
|
||||
|
||||
aiVector3D vNormals;
|
||||
for (a = poResult.begin();a != end;++a) {
|
||||
for (std::vector<unsigned int>::const_iterator a = poResult.begin(); a != poResult.end(); ++a) {
|
||||
const aiVector3D &v = faceNormals[*a];
|
||||
if (v * faceNormals[idx] < fLimit)
|
||||
continue;
|
||||
|
@ -555,21 +547,19 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
|
|||
for (begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
|
||||
const aiFace &face = *begin;
|
||||
unsigned int *beginIdx = face.mIndices, *const endIdx = face.mIndices + face.mNumIndices;
|
||||
for (; beginIdx != endIdx; ++beginIdx)
|
||||
{
|
||||
for (; beginIdx != endIdx; ++beginIdx) {
|
||||
unsigned int idx = *beginIdx;
|
||||
if (vertexDone[idx])
|
||||
continue;
|
||||
sSort.FindPositions(mesh->mVertices[idx], *it, posEpsilon, poResult, true);
|
||||
std::vector<unsigned int>::const_iterator a, end = poResult.end();
|
||||
|
||||
aiVector3D vNormals;
|
||||
for (a = poResult.begin();a != end;++a) {
|
||||
for (std::vector<unsigned int>::const_iterator a = poResult.begin(); a != poResult.end(); ++a) {
|
||||
const aiVector3D &v = faceNormals[*a];
|
||||
vNormals += v;
|
||||
}
|
||||
vNormals.Normalize();
|
||||
for (a = poResult.begin();a != end;++a) {
|
||||
for (std::vector<unsigned int>::const_iterator a = poResult.begin(); a != poResult.end(); ++a) {
|
||||
mesh->mNormals[*a] = vNormals;
|
||||
vertexDone[*a] = true;
|
||||
}
|
||||
|
@ -579,10 +569,9 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::GenerateNodeGraph(std::map<uint16_t,aiNode*>& apcNodes)
|
||||
{
|
||||
void LWOImporter::GenerateNodeGraph(std::map<uint16_t, aiNode *> &apcNodes) {
|
||||
// now generate the final nodegraph - generate a root node and attach children
|
||||
aiNode* root = pScene->mRootNode = new aiNode();
|
||||
aiNode *root = mScene->mRootNode = new aiNode();
|
||||
root->mName.Set("<LWORoot>");
|
||||
|
||||
//Set parent of all children, inserting pivots
|
||||
|
@ -622,7 +611,7 @@ void LWOImporter::GenerateNodeGraph(std::map<uint16_t,aiNode*>& apcNodes)
|
|||
}
|
||||
|
||||
//Set children of all parents
|
||||
apcNodes[-1] = root;
|
||||
apcNodes[(uint16_t)-1] = root;
|
||||
for (auto itMapParentNodes = apcNodes.begin(); itMapParentNodes != apcNodes.end(); ++itMapParentNodes) {
|
||||
for (auto itMapChildNodes = apcNodes.begin(); itMapChildNodes != apcNodes.end(); ++itMapChildNodes) {
|
||||
if ((itMapParentNodes->first != itMapChildNodes->first) && (itMapParentNodes->second == itMapChildNodes->second->mParent)) {
|
||||
|
@ -640,28 +629,27 @@ void LWOImporter::GenerateNodeGraph(std::map<uint16_t,aiNode*>& apcNodes)
|
|||
}
|
||||
}
|
||||
|
||||
if (!pScene->mRootNode->mNumChildren)
|
||||
if (!mScene->mRootNode->mNumChildren)
|
||||
throw DeadlyImportError("LWO: Unable to build a valid node graph");
|
||||
|
||||
// Remove a single root node with no meshes assigned to it ...
|
||||
if (1 == pScene->mRootNode->mNumChildren) {
|
||||
aiNode* pc = pScene->mRootNode->mChildren[0];
|
||||
pc->mParent = pScene->mRootNode->mChildren[0] = NULL;
|
||||
delete pScene->mRootNode;
|
||||
pScene->mRootNode = pc;
|
||||
if (1 == mScene->mRootNode->mNumChildren) {
|
||||
aiNode *pc = mScene->mRootNode->mChildren[0];
|
||||
pc->mParent = mScene->mRootNode->mChildren[0] = nullptr;
|
||||
delete mScene->mRootNode;
|
||||
mScene->mRootNode = pc;
|
||||
}
|
||||
|
||||
// convert the whole stuff to RH with CCW winding
|
||||
MakeLeftHandedProcess maker;
|
||||
maker.Execute(pScene);
|
||||
maker.Execute(mScene);
|
||||
|
||||
FlipWindingOrderProcess flipper;
|
||||
flipper.Execute(pScene);
|
||||
flipper.Execute(mScene);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::ResolveTags()
|
||||
{
|
||||
void LWOImporter::ResolveTags() {
|
||||
// --- this function is used for both LWO2 and LWOB
|
||||
mMapping->resize(mTags->size(), UINT_MAX);
|
||||
for (unsigned int a = 0; a < mTags->size(); ++a) {
|
||||
|
@ -680,8 +668,7 @@ void LWOImporter::ResolveTags()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::ResolveClips()
|
||||
{
|
||||
void LWOImporter::ResolveClips() {
|
||||
for (unsigned int i = 0; i < mClips.size(); ++i) {
|
||||
|
||||
Clip &clip = mClips[i];
|
||||
|
@ -707,8 +694,7 @@ void LWOImporter::ResolveClips()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::AdjustTexturePath(std::string& out)
|
||||
{
|
||||
void LWOImporter::AdjustTexturePath(std::string &out) {
|
||||
// --- this function is used for both LWO2 and LWOB
|
||||
if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) {
|
||||
|
||||
|
@ -725,16 +711,13 @@ void LWOImporter::AdjustTexturePath(std::string& out)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWOTags(unsigned int size)
|
||||
{
|
||||
void LWOImporter::LoadLWOTags(unsigned int size) {
|
||||
// --- this function is used for both LWO2 and LWOB
|
||||
|
||||
const char *szCur = (const char *)mFileBuffer, *szLast = szCur;
|
||||
const char *const szEnd = szLast + size;
|
||||
while (szCur < szEnd)
|
||||
{
|
||||
if (!(*szCur))
|
||||
{
|
||||
while (szCur < szEnd) {
|
||||
if (!(*szCur)) {
|
||||
const size_t len = (size_t)(szCur - szLast);
|
||||
// FIX: skip empty-sized tags
|
||||
if (len)
|
||||
|
@ -747,27 +730,24 @@ void LWOImporter::LoadLWOTags(unsigned int size)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWOPoints(unsigned int length)
|
||||
{
|
||||
void LWOImporter::LoadLWOPoints(unsigned int length) {
|
||||
// --- this function is used for both LWO2 and LWOB but for
|
||||
// LWO2 we need to allocate 25% more storage - it could be we'll
|
||||
// need to duplicate some points later.
|
||||
const size_t vertexLen = 12;
|
||||
if ((length % vertexLen) != 0)
|
||||
{
|
||||
if ((length % vertexLen) != 0) {
|
||||
throw DeadlyImportError("LWO2: Points chunk length is not multiple of vertexLen (12)");
|
||||
}
|
||||
unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
|
||||
if (mIsLWO2)
|
||||
{
|
||||
if (mIsLWO2) {
|
||||
mCurLayer->mTempPoints.reserve(regularSize + (regularSize >> 2u));
|
||||
mCurLayer->mTempPoints.resize(regularSize);
|
||||
|
||||
// initialize all point referrers with the default values
|
||||
mCurLayer->mPointReferrers.reserve(regularSize + (regularSize >> 2u));
|
||||
mCurLayer->mPointReferrers.resize(regularSize, UINT_MAX);
|
||||
}
|
||||
else mCurLayer->mTempPoints.resize( regularSize );
|
||||
} else
|
||||
mCurLayer->mTempPoints.resize(regularSize);
|
||||
|
||||
// perform endianness conversions
|
||||
#ifndef AI_BUILD_BIG_ENDIAN
|
||||
|
@ -778,20 +758,19 @@ void LWOImporter::LoadLWOPoints(unsigned int length)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2Polygons(unsigned int length)
|
||||
{
|
||||
void LWOImporter::LoadLWO2Polygons(unsigned int length) {
|
||||
LE_NCONST uint16_t *const end = (LE_NCONST uint16_t *)(mFileBuffer + length);
|
||||
const uint32_t type = GetU4();
|
||||
|
||||
// Determine the type of the polygons
|
||||
switch (type)
|
||||
{
|
||||
switch (type) {
|
||||
// read unsupported stuff too (although we won't process it)
|
||||
case AI_LWO_MBAL:
|
||||
ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (METABALL)");
|
||||
break;
|
||||
case AI_LWO_CURV:
|
||||
ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (SPLINE)");;
|
||||
ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (SPLINE)");
|
||||
;
|
||||
break;
|
||||
|
||||
// These are ok with no restrictions
|
||||
|
@ -814,8 +793,7 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
|
|||
CountVertsAndFacesLWO2(iNumVertices, iNumFaces, cursor, end);
|
||||
|
||||
// allocate the output array and copy face indices
|
||||
if (iNumFaces)
|
||||
{
|
||||
if (iNumFaces) {
|
||||
cursor = (uint16_t *)mFileBuffer;
|
||||
|
||||
mCurLayer->mFaces.resize(iNumFaces, LWO::Face(type));
|
||||
|
@ -826,10 +804,8 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::CountVertsAndFacesLWO2(unsigned int &verts, unsigned int &faces,
|
||||
uint16_t*& cursor, const uint16_t* const end, unsigned int max)
|
||||
{
|
||||
while (cursor < end && max--)
|
||||
{
|
||||
uint16_t *&cursor, const uint16_t *const end, unsigned int max) {
|
||||
while (cursor < end && max--) {
|
||||
uint16_t numIndices;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
AI_LSWAP2(numIndices);
|
||||
|
@ -838,8 +814,7 @@ void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& face
|
|||
verts += numIndices;
|
||||
++faces;
|
||||
|
||||
for(uint16_t i = 0; i < numIndices; i++)
|
||||
{
|
||||
for (uint16_t i = 0; i < numIndices; i++) {
|
||||
ReadVSizedIntLWO2((uint8_t *&)cursor);
|
||||
}
|
||||
}
|
||||
|
@ -848,10 +823,8 @@ void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& face
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator &it,
|
||||
uint16_t *&cursor,
|
||||
const uint16_t* const end)
|
||||
{
|
||||
while (cursor < end)
|
||||
{
|
||||
const uint16_t *const end) {
|
||||
while (cursor < end) {
|
||||
LWO::Face &face = *it++;
|
||||
uint16_t numIndices;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
|
@ -861,24 +834,20 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
|
|||
if (face.mNumIndices) /* byte swapping has already been done */
|
||||
{
|
||||
face.mIndices = new unsigned int[face.mNumIndices];
|
||||
for(unsigned int i = 0; i < face.mNumIndices; i++)
|
||||
{
|
||||
for (unsigned int i = 0; i < face.mNumIndices; i++) {
|
||||
face.mIndices[i] = ReadVSizedIntLWO2((uint8_t *&)cursor) + mCurLayer->mPointIDXOfs;
|
||||
if(face.mIndices[i] > mCurLayer->mTempPoints.size())
|
||||
{
|
||||
if (face.mIndices[i] > mCurLayer->mTempPoints.size()) {
|
||||
ASSIMP_LOG_WARN("LWO2: Failure evaluating face record, index is out of range");
|
||||
face.mIndices[i] = (unsigned int)mCurLayer->mTempPoints.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else throw DeadlyImportError("LWO2: Encountered invalid face record with zero indices");
|
||||
} else
|
||||
throw DeadlyImportError("LWO2: Encountered invalid face record with zero indices");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
|
||||
{
|
||||
void LWOImporter::LoadLWO2PolygonTags(unsigned int length) {
|
||||
LE_NCONST uint8_t *const end = mFileBuffer + length;
|
||||
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(length, PTAG, 4);
|
||||
|
@ -887,8 +856,7 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
|
|||
if (type != AI_LWO_SURF && type != AI_LWO_SMGP)
|
||||
return;
|
||||
|
||||
while (mFileBuffer < end)
|
||||
{
|
||||
while (mFileBuffer < end) {
|
||||
unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
|
||||
unsigned int j = GetU2();
|
||||
|
||||
|
@ -911,8 +879,7 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPoly)
|
||||
{
|
||||
VMapEntry *FindEntry(std::vector<T> &list, const std::string &name, bool perPoly) {
|
||||
for (auto &elem : list) {
|
||||
if (elem.name == name) {
|
||||
if (!perPoly) {
|
||||
|
@ -929,8 +896,7 @@ VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPol
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
inline void CreateNewEntry(T& chan, unsigned int srcIdx)
|
||||
{
|
||||
inline void CreateNewEntry(T &chan, unsigned int srcIdx) {
|
||||
if (!chan.name.length())
|
||||
return;
|
||||
|
||||
|
@ -943,8 +909,7 @@ inline void CreateNewEntry(T& chan, unsigned int srcIdx)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
inline void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx)
|
||||
{
|
||||
inline void CreateNewEntry(std::vector<T> &list, unsigned int srcIdx) {
|
||||
for (auto &elem : list) {
|
||||
CreateNewEntry(elem, srcIdx);
|
||||
}
|
||||
|
@ -952,8 +917,7 @@ inline void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry *base, unsigned int numRead,
|
||||
unsigned int idx, float* data)
|
||||
{
|
||||
unsigned int idx, float *data) {
|
||||
ai_assert(NULL != data);
|
||||
LWO::ReferrerList &refList = mCurLayer->mPointReferrers;
|
||||
unsigned int i;
|
||||
|
@ -972,8 +936,7 @@ inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, unsigned int destIdx)
|
||||
{
|
||||
inline void AddToSingleLinkedList(ReferrerList &refList, unsigned int srcIdx, unsigned int destIdx) {
|
||||
if (UINT_MAX == refList[srcIdx]) {
|
||||
refList[srcIdx] = destIdx;
|
||||
return;
|
||||
|
@ -983,8 +946,7 @@ inline void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, un
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Load LWO2 vertex map
|
||||
void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
|
||||
{
|
||||
void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) {
|
||||
LE_NCONST uint8_t *const end = mFileBuffer + length;
|
||||
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(length, VMAP, 6);
|
||||
|
@ -997,12 +959,10 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
|
|||
std::string name;
|
||||
GetS0(name, length);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
switch (type) {
|
||||
case AI_LWO_TXUV:
|
||||
if (dims != 2) {
|
||||
ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'"
|
||||
+ name + "\' with !2 components");
|
||||
ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'" + name + "\' with !2 components");
|
||||
return;
|
||||
}
|
||||
base = FindEntry(mCurLayer->mUVChannels, name, perPoly);
|
||||
|
@ -1010,18 +970,15 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
|
|||
case AI_LWO_WGHT:
|
||||
case AI_LWO_MNVW:
|
||||
if (dims != 1) {
|
||||
ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'"
|
||||
+ name + "\' with !1 components");
|
||||
ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'" + name + "\' with !1 components");
|
||||
return;
|
||||
}
|
||||
base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels
|
||||
: mCurLayer->mSWeightChannels),name,perPoly);
|
||||
base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels : mCurLayer->mSWeightChannels), name, perPoly);
|
||||
break;
|
||||
case AI_LWO_RGB:
|
||||
case AI_LWO_RGBA:
|
||||
if (dims != 3 && dims != 4) {
|
||||
ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'"
|
||||
+ name + "\' with a dimension > 4 or < 3");
|
||||
ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'" + name + "\' with a dimension > 4 or < 3");
|
||||
return;
|
||||
}
|
||||
base = FindEntry(mCurLayer->mVColorChannels, name, perPoly);
|
||||
|
@ -1096,8 +1053,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
|
|||
do {
|
||||
if (tmp == srcIdx)
|
||||
break;
|
||||
}
|
||||
while ((tmp = refList[tmp]) != UINT_MAX);
|
||||
} while ((tmp = refList[tmp]) != UINT_MAX);
|
||||
if (tmp == UINT_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1138,8 +1094,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Load LWO2 clip
|
||||
void LWOImporter::LoadLWO2Clip(unsigned int length)
|
||||
{
|
||||
void LWOImporter::LoadLWO2Clip(unsigned int length) {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(length, CLIP, 10);
|
||||
|
||||
mClips.push_back(LWO::Clip());
|
||||
|
@ -1149,8 +1104,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
clip.idx = GetU4();
|
||||
|
||||
IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
switch (head.type)
|
||||
{
|
||||
switch (head.type) {
|
||||
case AI_LWO_STIL:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, STIL, 1);
|
||||
|
||||
|
@ -1163,9 +1117,12 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, ISEQ, 16);
|
||||
// Image sequence. We'll later take the first.
|
||||
{
|
||||
uint8_t digits = GetU1(); mFileBuffer++;
|
||||
int16_t offset = GetU2(); mFileBuffer+=4;
|
||||
int16_t start = GetU2(); mFileBuffer+=4;
|
||||
uint8_t digits = GetU1();
|
||||
mFileBuffer++;
|
||||
int16_t offset = GetU2();
|
||||
mFileBuffer += 4;
|
||||
int16_t start = GetU2();
|
||||
mFileBuffer += 4;
|
||||
|
||||
std::string s;
|
||||
std::ostringstream ss;
|
||||
|
@ -1209,8 +1166,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Load envelope description
|
||||
void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
||||
{
|
||||
void LWOImporter::LoadLWO2Envelope(unsigned int length) {
|
||||
LE_NCONST uint8_t *const end = mFileBuffer + length;
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(length, ENVL, 4);
|
||||
|
||||
|
@ -1223,18 +1179,15 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
// It looks like there might be an extra U4 right after the index,
|
||||
// at least in modo (LXOB) files: we'll ignore it if it's zero,
|
||||
// otherwise it represents the start of a subchunk, so we backtrack.
|
||||
if (mIsLXOB)
|
||||
{
|
||||
if (mIsLXOB) {
|
||||
uint32_t extra = GetU4();
|
||||
if (extra)
|
||||
{
|
||||
if (extra) {
|
||||
mFileBuffer -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
// ... and read all subchunks
|
||||
while (true)
|
||||
{
|
||||
while (true) {
|
||||
if (mFileBuffer + 6 >= end) break;
|
||||
LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
|
@ -1242,8 +1195,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
throw DeadlyImportError("LWO2: Invalid envelope chunk length");
|
||||
|
||||
uint8_t *const next = mFileBuffer + head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
switch (head.type) {
|
||||
// Type & representation of the envelope
|
||||
case AI_LWO_TYPE:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, TYPE, 2);
|
||||
|
@ -1267,8 +1219,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
break;
|
||||
|
||||
// keyframe
|
||||
case AI_LWO_KEY:
|
||||
{
|
||||
case AI_LWO_KEY: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, KEY, 8);
|
||||
|
||||
envelope.keys.push_back(LWO::Key());
|
||||
|
@ -1280,27 +1231,31 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
}
|
||||
|
||||
// interval interpolation
|
||||
case AI_LWO_SPAN:
|
||||
{
|
||||
case AI_LWO_SPAN: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SPAN, 4);
|
||||
if (envelope.keys.size() < 2)
|
||||
ASSIMP_LOG_WARN("LWO2: Unexpected SPAN chunk");
|
||||
else {
|
||||
LWO::Key &key = envelope.keys.back();
|
||||
switch (GetU4())
|
||||
{
|
||||
switch (GetU4()) {
|
||||
case AI_LWO_STEP:
|
||||
key.inter = LWO::IT_STEP;break;
|
||||
key.inter = LWO::IT_STEP;
|
||||
break;
|
||||
case AI_LWO_LINE:
|
||||
key.inter = LWO::IT_LINE;break;
|
||||
key.inter = LWO::IT_LINE;
|
||||
break;
|
||||
case AI_LWO_TCB:
|
||||
key.inter = LWO::IT_TCB;break;
|
||||
key.inter = LWO::IT_TCB;
|
||||
break;
|
||||
case AI_LWO_HERM:
|
||||
key.inter = LWO::IT_HERM;break;
|
||||
key.inter = LWO::IT_HERM;
|
||||
break;
|
||||
case AI_LWO_BEZI:
|
||||
key.inter = LWO::IT_BEZI;break;
|
||||
key.inter = LWO::IT_BEZI;
|
||||
break;
|
||||
case AI_LWO_BEZ2:
|
||||
key.inter = LWO::IT_BEZ2;break;
|
||||
key.inter = LWO::IT_BEZ2;
|
||||
break;
|
||||
default:
|
||||
ASSIMP_LOG_WARN("LWO2: Unknown interval interpolation mode");
|
||||
};
|
||||
|
@ -1321,19 +1276,16 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Load file - master function
|
||||
void LWOImporter::LoadLWO2File()
|
||||
{
|
||||
void LWOImporter::LoadLWO2File() {
|
||||
bool skip = false;
|
||||
|
||||
LE_NCONST uint8_t *const end = mFileBuffer + fileSize;
|
||||
unsigned int iUnnamed = 0;
|
||||
while (true)
|
||||
{
|
||||
while (true) {
|
||||
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end) break;
|
||||
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head.length > end)
|
||||
{
|
||||
if (mFileBuffer + head.length > end) {
|
||||
throw DeadlyImportError("LWO2: Chunk length points behind the file");
|
||||
break;
|
||||
}
|
||||
|
@ -1344,11 +1296,9 @@ void LWOImporter::LoadLWO2File()
|
|||
continue;
|
||||
}
|
||||
|
||||
switch (head.type)
|
||||
{
|
||||
switch (head.type) {
|
||||
// new layer
|
||||
case AI_LWO_LAYR:
|
||||
{
|
||||
case AI_LWO_LAYR: {
|
||||
// add a new layer to the list ....
|
||||
mLayers->push_back(LWO::Layer());
|
||||
LWO::Layer &layer = mLayers->back();
|
||||
|
@ -1362,8 +1312,8 @@ void LWOImporter::LoadLWO2File()
|
|||
// Continue loading this layer or ignore it? Check the layer index property
|
||||
if (UINT_MAX != configLayerIndex && (configLayerIndex - 1) != layer.mIndex) {
|
||||
skip = true;
|
||||
}
|
||||
else skip = false;
|
||||
} else
|
||||
skip = false;
|
||||
|
||||
// pivot point
|
||||
mFileBuffer += 2; /* unknown */
|
||||
|
@ -1382,13 +1332,14 @@ void LWOImporter::LoadLWO2File()
|
|||
// load this layer or ignore it? Check the layer name property
|
||||
if (configLayerName.length() && configLayerName != layer.mName) {
|
||||
skip = true;
|
||||
}
|
||||
else hasNamedLayer = true;
|
||||
} else
|
||||
hasNamedLayer = true;
|
||||
|
||||
// optional: parent of this layer
|
||||
if (mFileBuffer + 2 <= next)
|
||||
layer.mParent = GetU2();
|
||||
else layer.mParent = -1;
|
||||
else
|
||||
layer.mParent = (uint16_t) -1;
|
||||
|
||||
// Set layer skip parameter
|
||||
layer.skip = skip;
|
||||
|
@ -1397,8 +1348,7 @@ void LWOImporter::LoadLWO2File()
|
|||
}
|
||||
|
||||
// vertex list
|
||||
case AI_LWO_PNTS:
|
||||
{
|
||||
case AI_LWO_PNTS: {
|
||||
if (skip)
|
||||
break;
|
||||
|
||||
|
@ -1409,25 +1359,23 @@ void LWOImporter::LoadLWO2File()
|
|||
}
|
||||
// vertex tags
|
||||
case AI_LWO_VMAD:
|
||||
if (mCurLayer->mFaces.empty())
|
||||
{
|
||||
if (mCurLayer->mFaces.empty()) {
|
||||
ASSIMP_LOG_WARN("LWO2: Unexpected VMAD chunk");
|
||||
break;
|
||||
}
|
||||
// --- intentionally no break here
|
||||
case AI_LWO_VMAP:
|
||||
{
|
||||
case AI_LWO_VMAP: {
|
||||
if (skip)
|
||||
break;
|
||||
|
||||
if (mCurLayer->mTempPoints.empty())
|
||||
ASSIMP_LOG_WARN("LWO2: Unexpected VMAP chunk");
|
||||
else LoadLWO2VertexMap(head.length,head.type == AI_LWO_VMAD);
|
||||
else
|
||||
LoadLWO2VertexMap(head.length, head.type == AI_LWO_VMAD);
|
||||
break;
|
||||
}
|
||||
// face list
|
||||
case AI_LWO_POLS:
|
||||
{
|
||||
case AI_LWO_POLS: {
|
||||
if (skip)
|
||||
break;
|
||||
|
||||
|
@ -1437,8 +1385,7 @@ void LWOImporter::LoadLWO2File()
|
|||
break;
|
||||
}
|
||||
// polygon tags
|
||||
case AI_LWO_PTAG:
|
||||
{
|
||||
case AI_LWO_PTAG: {
|
||||
if (skip)
|
||||
break;
|
||||
|
||||
|
@ -1450,8 +1397,7 @@ void LWOImporter::LoadLWO2File()
|
|||
break;
|
||||
}
|
||||
// list of tags
|
||||
case AI_LWO_TAGS:
|
||||
{
|
||||
case AI_LWO_TAGS: {
|
||||
if (!mTags->empty()) {
|
||||
ASSIMP_LOG_WARN("LWO2: SRFS chunk encountered twice");
|
||||
} else {
|
||||
|
@ -1461,22 +1407,19 @@ void LWOImporter::LoadLWO2File()
|
|||
}
|
||||
|
||||
// surface chunk
|
||||
case AI_LWO_SURF:
|
||||
{
|
||||
case AI_LWO_SURF: {
|
||||
LoadLWO2Surface(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// clip chunk
|
||||
case AI_LWO_CLIP:
|
||||
{
|
||||
case AI_LWO_CLIP: {
|
||||
LoadLWO2Clip(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// envelope chunk
|
||||
case AI_LWO_ENVL:
|
||||
{
|
||||
case AI_LWO_ENVL: {
|
||||
LoadLWO2Envelope(head.length);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -76,9 +76,6 @@ public:
|
|||
LWOImporter();
|
||||
~LWOImporter();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the class can handle the format of the given file.
|
||||
* See BaseImporter::CanRead() for details.
|
||||
|
@ -86,7 +83,6 @@ public:
|
|||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
|
||||
bool checkSig) const;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Called prior to ReadFile().
|
||||
* The function is a request to the importer to update its configuration
|
||||
|
@ -389,7 +385,7 @@ protected:
|
|||
unsigned int fileSize;
|
||||
|
||||
/** Output scene */
|
||||
aiScene* pScene;
|
||||
aiScene* mScene;
|
||||
|
||||
/** Configuration option: speed flag set? */
|
||||
bool configSpeedFlag;
|
||||
|
@ -406,8 +402,8 @@ protected:
|
|||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline float LWOImporter::GetF4()
|
||||
{
|
||||
inline
|
||||
float LWOImporter::GetF4() {
|
||||
float f;
|
||||
::memcpy(&f, mFileBuffer, 4);
|
||||
mFileBuffer += 4;
|
||||
|
|
|
@ -43,30 +43,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
/** @file Implementation of the material oart of the LWO importer class */
|
||||
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
|
||||
|
||||
// internal headers
|
||||
#include "LWOLoader.h"
|
||||
#include <assimp/ByteSwapper.h>
|
||||
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
T lerp(const T& one, const T& two, float val)
|
||||
{
|
||||
T lerp(const T &one, const T &two, float val) {
|
||||
return one + (two - one) * val;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Convert a lightwave mapping mode to our's
|
||||
inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
|
||||
{
|
||||
switch (in)
|
||||
{
|
||||
inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) {
|
||||
switch (in) {
|
||||
case LWO::Texture::REPEAT:
|
||||
return aiTextureMapMode_Wrap;
|
||||
|
||||
|
@ -84,8 +78,7 @@ inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTextureType type)
|
||||
{
|
||||
bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTextureType type) {
|
||||
ai_assert(NULL != pcMat);
|
||||
|
||||
unsigned int cur = 0, temp = 0;
|
||||
|
@ -101,9 +94,8 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
// as they are, the GenUVcoords step will compute UV
|
||||
// channels if they're not there.
|
||||
|
||||
aiTextureMapping mapping;
|
||||
switch (texture.mapMode)
|
||||
{
|
||||
aiTextureMapping mapping = aiTextureMapping_OTHER;
|
||||
switch (texture.mapMode) {
|
||||
case LWO::Texture::Planar:
|
||||
mapping = aiTextureMapping_PLANE;
|
||||
break;
|
||||
|
@ -120,8 +112,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
ASSIMP_LOG_ERROR("LWO2: Unsupported texture mapping: FrontProjection");
|
||||
mapping = aiTextureMapping_OTHER;
|
||||
break;
|
||||
case LWO::Texture::UV:
|
||||
{
|
||||
case LWO::Texture::UV: {
|
||||
if (UINT_MAX == texture.mRealUVIndex) {
|
||||
// We have no UV index for this texture, so we can't display it
|
||||
continue;
|
||||
|
@ -132,8 +123,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
pcMat->AddProperty<int>((int *)&temp, 1, AI_MATKEY_UVWSRC(type, cur));
|
||||
|
||||
mapping = aiTextureMapping_UV;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
ai_assert(false);
|
||||
};
|
||||
|
@ -178,7 +168,6 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
if ((*clip).idx == temp) {
|
||||
candidate = clip;
|
||||
}
|
||||
|
||||
}
|
||||
if (candidate == end) {
|
||||
ASSIMP_LOG_ERROR("LWO2: Clip index is out of bounds");
|
||||
|
@ -191,8 +180,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
s.Set("$texture.png");
|
||||
|
||||
//continue;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (Clip::UNSUPPORTED == (*candidate).type) {
|
||||
ASSIMP_LOG_ERROR("LWO2: Clip type is not supported");
|
||||
continue;
|
||||
|
@ -207,9 +195,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
}
|
||||
pcMat->AddProperty(&flags, 1, AI_MATKEY_TEXFLAGS(type, cur));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
std::string ss = texture.mFileName;
|
||||
if (!ss.length()) {
|
||||
ASSIMP_LOG_WARN("LWOB: Empty file name");
|
||||
|
@ -224,8 +210,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
pcMat->AddProperty<float>(&texture.mStrength, 1, AI_MATKEY_TEXBLEND(type, cur));
|
||||
|
||||
// add the blend operation
|
||||
switch (texture.blendType)
|
||||
{
|
||||
switch (texture.blendType) {
|
||||
case LWO::Texture::Normal:
|
||||
case LWO::Texture::Multiply:
|
||||
temp = (unsigned int)aiTextureOp_Multiply;
|
||||
|
@ -247,7 +232,6 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
default:
|
||||
temp = (unsigned int)aiTextureOp_Multiply;
|
||||
ASSIMP_LOG_WARN("LWO2: Unsupported texture blend mode: alpha or displacement");
|
||||
|
||||
}
|
||||
// Setup texture operation
|
||||
pcMat->AddProperty<int>((int *)&temp, 1, AI_MATKEY_TEXOP(type, cur));
|
||||
|
@ -270,8 +254,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
|
||||
{
|
||||
void LWOImporter::ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat) {
|
||||
// copy the name of the surface
|
||||
aiString st;
|
||||
st.Set(surf.mName);
|
||||
|
@ -285,28 +268,26 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
|
|||
pcMat->AddProperty(&surf.mBumpIntensity, 1, AI_MATKEY_BUMPSCALING);
|
||||
|
||||
aiShadingMode m;
|
||||
if (surf.mSpecularValue && surf.mGlossiness)
|
||||
{
|
||||
if (surf.mSpecularValue && surf.mGlossiness) {
|
||||
float fGloss;
|
||||
if (mIsLWO2) {
|
||||
fGloss = std::pow(surf.mGlossiness * ai_real(10.0) + ai_real(2.0), ai_real(2.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (16.0 >= surf.mGlossiness)
|
||||
fGloss = 6.0;
|
||||
else if (64.0 >= surf.mGlossiness)
|
||||
fGloss = 20.0;
|
||||
else if (256.0 >= surf.mGlossiness)
|
||||
fGloss = 50.0;
|
||||
else fGloss = 80.0;
|
||||
else
|
||||
fGloss = 80.0;
|
||||
}
|
||||
|
||||
pcMat->AddProperty(&surf.mSpecularValue, 1, AI_MATKEY_SHININESS_STRENGTH);
|
||||
pcMat->AddProperty(&fGloss, 1, AI_MATKEY_SHININESS);
|
||||
m = aiShadingMode_Phong;
|
||||
}
|
||||
else m = aiShadingMode_Gouraud;
|
||||
} else
|
||||
m = aiShadingMode_Gouraud;
|
||||
|
||||
// specular color
|
||||
aiColor3D clr = lerp(aiColor3D(1.0, 1.0, 1.0), surf.mColor, surf.mColorHighlights);
|
||||
|
@ -330,7 +311,6 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
|
|||
pcMat->AddProperty(&def, 1, AI_MATKEY_BLEND_FUNC);
|
||||
}
|
||||
|
||||
|
||||
// ADD TEXTURES to the material
|
||||
// TODO: find out how we can handle COLOR textures correctly...
|
||||
bool b = HandleTextures(pcMat, surf.mColorTextures, aiTextureType_DIFFUSE);
|
||||
|
@ -349,15 +329,12 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
|
|||
|
||||
m = aiShadingMode_Toon;
|
||||
break;
|
||||
}
|
||||
else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel") {
|
||||
} else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel") {
|
||||
ASSIMP_LOG_INFO("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
|
||||
|
||||
m = aiShadingMode_Fresnel;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ASSIMP_LOG_WARN_F("LWO2: Unknown surface shader: ", shader.functionName);
|
||||
}
|
||||
}
|
||||
|
@ -377,8 +354,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
char LWOImporter::FindUVChannels(LWO::TextureList &list,
|
||||
LWO::Layer& /*layer*/,LWO::UVChannel& uv, unsigned int next)
|
||||
{
|
||||
LWO::Layer & /*layer*/, LWO::UVChannel &uv, unsigned int next) {
|
||||
char ret = 0;
|
||||
for (auto &texture : list) {
|
||||
|
||||
|
@ -391,11 +367,9 @@ char LWOImporter::FindUVChannels(LWO::TextureList& list,
|
|||
ret = 1;
|
||||
|
||||
// got it.
|
||||
if (texture.mRealUVIndex == UINT_MAX || texture.mRealUVIndex == next)
|
||||
{
|
||||
if (texture.mRealUVIndex == UINT_MAX || texture.mRealUVIndex == next) {
|
||||
texture.mRealUVIndex = next;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// channel mismatch. need to duplicate the material.
|
||||
ASSIMP_LOG_WARN("LWO: Channel mismatch, would need to duplicate surface [design bug]");
|
||||
|
||||
|
@ -409,8 +383,7 @@ char LWOImporter::FindUVChannels(LWO::TextureList& list,
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::FindUVChannels(LWO::Surface &surf,
|
||||
LWO::SortedRep &sorted, LWO::Layer &layer,
|
||||
unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
|
||||
{
|
||||
unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]) {
|
||||
unsigned int next = 0, extra = 0, num_extra = 0;
|
||||
|
||||
// Check whether we have an UV entry != 0 for one of the faces in 'sorted'
|
||||
|
@ -429,10 +402,10 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf,
|
|||
if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
||||
|
||||
ASSIMP_LOG_ERROR("LWO: Maximum number of UV channels for "
|
||||
"this mesh reached. Skipping channel \'" + uv.name + "\'");
|
||||
"this mesh reached. Skipping channel \'" +
|
||||
uv.name + "\'");
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Search through all textures assigned to 'surf' and look for this UV channel
|
||||
char had = 0;
|
||||
had |= FindUVChannels(surf.mColorTextures, layer, uv, next);
|
||||
|
@ -474,8 +447,7 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::FindVCChannels(const LWO::Surface &surf, LWO::SortedRep &sorted, const LWO::Layer &layer,
|
||||
unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
|
||||
{
|
||||
unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]) {
|
||||
unsigned int next = 0;
|
||||
|
||||
// Check whether we have an vc entry != 0 for one of the faces in 'sorted'
|
||||
|
@ -489,8 +461,7 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte
|
|||
}
|
||||
out[0] = i;
|
||||
++next;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
|
||||
for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) {
|
||||
const LWO::Face &face = layer.mFaces[*it];
|
||||
|
@ -502,10 +473,10 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte
|
|||
if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
|
||||
|
||||
ASSIMP_LOG_ERROR("LWO: Maximum number of vertex color channels for "
|
||||
"this mesh reached. Skipping channel \'" + vc.name + "\'");
|
||||
"this mesh reached. Skipping channel \'" +
|
||||
vc.name + "\'");
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
out[next++] = i;
|
||||
}
|
||||
it = sorted.end() - 1;
|
||||
|
@ -521,11 +492,9 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
|
||||
{
|
||||
void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture &tex) {
|
||||
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
||||
while (true)
|
||||
{
|
||||
while (true) {
|
||||
if (mFileBuffer + 6 >= end) break;
|
||||
LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
|
@ -533,8 +502,7 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
|
|||
throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
|
||||
|
||||
uint8_t *const next = mFileBuffer + head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
switch (head.type) {
|
||||
case AI_LWO_PROJ:
|
||||
tex.mapMode = (Texture::MappingMode)GetU2();
|
||||
break;
|
||||
|
@ -563,37 +531,32 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex )
|
||||
{
|
||||
void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture &tex) {
|
||||
// --- not supported at the moment
|
||||
ASSIMP_LOG_ERROR("LWO2: Found procedural texture, this is not supported");
|
||||
tex.bCanUse = false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture& tex )
|
||||
{
|
||||
void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture &tex) {
|
||||
// --- not supported at the moment
|
||||
ASSIMP_LOG_ERROR("LWO2: Found gradient texture, this is not supported");
|
||||
tex.bCanUse = false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
|
||||
{
|
||||
void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture &tex) {
|
||||
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
||||
|
||||
// get the ordinal string
|
||||
GetS0(tex.ordinal, size);
|
||||
|
||||
// we could crash later if this is an empty string ...
|
||||
if (!tex.ordinal.length())
|
||||
{
|
||||
if (!tex.ordinal.length()) {
|
||||
ASSIMP_LOG_ERROR("LWO2: Ill-formed SURF.BLOK ordinal string");
|
||||
tex.ordinal = "\x00";
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
while (true) {
|
||||
if (mFileBuffer + 6 >= end) break;
|
||||
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
|
@ -601,8 +564,7 @@ void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
|
|||
throw DeadlyImportError("LWO2: Invalid texture header chunk length");
|
||||
|
||||
uint8_t *const next = mFileBuffer + head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
switch (head.type) {
|
||||
case AI_LWO_CHAN:
|
||||
tex.type = GetU4();
|
||||
break;
|
||||
|
@ -619,8 +581,7 @@ void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size )
|
||||
{
|
||||
void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader *head, unsigned int size) {
|
||||
ai_assert(!mSurfaces->empty());
|
||||
LWO::Surface &surf = mSurfaces->back();
|
||||
LWO::Texture tex;
|
||||
|
@ -630,8 +591,7 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsi
|
|||
size -= head->length + 6;
|
||||
|
||||
// now get the exact type of the texture
|
||||
switch (head->type)
|
||||
{
|
||||
switch (head->type) {
|
||||
case AI_LWO_PROC:
|
||||
LoadLWO2Procedural(size, tex);
|
||||
break;
|
||||
|
@ -644,22 +604,28 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsi
|
|||
|
||||
// get the destination channel
|
||||
TextureList *listRef = NULL;
|
||||
switch (tex.type)
|
||||
{
|
||||
switch (tex.type) {
|
||||
case AI_LWO_COLR:
|
||||
listRef = &surf.mColorTextures;break;
|
||||
listRef = &surf.mColorTextures;
|
||||
break;
|
||||
case AI_LWO_DIFF:
|
||||
listRef = &surf.mDiffuseTextures;break;
|
||||
listRef = &surf.mDiffuseTextures;
|
||||
break;
|
||||
case AI_LWO_SPEC:
|
||||
listRef = &surf.mSpecularTextures;break;
|
||||
listRef = &surf.mSpecularTextures;
|
||||
break;
|
||||
case AI_LWO_GLOS:
|
||||
listRef = &surf.mGlossinessTextures;break;
|
||||
listRef = &surf.mGlossinessTextures;
|
||||
break;
|
||||
case AI_LWO_BUMP:
|
||||
listRef = &surf.mBumpTextures;break;
|
||||
listRef = &surf.mBumpTextures;
|
||||
break;
|
||||
case AI_LWO_TRAN:
|
||||
listRef = &surf.mOpacityTextures;break;
|
||||
listRef = &surf.mOpacityTextures;
|
||||
break;
|
||||
case AI_LWO_REFL:
|
||||
listRef = &surf.mReflectionTextures;break;
|
||||
listRef = &surf.mReflectionTextures;
|
||||
break;
|
||||
default:
|
||||
ASSIMP_LOG_WARN("LWO2: Encountered unknown texture type");
|
||||
return;
|
||||
|
@ -676,8 +642,7 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsi
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, unsigned int size )
|
||||
{
|
||||
void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader * /*head*/, unsigned int size) {
|
||||
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
||||
|
||||
ai_assert(!mSurfaces->empty());
|
||||
|
@ -688,15 +653,13 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u
|
|||
GetS0(shader.ordinal, size);
|
||||
|
||||
// we could crash later if this is an empty string ...
|
||||
if (!shader.ordinal.length())
|
||||
{
|
||||
if (!shader.ordinal.length()) {
|
||||
ASSIMP_LOG_ERROR("LWO2: Ill-formed SURF.BLOK ordinal string");
|
||||
shader.ordinal = "\x00";
|
||||
}
|
||||
|
||||
// read the header
|
||||
while (true)
|
||||
{
|
||||
while (true) {
|
||||
if (mFileBuffer + 6 >= end) break;
|
||||
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
|
@ -704,8 +667,7 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u
|
|||
throw DeadlyImportError("LWO2: Invalid shader header chunk length");
|
||||
|
||||
uint8_t *const next = mFileBuffer + head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
switch (head.type) {
|
||||
case AI_LWO_ENAB:
|
||||
shader.enabled = GetU2() ? true : false;
|
||||
break;
|
||||
|
@ -727,8 +689,7 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2Surface(unsigned int size)
|
||||
{
|
||||
void LWOImporter::LoadLWO2Surface(unsigned int size) {
|
||||
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
||||
|
||||
mSurfaces->push_back(LWO::Surface());
|
||||
|
@ -741,19 +702,20 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
GetS0(derived, (unsigned int)(end - mFileBuffer));
|
||||
if (derived.length()) {
|
||||
// yes, find this surface
|
||||
for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) {
|
||||
for (SurfaceList::iterator it = mSurfaces->begin(), itEnd = mSurfaces->end() - 1; it != itEnd; ++it) {
|
||||
if ((*it).mName == derived) {
|
||||
// we have it ...
|
||||
surf = *it;
|
||||
derived.clear();break;
|
||||
derived.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (derived.size())
|
||||
if (derived.size()) {
|
||||
ASSIMP_LOG_WARN("LWO2: Unable to find source surface: " + derived);
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
while (true) {
|
||||
if (mFileBuffer + 6 >= end)
|
||||
break;
|
||||
const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
@ -762,11 +724,9 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
throw DeadlyImportError("LWO2: Invalid surface chunk length");
|
||||
|
||||
uint8_t *const next = mFileBuffer + head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
switch (head.type) {
|
||||
// diffuse color
|
||||
case AI_LWO_COLR:
|
||||
{
|
||||
case AI_LWO_COLR: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, COLR, 12);
|
||||
surf.mColor.r = GetF4();
|
||||
surf.mColor.g = GetF4();
|
||||
|
@ -774,22 +734,19 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
break;
|
||||
}
|
||||
// diffuse strength ... hopefully
|
||||
case AI_LWO_DIFF:
|
||||
{
|
||||
case AI_LWO_DIFF: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, DIFF, 4);
|
||||
surf.mDiffuseValue = GetF4();
|
||||
break;
|
||||
}
|
||||
// specular strength ... hopefully
|
||||
case AI_LWO_SPEC:
|
||||
{
|
||||
case AI_LWO_SPEC: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SPEC, 4);
|
||||
surf.mSpecularValue = GetF4();
|
||||
break;
|
||||
}
|
||||
// transparency
|
||||
case AI_LWO_TRAN:
|
||||
{
|
||||
case AI_LWO_TRAN: {
|
||||
// transparency explicitly disabled?
|
||||
if (surf.mTransparency == 10e10f)
|
||||
break;
|
||||
|
@ -799,65 +756,56 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
break;
|
||||
}
|
||||
// additive transparency
|
||||
case AI_LWO_ADTR:
|
||||
{
|
||||
case AI_LWO_ADTR: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, ADTR, 4);
|
||||
surf.mAdditiveTransparency = GetF4();
|
||||
break;
|
||||
}
|
||||
// wireframe mode
|
||||
case AI_LWO_LINE:
|
||||
{
|
||||
case AI_LWO_LINE: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, LINE, 2);
|
||||
if (GetU2() & 0x1)
|
||||
surf.mWireframe = true;
|
||||
break;
|
||||
}
|
||||
// glossiness
|
||||
case AI_LWO_GLOS:
|
||||
{
|
||||
case AI_LWO_GLOS: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, GLOS, 4);
|
||||
surf.mGlossiness = GetF4();
|
||||
break;
|
||||
}
|
||||
// bump intensity
|
||||
case AI_LWO_BUMP:
|
||||
{
|
||||
case AI_LWO_BUMP: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, BUMP, 4);
|
||||
surf.mBumpIntensity = GetF4();
|
||||
break;
|
||||
}
|
||||
// color highlights
|
||||
case AI_LWO_CLRH:
|
||||
{
|
||||
case AI_LWO_CLRH: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, CLRH, 4);
|
||||
surf.mColorHighlights = GetF4();
|
||||
break;
|
||||
}
|
||||
// index of refraction
|
||||
case AI_LWO_RIND:
|
||||
{
|
||||
case AI_LWO_RIND: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, RIND, 4);
|
||||
surf.mIOR = GetF4();
|
||||
break;
|
||||
}
|
||||
// polygon sidedness
|
||||
case AI_LWO_SIDE:
|
||||
{
|
||||
case AI_LWO_SIDE: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SIDE, 2);
|
||||
surf.bDoubleSided = (3 == GetU2());
|
||||
break;
|
||||
}
|
||||
// maximum smoothing angle
|
||||
case AI_LWO_SMAN:
|
||||
{
|
||||
case AI_LWO_SMAN: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SMAN, 4);
|
||||
surf.mMaximumSmoothAngle = std::fabs(GetF4());
|
||||
break;
|
||||
}
|
||||
// vertex color channel to be applied to the surface
|
||||
case AI_LWO_VCOL:
|
||||
{
|
||||
case AI_LWO_VCOL: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, VCOL, 12);
|
||||
surf.mDiffuseValue *= GetF4(); // strength
|
||||
ReadVSizedIntLWO2(mFileBuffer); // skip envelope
|
||||
|
@ -868,13 +816,11 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
break;
|
||||
}
|
||||
// surface bock entry
|
||||
case AI_LWO_BLOK:
|
||||
{
|
||||
case AI_LWO_BLOK: {
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, BLOK, 4);
|
||||
IFF::SubChunkHeader head2 = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
switch (head2.type)
|
||||
{
|
||||
switch (head2.type) {
|
||||
case AI_LWO_PROC:
|
||||
case AI_LWO_GRAD:
|
||||
case AI_LWO_IMAP:
|
||||
|
|
|
@ -45,22 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
* @brief Implementation of the LWS importer class
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
|
||||
|
||||
#include "LWS/LWSLoader.h"
|
||||
#include "PostProcessing/ConvertToLHProcess.h"
|
||||
#include "Common/Importer.h"
|
||||
#include "PostProcessing/ConvertToLHProcess.h"
|
||||
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <assimp/SceneCombiner.h>
|
||||
#include <assimp/GenericProperty.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <assimp/SceneCombiner.h>
|
||||
#include <assimp/SkeletonMeshBuilder.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -81,8 +80,7 @@ static const aiImporterDesc desc = {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Recursive parsing of LWS files
|
||||
void LWS::Element::Parse (const char*& buffer)
|
||||
{
|
||||
void LWS::Element::Parse(const char *&buffer) {
|
||||
for (; SkipSpacesAndLineEnd(&buffer); SkipLine(&buffer)) {
|
||||
|
||||
// begin of a new element with children
|
||||
|
@ -91,8 +89,7 @@ void LWS::Element::Parse (const char*& buffer)
|
|||
++buffer;
|
||||
SkipSpaces(&buffer);
|
||||
sub = true;
|
||||
}
|
||||
else if (*buffer == '}')
|
||||
} else if (*buffer == '}')
|
||||
return;
|
||||
|
||||
children.push_back(Element());
|
||||
|
@ -100,12 +97,12 @@ void LWS::Element::Parse (const char*& buffer)
|
|||
// copy data line - read token per token
|
||||
|
||||
const char *cur = buffer;
|
||||
while (!IsSpaceOrNewLine(*buffer)) ++buffer;
|
||||
while (!IsSpaceOrNewLine(*buffer))
|
||||
++buffer;
|
||||
children.back().tokens[0] = std::string(cur, (size_t)(buffer - cur));
|
||||
SkipSpaces(&buffer);
|
||||
|
||||
if (children.back().tokens[0] == "Plugin")
|
||||
{
|
||||
if (children.back().tokens[0] == "Plugin") {
|
||||
ASSIMP_LOG_DEBUG("LWS: Skipping over plugin-specific data");
|
||||
|
||||
// strange stuff inside Plugin/Endplugin blocks. Needn't
|
||||
|
@ -120,7 +117,8 @@ void LWS::Element::Parse (const char*& buffer)
|
|||
}
|
||||
|
||||
cur = buffer;
|
||||
while (!IsLineEnd(*buffer)) ++buffer;
|
||||
while (!IsLineEnd(*buffer))
|
||||
++buffer;
|
||||
children.back().tokens[1] = std::string(cur, (size_t)(buffer - cur));
|
||||
|
||||
// parse more elements recursively
|
||||
|
@ -131,28 +129,25 @@ void LWS::Element::Parse (const char*& buffer)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
LWSImporter::LWSImporter()
|
||||
: configSpeedFlag(),
|
||||
LWSImporter::LWSImporter() :
|
||||
configSpeedFlag(),
|
||||
io(),
|
||||
first(),
|
||||
last(),
|
||||
fps(),
|
||||
noSkeletonMesh()
|
||||
{
|
||||
noSkeletonMesh() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
LWSImporter::~LWSImporter()
|
||||
{
|
||||
LWSImporter::~LWSImporter() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool checkSig) const
|
||||
{
|
||||
bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
|
||||
const std::string extension = GetExtension(pFile);
|
||||
if (extension == "lws" || extension == "mot")
|
||||
return true;
|
||||
|
@ -169,15 +164,13 @@ bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool c
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get list of file extensions
|
||||
const aiImporterDesc* LWSImporter::GetInfo () const
|
||||
{
|
||||
const aiImporterDesc *LWSImporter::GetInfo() const {
|
||||
return &desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties
|
||||
void LWSImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
void LWSImporter::SetupProperties(const Importer *pImp) {
|
||||
// AI_CONFIG_FAVOUR_SPEED
|
||||
configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0));
|
||||
|
||||
|
@ -198,15 +191,15 @@ void LWSImporter::SetupProperties(const Importer* pImp)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Read an envelope description
|
||||
void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
|
||||
{
|
||||
void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
|
||||
if (dad.children.empty()) {
|
||||
ASSIMP_LOG_ERROR("LWS: Envelope descriptions must not be empty");
|
||||
return;
|
||||
}
|
||||
|
||||
// reserve enough storage
|
||||
std::list< LWS::Element >::const_iterator it = dad.children.begin();;
|
||||
std::list<LWS::Element>::const_iterator it = dad.children.begin();
|
||||
;
|
||||
fill.keys.reserve(strtoul10(it->tokens[1].c_str()));
|
||||
|
||||
for (++it; it != dad.children.end(); ++it) {
|
||||
|
@ -255,8 +248,7 @@ void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
|
|||
SkipSpaces(&c);
|
||||
c = fast_atoreal_move<float>(c, key.params[i]);
|
||||
}
|
||||
}
|
||||
else if ((*it).tokens[0] == "Behaviors") {
|
||||
} else if ((*it).tokens[0] == "Behaviors") {
|
||||
SkipSpaces(&c);
|
||||
fill.pre = (LWO::PrePostBehaviour)strtoul10(c, &c);
|
||||
SkipSpaces(&c);
|
||||
|
@ -271,8 +263,7 @@ void LWSImporter::ReadEnvelope_Old(
|
|||
std::list<LWS::Element>::const_iterator &it,
|
||||
const std::list<LWS::Element>::const_iterator &end,
|
||||
LWS::NodeDesc &nodes,
|
||||
unsigned int /*version*/)
|
||||
{
|
||||
unsigned int /*version*/) {
|
||||
unsigned int num, sub_num;
|
||||
if (++it == end) goto unexpected_end;
|
||||
|
||||
|
@ -311,8 +302,7 @@ unexpected_end:
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup a nice name for a node
|
||||
void LWSImporter::SetupNodeName(aiNode* nd, LWS::NodeDesc& src)
|
||||
{
|
||||
void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
|
||||
const unsigned int combined = src.number | ((unsigned int)src.type) << 28u;
|
||||
|
||||
// the name depends on the type. We break LWS's strange naming convention
|
||||
|
@ -323,7 +313,8 @@ void LWSImporter::SetupNodeName(aiNode* nd, LWS::NodeDesc& src)
|
|||
std::string::size_type s = src.path.find_last_of("\\/");
|
||||
if (s == std::string::npos)
|
||||
s = 0;
|
||||
else ++s;
|
||||
else
|
||||
++s;
|
||||
std::string::size_type t = src.path.substr(s).find_last_of(".");
|
||||
|
||||
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
|
||||
|
@ -339,8 +330,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
|
|||
BatchLoader &batch,
|
||||
aiCamera **&camOut,
|
||||
aiLight **&lightOut,
|
||||
std::vector<aiNodeAnim*>& animOut)
|
||||
{
|
||||
std::vector<aiNodeAnim *> &animOut) {
|
||||
// Setup a very cryptic name for the node, we want the user to be happy
|
||||
SetupNodeName(nd, src);
|
||||
aiNode *ndAnim = nd;
|
||||
|
@ -354,8 +344,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
|
|||
obj = batch.GetImport(src.id);
|
||||
if (!obj) {
|
||||
ASSIMP_LOG_ERROR("LWS: Failed to read external file " + src.path);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (obj->mRootNode->mNumChildren == 1) {
|
||||
|
||||
//If the pivot is not set for this layer, get it from the external object
|
||||
|
@ -418,11 +407,10 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
|
|||
lit->mAngleInnerCone = (float)AI_DEG_TO_RAD(src.lightConeAngle);
|
||||
lit->mAngleOuterCone = lit->mAngleInnerCone + (float)AI_DEG_TO_RAD(src.lightEdgeAngle);
|
||||
|
||||
}
|
||||
else if (src.lightType == 1) { /* directional light source */
|
||||
} else if (src.lightType == 1) { /* directional light source */
|
||||
lit->mType = aiLightSource_DIRECTIONAL;
|
||||
}
|
||||
else lit->mType = aiLightSource_POINT;
|
||||
} else
|
||||
lit->mType = aiLightSource_POINT;
|
||||
|
||||
// fixme: no proper handling of light falloffs yet
|
||||
if (src.lightFalloffType == 1)
|
||||
|
@ -471,15 +459,13 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Determine the exact location of a LWO file
|
||||
std::string LWSImporter::FindLWOFile(const std::string& in)
|
||||
{
|
||||
std::string LWSImporter::FindLWOFile(const std::string &in) {
|
||||
// insert missing directory separator if necessary
|
||||
std::string tmp;
|
||||
if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
|
||||
{
|
||||
if (in.length() > 3 && in[1] == ':' && in[2] != '\\' && in[2] != '/') {
|
||||
tmp = in[0] + (std::string(":\\") + in.substr(2));
|
||||
}
|
||||
else tmp = in;
|
||||
} else
|
||||
tmp = in;
|
||||
|
||||
if (io->Exists(tmp)) {
|
||||
return in;
|
||||
|
@ -503,7 +489,6 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
|
|||
return test;
|
||||
}
|
||||
|
||||
|
||||
// return original path, maybe the IOsystem knows better
|
||||
return tmp;
|
||||
}
|
||||
|
@ -511,8 +496,7 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Read file into given scene data structure
|
||||
void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene,
|
||||
IOSystem* pIOHandler)
|
||||
{
|
||||
IOSystem *pIOHandler) {
|
||||
io = pIOHandler;
|
||||
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
|
||||
|
||||
|
@ -526,7 +510,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
TextFileToBuffer(file.get(), mBuffer);
|
||||
|
||||
// Parse the file structure
|
||||
LWS::Element root; const char* dummy = &mBuffer[0];
|
||||
LWS::Element root;
|
||||
const char *dummy = &mBuffer[0];
|
||||
root.Parse(dummy);
|
||||
|
||||
// Construct a Batchimporter to read more files recursively
|
||||
|
@ -594,8 +579,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (version >= 4) { // handle LWSC 4 explicit ID
|
||||
SkipSpaces(&c);
|
||||
d.number = strtoul16(c, &c) & AI_LWS_MASK;
|
||||
}
|
||||
else d.number = cur_object++;
|
||||
} else
|
||||
d.number = cur_object++;
|
||||
|
||||
// and add the file to the import list
|
||||
SkipSpaces(&c);
|
||||
|
@ -616,8 +601,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (version >= 4) { // handle LWSC 4 explicit ID
|
||||
d.number = strtoul16(c, &c) & AI_LWS_MASK;
|
||||
SkipSpaces(&c);
|
||||
}
|
||||
else d.number = cur_object++;
|
||||
} else
|
||||
d.number = cur_object++;
|
||||
std::string path = FindLWOFile(c);
|
||||
d.id = batch.AddLoadRequest(path, 0, NULL);
|
||||
|
||||
|
@ -634,8 +619,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (version >= 4) { // handle LWSC 4 explicit ID
|
||||
d.number = strtoul16(c, &c) & AI_LWS_MASK;
|
||||
SkipSpaces(&c);
|
||||
}
|
||||
else d.number = cur_object++;
|
||||
} else
|
||||
d.number = cur_object++;
|
||||
d.name = c;
|
||||
nodes.push_back(d);
|
||||
|
||||
|
@ -695,11 +680,13 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (nodes.empty())
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Pre/PostBehavior'");
|
||||
else {
|
||||
for (std::list<LWO::Envelope>::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) {
|
||||
for (std::list<LWO::Envelope>::iterator envelopeIt = nodes.back().channels.begin(); envelopeIt != nodes.back().channels.end(); ++envelopeIt) {
|
||||
// two ints per envelope
|
||||
LWO::Envelope& env = *it;
|
||||
env.pre = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
|
||||
env.post = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
|
||||
LWO::Envelope &env = *envelopeIt;
|
||||
env.pre = (LWO::PrePostBehaviour)strtoul10(c, &c);
|
||||
SkipSpaces(&c);
|
||||
env.post = (LWO::PrePostBehaviour)strtoul10(c, &c);
|
||||
SkipSpaces(&c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -708,7 +695,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (nodes.empty())
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentItem\'");
|
||||
|
||||
else nodes.back().parent = strtoul16(c,&c);
|
||||
else
|
||||
nodes.back().parent = strtoul16(c, &c);
|
||||
}
|
||||
// 'ParentObject': deprecated one for older formats
|
||||
else if (version < 3 && (*it).tokens[0] == "ParentObject") {
|
||||
|
@ -728,8 +716,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
|
||||
if (version >= 4) { // handle LWSC 4 explicit ID
|
||||
d.number = strtoul16(c, &c) & AI_LWS_MASK;
|
||||
}
|
||||
else d.number = cur_camera++;
|
||||
} else
|
||||
d.number = cur_camera++;
|
||||
nodes.push_back(d);
|
||||
|
||||
num_camera++;
|
||||
|
@ -739,7 +727,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA)
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'CameraName\'");
|
||||
|
||||
else nodes.back().name = c;
|
||||
else
|
||||
nodes.back().name = c;
|
||||
}
|
||||
// 'AddLight': add a light to the scenegraph
|
||||
else if ((*it).tokens[0] == "AddLight") {
|
||||
|
@ -750,8 +739,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
|
||||
if (version >= 4) { // handle LWSC 4 explicit ID
|
||||
d.number = strtoul16(c, &c) & AI_LWS_MASK;
|
||||
}
|
||||
else d.number = cur_light++;
|
||||
} else
|
||||
d.number = cur_light++;
|
||||
nodes.push_back(d);
|
||||
|
||||
num_light++;
|
||||
|
@ -761,14 +750,16 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightName\'");
|
||||
|
||||
else nodes.back().name = c;
|
||||
else
|
||||
nodes.back().name = c;
|
||||
}
|
||||
// 'LightIntensity': set intensity of currently active light
|
||||
else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity") {
|
||||
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightIntensity\'");
|
||||
|
||||
else fast_atoreal_move<float>(c, nodes.back().lightIntensity );
|
||||
else
|
||||
fast_atoreal_move<float>(c, nodes.back().lightIntensity);
|
||||
|
||||
}
|
||||
// 'LightType': set type of currently active light
|
||||
|
@ -776,7 +767,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightType\'");
|
||||
|
||||
else nodes.back().lightType = strtoul10(c);
|
||||
else
|
||||
nodes.back().lightType = strtoul10(c);
|
||||
|
||||
}
|
||||
// 'LightFalloffType': set falloff type of currently active light
|
||||
|
@ -784,7 +776,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightFalloffType\'");
|
||||
|
||||
else nodes.back().lightFalloffType = strtoul10(c);
|
||||
else
|
||||
nodes.back().lightFalloffType = strtoul10(c);
|
||||
|
||||
}
|
||||
// 'LightConeAngle': set cone angle of currently active light
|
||||
|
@ -792,7 +785,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightConeAngle\'");
|
||||
|
||||
else nodes.back().lightConeAngle = fast_atof(c);
|
||||
else
|
||||
nodes.back().lightConeAngle = fast_atof(c);
|
||||
|
||||
}
|
||||
// 'LightEdgeAngle': set area where we're smoothing from min to max intensity
|
||||
|
@ -800,7 +794,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
|
||||
ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightEdgeAngle\'");
|
||||
|
||||
else nodes.back().lightEdgeAngle = fast_atof(c);
|
||||
else
|
||||
nodes.back().lightEdgeAngle = fast_atof(c);
|
||||
|
||||
}
|
||||
// 'LightColor': set color of currently active light
|
||||
|
@ -834,32 +829,33 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
}
|
||||
|
||||
// resolve parenting
|
||||
for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
|
||||
for (std::list<LWS::NodeDesc>::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) {
|
||||
|
||||
// check whether there is another node which calls us a parent
|
||||
for (std::list<LWS::NodeDesc>::iterator dit = nodes.begin(); dit != nodes.end(); ++dit) {
|
||||
if (dit != it && *it == (*dit).parent) {
|
||||
if (dit != ndIt && *ndIt == (*dit).parent) {
|
||||
if ((*dit).parent_resolved) {
|
||||
// fixme: it's still possible to produce an overflow due to cross references ..
|
||||
ASSIMP_LOG_ERROR("LWS: Found cross reference in scene-graph");
|
||||
continue;
|
||||
}
|
||||
|
||||
(*it).children.push_back(&*dit);
|
||||
(*dit).parent_resolved = &*it;
|
||||
ndIt->children.push_back(&*dit);
|
||||
(*dit).parent_resolved = &*ndIt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find out how many nodes have no parent yet
|
||||
unsigned int no_parent = 0;
|
||||
for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
|
||||
if (!(*it).parent_resolved)
|
||||
for (std::list<LWS::NodeDesc>::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) {
|
||||
if (!ndIt->parent_resolved) {
|
||||
++no_parent;
|
||||
}
|
||||
if (!no_parent)
|
||||
}
|
||||
if (!no_parent) {
|
||||
throw DeadlyImportError("LWS: Unable to find scene root node");
|
||||
|
||||
}
|
||||
|
||||
// Load all subsequent files
|
||||
batch.LoadAll();
|
||||
|
@ -884,14 +880,14 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
|
||||
nd->mName.Set("<LWSRoot>");
|
||||
nd->mChildren = new aiNode *[no_parent];
|
||||
for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
|
||||
if (!(*it).parent_resolved) {
|
||||
for (std::list<LWS::NodeDesc>::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) {
|
||||
if (!ndIt->parent_resolved) {
|
||||
aiNode *ro = nd->mChildren[nd->mNumChildren++] = new aiNode();
|
||||
ro->mParent = nd;
|
||||
|
||||
// ... and build the scene graph. If we encounter object nodes,
|
||||
// add then to our attachment table.
|
||||
BuildGraph(ro,*it, attach, batch, cams, lights, anims);
|
||||
BuildGraph(ro, *ndIt, attach, batch, cams, lights, anims);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -920,7 +916,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
// OK ... finally build the output graph
|
||||
SceneCombiner::MergeScenes(&pScene, master, attach,
|
||||
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
|
||||
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0));
|
||||
AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) :
|
||||
0));
|
||||
|
||||
// Check flags
|
||||
if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
|
||||
|
@ -931,7 +928,6 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
SkeletonMeshBuilder builder(pScene);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_LWS_IMPORTER
|
||||
|
|
|
@ -56,9 +56,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/Importer.hpp>
|
||||
#include <memory>
|
||||
|
||||
#include "M3DWrapper.h"
|
||||
#include "M3DImporter.h"
|
||||
#include "M3DMaterials.h"
|
||||
#include "M3DWrapper.h"
|
||||
|
||||
// RESOURCES:
|
||||
// https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md
|
||||
|
@ -256,9 +256,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) {
|
|||
|
||||
for (i = 0; i < m3d->nummaterial; i++) {
|
||||
m = &m3d->material[i];
|
||||
aiMaterial *mat = new aiMaterial;
|
||||
aiMaterial *newMat = new aiMaterial;
|
||||
name.Set(std::string(m->name));
|
||||
mat->AddProperty(&name, AI_MATKEY_NAME);
|
||||
newMat->AddProperty(&name, AI_MATKEY_NAME);
|
||||
for (j = 0; j < m->numprop; j++) {
|
||||
// look up property type
|
||||
// 0 - 127 scalar values,
|
||||
|
@ -271,29 +271,36 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) {
|
|||
break;
|
||||
}
|
||||
// should never happen, but be safe than sorry
|
||||
if (k == 256) continue;
|
||||
if (k == 256)
|
||||
continue;
|
||||
|
||||
// scalar properties
|
||||
if (m->prop[j].type < 128 && aiProps[k].pKey) {
|
||||
switch (m3d_propertytypes[k].format) {
|
||||
case m3dpf_color:
|
||||
c = mkColor(m->prop[j].value.color);
|
||||
mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index);
|
||||
newMat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index);
|
||||
break;
|
||||
case m3dpf_float:
|
||||
f = m->prop[j].value.fnum;
|
||||
mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index);
|
||||
newMat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index);
|
||||
break;
|
||||
default:
|
||||
n = m->prop[j].value.num;
|
||||
if (m->prop[j].type == m3dp_il) {
|
||||
switch (n) {
|
||||
case 0: n = aiShadingMode_NoShading; break;
|
||||
case 2: n = aiShadingMode_Phong; break;
|
||||
default: n = aiShadingMode_Gouraud; break;
|
||||
case 0:
|
||||
n = aiShadingMode_NoShading;
|
||||
break;
|
||||
case 2:
|
||||
n = aiShadingMode_Phong;
|
||||
break;
|
||||
default:
|
||||
n = aiShadingMode_Gouraud;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index);
|
||||
newMat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -403,7 +410,6 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) {
|
|||
ai_assert(m3d);
|
||||
ai_assert(mScene->mRootNode != nullptr);
|
||||
|
||||
|
||||
for (i = 0; i < m3d->numface; i++) {
|
||||
// we must switch mesh if material changes
|
||||
if (lastMat != m3d->face[i].materialid) {
|
||||
|
|
|
@ -100,6 +100,10 @@ M3DWrapper::M3DWrapper() {
|
|||
}
|
||||
|
||||
M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) {
|
||||
if (nullptr == pIOHandler) {
|
||||
ai_assert(nullptr != pIOHandler);
|
||||
}
|
||||
|
||||
#ifdef ASSIMP_USE_M3D_READFILECB
|
||||
// pass this IOHandler to the C callback in a thread-local pointer
|
||||
m3dimporter_pIOHandler = pIOHandler;
|
||||
|
|
|
@ -99,6 +99,10 @@ typedef uint16_t M3D_INDEX;
|
|||
#define _register
|
||||
#endif
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127 )
|
||||
#pragma warning(disable : 4505 )
|
||||
|
||||
/*** File format structures ***/
|
||||
|
||||
/**
|
||||
|
@ -2162,8 +2166,8 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
|||
w = h = len = 0;
|
||||
ri.bits_per_channel = 8;
|
||||
model->texture[i].d = (uint8_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, 0, &ri);
|
||||
model->texture[i].w = w;
|
||||
model->texture[i].h = h;
|
||||
model->texture[i].w = (uint16_t) w;
|
||||
model->texture[i].h = (uint16_t) h;
|
||||
model->texture[i].f = (uint8_t)len;
|
||||
#endif
|
||||
} else {
|
||||
|
@ -5605,6 +5609,9 @@ namespace M3D {
|
|||
|
||||
#endif /* impl */
|
||||
}
|
||||
|
||||
#pragma warning(pop<)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -45,21 +45,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
* @brief Implementation of the MD5 importer class
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
|
||||
|
||||
// internal headers
|
||||
#include <assimp/RemoveComments.h>
|
||||
#include "MD5Loader.h"
|
||||
#include <assimp/MathFunctions.h>
|
||||
#include <assimp/RemoveComments.h>
|
||||
#include <assimp/SkeletonMeshBuilder.h>
|
||||
#include <assimp/StringComparison.h>
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <assimp/MathFunctions.h>
|
||||
#include <assimp/SkeletonMeshBuilder.h>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <memory>
|
||||
|
||||
using namespace Assimp;
|
||||
|
@ -67,7 +66,6 @@ using namespace Assimp;
|
|||
// Minimum weight value. Weights inside [-n ... n] are ignored
|
||||
#define AI_MD5_WEIGHT_EPSILON Math::getEpsilon<float>()
|
||||
|
||||
|
||||
static const aiImporterDesc desc = {
|
||||
"Doom 3 / MD5 Mesh Importer",
|
||||
"",
|
||||
|
@ -83,28 +81,20 @@ static const aiImporterDesc desc = {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
MD5Importer::MD5Importer()
|
||||
: mIOHandler()
|
||||
, mBuffer()
|
||||
, fileSize()
|
||||
, iLineNumber()
|
||||
, pScene()
|
||||
, pIOHandler()
|
||||
, bHadMD5Mesh()
|
||||
, bHadMD5Anim()
|
||||
, bHadMD5Camera()
|
||||
, configNoAutoLoad (false)
|
||||
{}
|
||||
MD5Importer::MD5Importer() :
|
||||
mIOHandler(nullptr), mBuffer(), fileSize(), iLineNumber(), pScene(), bHadMD5Mesh(), bHadMD5Anim(), bHadMD5Camera(), configNoAutoLoad(false) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
MD5Importer::~MD5Importer()
|
||||
{}
|
||||
MD5Importer::~MD5Importer() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool MD5Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
||||
{
|
||||
bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
|
||||
const std::string extension = GetExtension(pFile);
|
||||
|
||||
if (extension == "md5anim" || extension == "md5mesh" || extension == "md5camera")
|
||||
|
@ -121,15 +111,13 @@ bool MD5Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get list of all supported extensions
|
||||
const aiImporterDesc* MD5Importer::GetInfo () const
|
||||
{
|
||||
const aiImporterDesc *MD5Importer::GetInfo() const {
|
||||
return &desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup import properties
|
||||
void MD5Importer::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
void MD5Importer::SetupProperties(const Importer *pImp) {
|
||||
// AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD
|
||||
configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0));
|
||||
}
|
||||
|
@ -137,9 +125,8 @@ void MD5Importer::SetupProperties(const Importer* pImp)
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void MD5Importer::InternReadFile(const std::string &pFile,
|
||||
aiScene* _pScene, IOSystem* _pIOHandler)
|
||||
{
|
||||
pIOHandler = _pIOHandler;
|
||||
aiScene *_pScene, IOSystem *pIOHandler) {
|
||||
mIOHandler = pIOHandler;
|
||||
pScene = _pScene;
|
||||
bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false;
|
||||
|
||||
|
@ -151,25 +138,21 @@ void MD5Importer::InternReadFile( const std::string& pFile,
|
|||
try {
|
||||
if (extension == "md5camera") {
|
||||
LoadMD5CameraFile();
|
||||
}
|
||||
else if (configNoAutoLoad || extension == "md5anim") {
|
||||
} else if (configNoAutoLoad || extension == "md5anim") {
|
||||
// determine file extension and process just *one* file
|
||||
if (extension.length() == 0) {
|
||||
throw DeadlyImportError("Failure, need file extension to determine MD5 part type");
|
||||
}
|
||||
if (extension == "md5anim") {
|
||||
LoadMD5AnimFile();
|
||||
}
|
||||
else if (extension == "md5mesh") {
|
||||
} else if (extension == "md5mesh") {
|
||||
LoadMD5MeshFile();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LoadMD5MeshFile();
|
||||
LoadMD5AnimFile();
|
||||
}
|
||||
}
|
||||
catch ( ... ) { // std::exception, Assimp::DeadlyImportError
|
||||
} catch (...) { // std::exception, Assimp::DeadlyImportError
|
||||
UnloadFileFromMemory();
|
||||
throw;
|
||||
}
|
||||
|
@ -194,8 +177,7 @@ void MD5Importer::InternReadFile( const std::string& pFile,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Load a file into a memory buffer
|
||||
void MD5Importer::LoadFileIntoMemory (IOStream* file)
|
||||
{
|
||||
void MD5Importer::LoadFileIntoMemory(IOStream *file) {
|
||||
// unload the previous buffer, if any
|
||||
UnloadFileFromMemory();
|
||||
|
||||
|
@ -217,8 +199,7 @@ void MD5Importer::LoadFileIntoMemory (IOStream* file)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Unload the current memory buffer
|
||||
void MD5Importer::UnloadFileFromMemory ()
|
||||
{
|
||||
void MD5Importer::UnloadFileFromMemory() {
|
||||
// delete the file buffer
|
||||
delete[] mBuffer;
|
||||
mBuffer = NULL;
|
||||
|
@ -227,8 +208,7 @@ void MD5Importer::UnloadFileFromMemory ()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Build unique vertices
|
||||
void MD5Importer::MakeDataUnique (MD5::MeshDesc& meshSrc)
|
||||
{
|
||||
void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) {
|
||||
std::vector<bool> abHad(meshSrc.mVertices.size(), false);
|
||||
|
||||
// allocate enough storage to keep the output structures
|
||||
|
@ -252,8 +232,8 @@ void MD5Importer::MakeDataUnique (MD5::MeshDesc& meshSrc)
|
|||
// generate a new vertex
|
||||
meshSrc.mVertices[iNewIndex] = meshSrc.mVertices[face.mIndices[i]];
|
||||
face.mIndices[i] = iNewIndex++;
|
||||
}
|
||||
else abHad[face.mIndices[i]] = true;
|
||||
} else
|
||||
abHad[face.mIndices[i]] = true;
|
||||
}
|
||||
// swap face order
|
||||
std::swap(face.mIndices[0], face.mIndices[2]);
|
||||
|
@ -262,8 +242,7 @@ void MD5Importer::MakeDataUnique (MD5::MeshDesc& meshSrc)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Recursive node graph construction from a MD5MESH
|
||||
void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bones)
|
||||
{
|
||||
void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones) {
|
||||
ai_assert(NULL != piParent && !piParent->mNumChildren);
|
||||
|
||||
// First find out how many children we'll have
|
||||
|
@ -313,8 +292,7 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Recursive node graph construction from a MD5ANIM
|
||||
void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList& bones,const aiNodeAnim** node_anims)
|
||||
{
|
||||
void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneList &bones, const aiNodeAnim **node_anims) {
|
||||
ai_assert(NULL != piParent && !piParent->mNumChildren);
|
||||
|
||||
// First find out how many children we'll have
|
||||
|
@ -327,8 +305,7 @@ void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList
|
|||
piParent->mChildren = new aiNode *[piParent->mNumChildren];
|
||||
for (int i = 0; i < (int)bones.size(); ++i) {
|
||||
// (avoid infinite recursion)
|
||||
if (iParentID != i && bones[i].mParentIndex == iParentID)
|
||||
{
|
||||
if (iParentID != i && bones[i].mParentIndex == iParentID) {
|
||||
aiNode *pc;
|
||||
// setup a new node
|
||||
*piParent->mChildren++ = pc = new aiNode();
|
||||
|
@ -337,7 +314,8 @@ void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList
|
|||
|
||||
// get the corresponding animation channel and its first frame
|
||||
const aiNodeAnim **cur = node_anims;
|
||||
while ((**cur).mNodeName != pc->mName)++cur;
|
||||
while ((**cur).mNodeName != pc->mName)
|
||||
++cur;
|
||||
|
||||
aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue, pc->mTransformation);
|
||||
pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix());
|
||||
|
@ -353,13 +331,12 @@ void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Load a MD5MESH file
|
||||
void MD5Importer::LoadMD5MeshFile ()
|
||||
{
|
||||
void MD5Importer::LoadMD5MeshFile() {
|
||||
std::string pFile = mFile + "md5mesh";
|
||||
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
|
||||
std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb"));
|
||||
|
||||
// Check whether we can read from the file
|
||||
if( file.get() == NULL || !file->FileSize()) {
|
||||
if (file.get() == nullptr || !file->FileSize()) {
|
||||
ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile);
|
||||
return;
|
||||
}
|
||||
|
@ -442,8 +419,7 @@ void MD5Importer::LoadMD5MeshFile ()
|
|||
::memset(piCount, 0, sizeof(unsigned int) * meshParser.mJoints.size());
|
||||
|
||||
for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) {
|
||||
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
|
||||
{
|
||||
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) {
|
||||
MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
|
||||
/* FIX for some invalid exporters */
|
||||
if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON))
|
||||
|
@ -458,8 +434,7 @@ void MD5Importer::LoadMD5MeshFile ()
|
|||
if (mesh->mNumBones) // just for safety
|
||||
{
|
||||
mesh->mBones = new aiBone *[mesh->mNumBones];
|
||||
for (unsigned int q = 0,h = 0; q < meshParser.mJoints.size();++q)
|
||||
{
|
||||
for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) {
|
||||
if (!piCount[q]) continue;
|
||||
aiBone *p = mesh->mBones[h] = new aiBone();
|
||||
p->mNumWeights = piCount[q];
|
||||
|
@ -561,8 +536,7 @@ void MD5Importer::LoadMD5MeshFile ()
|
|||
|
||||
// set this also as material name
|
||||
mat->AddProperty(&meshSrc.mShader, AI_MATKEY_NAME);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
mat->AddProperty(&meshSrc.mShader, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
}
|
||||
mesh->mMaterialIndex = n++;
|
||||
|
@ -572,10 +546,9 @@ void MD5Importer::LoadMD5MeshFile ()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Load an MD5ANIM file
|
||||
void MD5Importer::LoadMD5AnimFile ()
|
||||
{
|
||||
void MD5Importer::LoadMD5AnimFile() {
|
||||
std::string pFile = mFile + "md5anim";
|
||||
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
|
||||
std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb"));
|
||||
|
||||
// Check whether we can read from the file
|
||||
if (!file.get() || !file->FileSize()) {
|
||||
|
@ -594,8 +567,7 @@ void MD5Importer::LoadMD5AnimFile ()
|
|||
if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() ||
|
||||
animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
|
||||
ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
bHadMD5Anim = true;
|
||||
|
||||
pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations = 1];
|
||||
|
@ -622,14 +594,12 @@ void MD5Importer::LoadMD5AnimFile ()
|
|||
// now process all values in there ... read all joints
|
||||
MD5::BaseFrameDesc *pcBaseFrame = &animParser.mBaseFrames[0];
|
||||
for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end(); ++iter2,
|
||||
++pcAnimNode,++pcBaseFrame)
|
||||
{
|
||||
++pcAnimNode, ++pcBaseFrame) {
|
||||
if ((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) {
|
||||
|
||||
// Allow for empty frames
|
||||
if ((*iter2).iFlags != 0) {
|
||||
throw DeadlyImportError("MD5: Keyframe index is out of range");
|
||||
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -644,16 +614,16 @@ void MD5Importer::LoadMD5AnimFile ()
|
|||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
if ((*iter2).iFlags & (1u << i)) {
|
||||
vKey->mValue[i] = *fpCur++;
|
||||
}
|
||||
else vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i];
|
||||
} else
|
||||
vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i];
|
||||
}
|
||||
|
||||
// orientation component
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
if ((*iter2).iFlags & (8u << i)) {
|
||||
vTemp[i] = *fpCur++;
|
||||
}
|
||||
else vTemp[i] = pcBaseFrame->vRotationQuat[i];
|
||||
} else
|
||||
vTemp[i] = pcBaseFrame->vRotationQuat[i];
|
||||
}
|
||||
|
||||
MD5::ConvertQuaternion(vTemp, qKey->mValue);
|
||||
|
@ -683,10 +653,9 @@ void MD5Importer::LoadMD5AnimFile ()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Load an MD5CAMERA file
|
||||
void MD5Importer::LoadMD5CameraFile ()
|
||||
{
|
||||
void MD5Importer::LoadMD5CameraFile() {
|
||||
std::string pFile = mFile + "md5camera";
|
||||
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
|
||||
std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb"));
|
||||
|
||||
// Check whether we can read from the file
|
||||
if (!file.get() || !file->FileSize()) {
|
||||
|
@ -727,8 +696,7 @@ void MD5Importer::LoadMD5CameraFile ()
|
|||
if (!cuts.size()) {
|
||||
cuts.push_back(0);
|
||||
cuts.push_back(static_cast<unsigned int>(frames.size() - 1));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cuts.insert(cuts.begin(), 0);
|
||||
|
||||
if (cuts.back() < frames.size() - 1)
|
||||
|
|
|
@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/** @file MD5Loader.h
|
||||
* @brief Definition of the .MD5 importer class.
|
||||
* http://www.modwiki.net/wiki/MD5_(file_format)
|
||||
|
@ -48,8 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_MD5LOADER_H_INCLUDED
|
||||
#define AI_MD5LOADER_H_INCLUDED
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include "MD5Parser.h"
|
||||
#include <assimp/BaseImporter.h>
|
||||
|
||||
#include <assimp/types.h>
|
||||
|
||||
|
@ -64,15 +63,11 @@ using namespace Assimp::MD5;
|
|||
// ---------------------------------------------------------------------------
|
||||
/** Importer class for the MD5 file format
|
||||
*/
|
||||
class MD5Importer : public BaseImporter
|
||||
{
|
||||
class MD5Importer : public BaseImporter {
|
||||
public:
|
||||
MD5Importer();
|
||||
~MD5Importer();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the class can handle the format of the given file.
|
||||
* See BaseImporter::CanRead() for details.
|
||||
|
@ -81,7 +76,6 @@ public:
|
|||
bool checkSig) const;
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Return importer meta information.
|
||||
* See #BaseImporter::GetInfo for the details
|
||||
|
@ -102,9 +96,6 @@ protected:
|
|||
void InternReadFile(const std::string &pFile, aiScene *pScene,
|
||||
IOSystem *pIOHandler);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Load a *.MD5MESH file.
|
||||
*/
|
||||
|
@ -154,7 +145,6 @@ protected:
|
|||
void LoadFileIntoMemory(IOStream *pFile);
|
||||
void UnloadFileFromMemory();
|
||||
|
||||
|
||||
/** IOSystem to be used to access files */
|
||||
IOSystem *mIOHandler;
|
||||
|
||||
|
@ -174,9 +164,6 @@ protected:
|
|||
/** Scene to be filled */
|
||||
aiScene *pScene;
|
||||
|
||||
/** (Custom) I/O handler implementation */
|
||||
IOSystem* pIOHandler;
|
||||
|
||||
/** true if a MD5MESH file has already been parsed */
|
||||
bool bHadMD5Mesh;
|
||||
|
||||
|
|
|
@ -817,20 +817,20 @@ void HL1MDLLoader::read_meshes() {
|
|||
mesh_faces.reserve(num_faces);
|
||||
|
||||
if (is_triangle_fan) {
|
||||
for (int i = 0; i < num_faces; ++i) {
|
||||
for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) {
|
||||
mesh_faces.push_back(HL1MeshFace{
|
||||
tricmds[0],
|
||||
tricmds[i + 1],
|
||||
tricmds[i + 2] });
|
||||
tricmds[faceIdx + 1],
|
||||
tricmds[faceIdx + 2] });
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num_faces; ++i) {
|
||||
for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) {
|
||||
if (i & 1) {
|
||||
// Preserve winding order.
|
||||
mesh_faces.push_back(HL1MeshFace{
|
||||
tricmds[i + 1],
|
||||
tricmds[i],
|
||||
tricmds[i + 2] });
|
||||
tricmds[faceIdx + 1],
|
||||
tricmds[faceIdx],
|
||||
tricmds[faceIdx + 2] });
|
||||
} else {
|
||||
mesh_faces.push_back(HL1MeshFace{
|
||||
tricmds[i],
|
||||
|
@ -1122,10 +1122,10 @@ void HL1MDLLoader::read_sequence_infos() {
|
|||
aiNode *blend_controller_node = blend_controllers_node->mChildren[j] = new aiNode();
|
||||
blend_controller_node->mParent = blend_controllers_node;
|
||||
|
||||
aiMetadata *md = blend_controller_node->mMetaData = aiMetadata::Alloc(3);
|
||||
md->Set(0, "Start", pseqdesc->blendstart[j]);
|
||||
md->Set(1, "End", pseqdesc->blendend[j]);
|
||||
md->Set(2, "MotionFlags", pseqdesc->blendtype[j]);
|
||||
aiMetadata *metaData = blend_controller_node->mMetaData = aiMetadata::Alloc(3);
|
||||
metaData->Set(0, "Start", pseqdesc->blendstart[j]);
|
||||
metaData->Set(1, "End", pseqdesc->blendend[j]);
|
||||
metaData->Set(2, "MotionFlags", pseqdesc->blendtype[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1151,10 +1151,10 @@ void HL1MDLLoader::read_sequence_infos() {
|
|||
aiNode *pEvent = pEventsNode->mChildren[j] = new aiNode();
|
||||
pEvent->mParent = pEventsNode;
|
||||
|
||||
aiMetadata *md = pEvent->mMetaData = aiMetadata::Alloc(3);
|
||||
md->Set(0, "Frame", pevent->frame);
|
||||
md->Set(1, "ScriptEvent", pevent->event);
|
||||
md->Set(2, "Options", aiString(pevent->options));
|
||||
aiMetadata *metaData = pEvent->mMetaData = aiMetadata::Alloc(3);
|
||||
metaData->Set(0, "Frame", pevent->frame);
|
||||
metaData->Set(1, "ScriptEvent", pevent->event);
|
||||
metaData->Set(2, "Options", aiString(pevent->options));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ struct HL1MeshTrivert {
|
|||
normindex(normindex),
|
||||
s(s),
|
||||
t(t),
|
||||
localindex() {
|
||||
localindex(localindex) {
|
||||
}
|
||||
|
||||
HL1MeshTrivert(const Trivert &a) :
|
||||
|
|
|
@ -68,7 +68,7 @@ static aiTexel* const bad_texel = reinterpret_cast<aiTexel*>(SIZE_MAX);
|
|||
void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
|
||||
{
|
||||
// now try to find the color map in the current directory
|
||||
IOStream* pcStream = pIOHandler->Open(configPalette,"rb");
|
||||
IOStream* pcStream = mIOHandler->Open(configPalette,"rb");
|
||||
|
||||
const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
|
||||
if(pcStream)
|
||||
|
@ -702,14 +702,13 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
|
|||
// data structures in the aiScene instance
|
||||
if (pcNew && pScene->mNumTextures <= 999)
|
||||
{
|
||||
|
||||
// place this as diffuse texture
|
||||
char szCurrent[5];
|
||||
ai_snprintf(szCurrent,5,"*%i",this->pScene->mNumTextures);
|
||||
char current[5];
|
||||
ai_snprintf(current, 5, "*%i", this->pScene->mNumTextures);
|
||||
|
||||
aiString szFile;
|
||||
const size_t iLen = strlen((const char*)szCurrent);
|
||||
::memcpy(szFile.data,(const char*)szCurrent,iLen+1);
|
||||
const size_t iLen = strlen((const char *)current);
|
||||
::memcpy(szFile.data, (const char *)current, iLen + 1);
|
||||
szFile.length = (ai_uint32)iLen;
|
||||
|
||||
pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
|
|
|
@ -261,19 +261,19 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
|||
TempTriangle& t = triangles[i];
|
||||
|
||||
stream.IncPtr(2);
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
t.indices[i] = stream.GetI2();
|
||||
for (unsigned int j = 0; j < 3; ++j) {
|
||||
t.indices[j] = stream.GetI2();
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
ReadVector(stream,t.normals[i]);
|
||||
for (unsigned int j = 0; j < 3; ++j) {
|
||||
ReadVector(stream,t.normals[j]);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
stream >> (float&)(t.uv[i].x); // see note in ReadColor()
|
||||
for (unsigned int j = 0; j < 3; ++j) {
|
||||
stream >> (float&)(t.uv[j].x); // see note in ReadColor()
|
||||
}
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
stream >> (float&)(t.uv[i].y);
|
||||
for (unsigned int j = 0; j < 3; ++j) {
|
||||
stream >> (float&)(t.uv[j].y);
|
||||
}
|
||||
|
||||
t.sg = stream.GetI1();
|
||||
|
@ -296,8 +296,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
|||
stream >> num;
|
||||
|
||||
t.triangles.resize(num);
|
||||
for (unsigned int i = 0; i < num; ++i) {
|
||||
t.triangles[i] = stream.GetI2();
|
||||
for (unsigned int j = 0; j < num; ++j) {
|
||||
t.triangles[j] = stream.GetI2();
|
||||
}
|
||||
t.mat = stream.GetI1();
|
||||
if (t.mat == UINT_MAX) {
|
||||
|
@ -309,8 +309,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
|||
stream >> mat;
|
||||
|
||||
std::vector<TempMaterial> materials(mat);
|
||||
for (unsigned int i = 0;i < mat; ++i) {
|
||||
TempMaterial& t = materials[i];
|
||||
for (unsigned int j = 0;j < mat; ++j) {
|
||||
TempMaterial& t = materials[j];
|
||||
|
||||
stream.CopyAndAdvance(t.name,32);
|
||||
t.name[32] = '\0';
|
||||
|
@ -338,8 +338,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
|||
stream >> joint;
|
||||
|
||||
std::vector<TempJoint> joints(joint);
|
||||
for(unsigned int i = 0; i < joint; ++i) {
|
||||
TempJoint& j = joints[i];
|
||||
for(unsigned int ii = 0; ii < joint; ++ii) {
|
||||
TempJoint& j = joints[ii];
|
||||
|
||||
stream.IncPtr(1);
|
||||
stream.CopyAndAdvance(j.name,32);
|
||||
|
@ -494,17 +494,17 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
|||
typedef std::map<unsigned int,unsigned int> BoneSet;
|
||||
BoneSet mybones;
|
||||
|
||||
for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) {
|
||||
aiFace& f = m->mFaces[i];
|
||||
if (g.triangles[i]>triangles.size()) {
|
||||
for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) {
|
||||
aiFace& f = m->mFaces[j];
|
||||
if (g.triangles[j]>triangles.size()) {
|
||||
throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
|
||||
}
|
||||
|
||||
TempTriangle& t = triangles[g.triangles[i]];
|
||||
f.mIndices = new unsigned int[f.mNumIndices=3];
|
||||
|
||||
for (unsigned int i = 0; i < 3; ++i,++n) {
|
||||
if (t.indices[i]>vertices.size()) {
|
||||
for (unsigned int k = 0; k < 3; ++k,++n) {
|
||||
if (t.indices[k]>vertices.size()) {
|
||||
throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
|
||||
}
|
||||
|
||||
|
@ -545,11 +545,11 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
|
||||
// .. and collect bone weights
|
||||
for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) {
|
||||
TempTriangle& t = triangles[g.triangles[i]];
|
||||
for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) {
|
||||
TempTriangle& t = triangles[g.triangles[j]];
|
||||
|
||||
for (unsigned int i = 0; i < 3; ++i,++n) {
|
||||
const TempVertex& v = vertices[t.indices[i]];
|
||||
for (unsigned int k = 0; k < 3; ++k,++n) {
|
||||
const TempVertex& v = vertices[t.indices[k]];
|
||||
for(unsigned int a = 0; a < 4; ++a) {
|
||||
const unsigned int bone = v.bone_id[a];
|
||||
if(bone==UINT_MAX){
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -185,8 +185,8 @@ private:
|
|||
|
||||
// for spheres, cones and cylinders: center point of the object
|
||||
aiVector3D center, radius, dir;
|
||||
|
||||
char name[128];
|
||||
static const size_t MaxNameLen = 128;
|
||||
char name[MaxNameLen];
|
||||
|
||||
std::vector<aiVector3D> vertices, normals, uvs;
|
||||
std::vector<unsigned int> faces;
|
||||
|
|
|
@ -80,7 +80,7 @@ ObjFileParser::ObjFileParser( IOStreamBuffer<char> &streamBuffer, const std::str
|
|||
m_progress(progress),
|
||||
m_originalObjFileName(originalObjFileName)
|
||||
{
|
||||
std::fill_n(m_buffer,Buffersize,0);
|
||||
std::fill_n(m_buffer,Buffersize,'\0');
|
||||
|
||||
// Create the model instance to store all the data
|
||||
m_pModel.reset(new ObjFile::Model());
|
||||
|
|
|
@ -668,8 +668,8 @@ void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/)
|
|||
|
||||
for (size_t i=0; i<numEdgeGroups; ++i)
|
||||
{
|
||||
uint16_t id = ReadHeader();
|
||||
if (id != M_EDGE_GROUP)
|
||||
uint16_t curId = ReadHeader();
|
||||
if (curId != M_EDGE_GROUP)
|
||||
throw DeadlyImportError("M_EDGE_GROUP not found in M_EDGE_LIST_LOD");
|
||||
|
||||
m_reader->IncPtr(sizeof(uint32_t) * 3);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -206,8 +206,8 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
|
|||
aiMaterial *material = new aiMaterial();
|
||||
m_textures.clear();
|
||||
|
||||
aiString ts(materialName);
|
||||
material->AddProperty(&ts, AI_MATKEY_NAME);
|
||||
aiString matName(materialName);
|
||||
material->AddProperty(&matName, AI_MATKEY_NAME);
|
||||
|
||||
// The stringstream will push words from a line until newline.
|
||||
// It will also trim whitespace from line start and between words.
|
||||
|
@ -279,14 +279,14 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
|
|||
else if (linePart=="$colormap")
|
||||
{
|
||||
ss >> linePart;
|
||||
aiString ts(linePart);
|
||||
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
||||
aiString cm(linePart);
|
||||
material->AddProperty(&cm, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
||||
}
|
||||
else if (linePart=="$normalmap")
|
||||
{
|
||||
ss >> linePart;
|
||||
aiString ts(linePart);
|
||||
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
||||
aiString nm(linePart);
|
||||
material->AddProperty(&nm, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
||||
}
|
||||
else if (linePart=="$shininess_strength")
|
||||
{
|
||||
|
|
|
@ -46,26 +46,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
|
||||
namespace Assimp {
|
||||
namespace Ogre {
|
||||
|
||||
/// Returns a lower cased copy of @s.
|
||||
static AI_FORCE_INLINE
|
||||
std::string ToLower(std::string s)
|
||||
{
|
||||
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||
return s;
|
||||
static AI_FORCE_INLINE std::string ToLower(const std::string &s) {
|
||||
std::string lower(s);
|
||||
std::transform(lower.begin(), lower.end(), lower.begin(), Assimp::ToLower<char>);
|
||||
|
||||
return lower;
|
||||
}
|
||||
|
||||
/// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching.
|
||||
static AI_FORCE_INLINE
|
||||
bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) {
|
||||
static AI_FORCE_INLINE bool EndsWith( const std::string &s, const std::string &suffix, bool caseSensitive = true) {
|
||||
if (s.empty() || suffix.empty()) {
|
||||
return false;
|
||||
} else if (s.length() < suffix.length()) {
|
||||
|
@ -86,7 +85,8 @@ bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitiv
|
|||
|
||||
/// Trim from start
|
||||
static AI_FORCE_INLINE
|
||||
std::string &TrimLeft(std::string &s, bool newlines = true) {
|
||||
std::string &
|
||||
TrimLeft(std::string &s, bool newlines = true) {
|
||||
if (!newlines) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); }));
|
||||
} else {
|
||||
|
@ -97,7 +97,8 @@ std::string &TrimLeft(std::string &s, bool newlines = true) {
|
|||
|
||||
/// Trim from end
|
||||
static AI_FORCE_INLINE
|
||||
std::string &TrimRight(std::string &s, bool newlines = true) {
|
||||
std::string &
|
||||
TrimRight(std::string &s, bool newlines = true) {
|
||||
if (!newlines) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(), s.end());
|
||||
} else {
|
||||
|
@ -108,13 +109,15 @@ std::string &TrimRight(std::string &s, bool newlines = true) {
|
|||
|
||||
/// Trim from both ends
|
||||
static AI_FORCE_INLINE
|
||||
std::string &Trim(std::string &s, bool newlines = true) {
|
||||
std::string &
|
||||
Trim(std::string &s, bool newlines = true) {
|
||||
return TrimLeft(TrimRight(s, newlines), newlines);
|
||||
}
|
||||
|
||||
/// Skips a line from current @ss position until a newline. Returns the skipped part.
|
||||
static AI_FORCE_INLINE
|
||||
std::string SkipLine(std::stringstream &ss) {
|
||||
std::string
|
||||
SkipLine(std::stringstream &ss) {
|
||||
std::string skipped;
|
||||
getline(ss, skipped);
|
||||
return skipped;
|
||||
|
@ -123,14 +126,15 @@ std::string SkipLine(std::stringstream &ss) {
|
|||
/// Skips a line and reads next element from @c ss to @c nextElement.
|
||||
/** @return Skipped line content until newline. */
|
||||
static AI_FORCE_INLINE
|
||||
std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) {
|
||||
std::string
|
||||
NextAfterNewLine(std::stringstream &ss, std::string &nextElement) {
|
||||
std::string skipped = SkipLine(ss);
|
||||
ss >> nextElement;
|
||||
return skipped;
|
||||
}
|
||||
|
||||
} // Ogre
|
||||
} // Assimp
|
||||
} // namespace Ogre
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||
#endif // AI_OGREPARSINGUTILS_H_INC
|
||||
|
|
|
@ -53,140 +53,94 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// Define as 1 to get verbose logging.
|
||||
#define OGRE_XML_SERIALIZER_DEBUG 0
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Ogre
|
||||
{
|
||||
namespace Assimp {
|
||||
namespace Ogre {
|
||||
|
||||
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error)
|
||||
{
|
||||
if (!error.empty())
|
||||
{
|
||||
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error) {
|
||||
if (!error.empty()) {
|
||||
throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
int32_t OgreXmlSerializer::ReadAttribute<int32_t>(const char *name) const
|
||||
{
|
||||
if (HasAttribute(name))
|
||||
{
|
||||
int32_t OgreXmlSerializer::ReadAttribute<int32_t>(const char *name) const {
|
||||
if (!HasAttribute(name)) {
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
}
|
||||
|
||||
return static_cast<int32_t>(m_reader->getAttributeValueAsInt(name));
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(const char *name) const
|
||||
{
|
||||
if (HasAttribute(name))
|
||||
{
|
||||
/** @note This is hackish. But we are never expecting unsigned values that go outside the
|
||||
int32_t range. Just monitor for negative numbers and kill the import. */
|
||||
int32_t temp = ReadAttribute<int32_t>(name);
|
||||
if (temp >= 0)
|
||||
{
|
||||
return static_cast<uint32_t>(temp);
|
||||
uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(const char *name) const {
|
||||
if (!HasAttribute(name)) {
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// @note This is hackish. But we are never expecting unsigned values that go outside the
|
||||
// int32_t range. Just monitor for negative numbers and kill the import.
|
||||
int32_t temp = ReadAttribute<int32_t>(name);
|
||||
if (temp < 0) {
|
||||
ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return static_cast<uint32_t>(temp);
|
||||
}
|
||||
|
||||
template <>
|
||||
uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(const char *name) const
|
||||
{
|
||||
if (HasAttribute(name))
|
||||
{
|
||||
uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(const char *name) const {
|
||||
if (!HasAttribute(name)) {
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
}
|
||||
|
||||
return static_cast<uint16_t>(ReadAttribute<uint32_t>(name));
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
float OgreXmlSerializer::ReadAttribute<float>(const char *name) const
|
||||
{
|
||||
if (HasAttribute(name))
|
||||
{
|
||||
float OgreXmlSerializer::ReadAttribute<float>(const char *name) const {
|
||||
if (!HasAttribute(name)) {
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
}
|
||||
|
||||
return m_reader->getAttributeValueAsFloat(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string OgreXmlSerializer::ReadAttribute<std::string>(const char *name) const
|
||||
{
|
||||
std::string OgreXmlSerializer::ReadAttribute<std::string>(const char *name) const {
|
||||
const char *value = m_reader->getAttributeValue(name);
|
||||
if (value)
|
||||
{
|
||||
if (nullptr == value) {
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
}
|
||||
|
||||
return std::string(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowAttibuteError(m_reader, name);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
bool OgreXmlSerializer::ReadAttribute<bool>(const char *name) const
|
||||
{
|
||||
bool OgreXmlSerializer::ReadAttribute<bool>(const char *name) const {
|
||||
std::string value = Ogre::ToLower(ReadAttribute<std::string>(name));
|
||||
if (ASSIMP_stricmp(value, "true") == 0)
|
||||
{
|
||||
if (ASSIMP_stricmp(value, "true") == 0) {
|
||||
return true;
|
||||
}
|
||||
else if (ASSIMP_stricmp(value, "false") == 0)
|
||||
{
|
||||
} else if (ASSIMP_stricmp(value, "false") == 0) {
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ThrowAttibuteError(m_reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool OgreXmlSerializer::HasAttribute(const char *name) const
|
||||
{
|
||||
bool OgreXmlSerializer::HasAttribute(const char *name) const {
|
||||
return (m_reader->getAttributeValue(name) != 0);
|
||||
}
|
||||
|
||||
std::string &OgreXmlSerializer::NextNode()
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!m_reader->read())
|
||||
{
|
||||
std::string &OgreXmlSerializer::NextNode() {
|
||||
do {
|
||||
if (!m_reader->read()) {
|
||||
m_currentNodeName = "";
|
||||
return m_currentNodeName;
|
||||
}
|
||||
}
|
||||
while(m_reader->getNodeType() != irr::io::EXN_ELEMENT);
|
||||
} while (m_reader->getNodeType() != irr::io::EXN_ELEMENT);
|
||||
|
||||
CurrentNodeName(true);
|
||||
#if (OGRE_XML_SERIALIZER_DEBUG == 1)
|
||||
|
@ -195,20 +149,17 @@ std::string &OgreXmlSerializer::NextNode()
|
|||
return m_currentNodeName;
|
||||
}
|
||||
|
||||
bool OgreXmlSerializer::CurrentNodeNameEquals(const std::string &name) const
|
||||
{
|
||||
bool OgreXmlSerializer::CurrentNodeNameEquals(const std::string &name) const {
|
||||
return (ASSIMP_stricmp(m_currentNodeName, name) == 0);
|
||||
}
|
||||
|
||||
std::string OgreXmlSerializer::CurrentNodeName(bool forceRead)
|
||||
{
|
||||
std::string OgreXmlSerializer::CurrentNodeName(bool forceRead) {
|
||||
if (forceRead)
|
||||
m_currentNodeName = std::string(m_reader->getNodeName());
|
||||
return m_currentNodeName;
|
||||
}
|
||||
|
||||
std::string &OgreXmlSerializer::SkipCurrentNode()
|
||||
{
|
||||
std::string &OgreXmlSerializer::SkipCurrentNode() {
|
||||
#if (OGRE_XML_SERIALIZER_DEBUG == 1)
|
||||
ASSIMP_LOG_DEBUG("Skipping node <" + m_currentNodeName + ">");
|
||||
#endif
|
||||
|
@ -330,26 +281,18 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
|
|||
m_currentNodeName == nnSubMeshNames ||
|
||||
m_currentNodeName == nnExtremes ||
|
||||
m_currentNodeName == nnPoses ||
|
||||
m_currentNodeName == nnAnimations)
|
||||
{
|
||||
if (m_currentNodeName == nnSharedGeometry)
|
||||
{
|
||||
m_currentNodeName == nnAnimations) {
|
||||
if (m_currentNodeName == nnSharedGeometry) {
|
||||
mesh->sharedVertexData = new VertexDataXml();
|
||||
ReadGeometry(mesh->sharedVertexData);
|
||||
}
|
||||
else if (m_currentNodeName == nnSubMeshes)
|
||||
{
|
||||
} else if (m_currentNodeName == nnSubMeshes) {
|
||||
NextNode();
|
||||
while (m_currentNodeName == nnSubMesh) {
|
||||
ReadSubMesh(mesh);
|
||||
}
|
||||
}
|
||||
else if (m_currentNodeName == nnBoneAssignments)
|
||||
{
|
||||
} else if (m_currentNodeName == nnBoneAssignments) {
|
||||
ReadBoneAssignments(mesh->sharedVertexData);
|
||||
}
|
||||
else if (m_currentNodeName == nnSkeletonLink)
|
||||
{
|
||||
} else if (m_currentNodeName == nnSkeletonLink) {
|
||||
mesh->skeletonRef = ReadAttribute<std::string>("name");
|
||||
ASSIMP_LOG_DEBUG_F("Read skeleton link ", mesh->skeletonRef);
|
||||
NextNode();
|
||||
|
@ -360,8 +303,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
|
|||
}
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest)
|
||||
{
|
||||
void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest) {
|
||||
dest->count = ReadAttribute<uint32_t>("vertexcount");
|
||||
ASSIMP_LOG_DEBUG_F(" - Reading geometry of ", dest->count, " vertices");
|
||||
|
||||
|
@ -371,8 +313,7 @@ void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest)
|
|||
}
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
|
||||
{
|
||||
void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
|
||||
bool positions = (HasAttribute("positions") && ReadAttribute<bool>("positions"));
|
||||
bool normals = (HasAttribute("normals") && ReadAttribute<bool>("normals"));
|
||||
bool tangents = (HasAttribute("tangents") && ReadAttribute<bool>("tangents"));
|
||||
|
@ -383,23 +324,19 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
|
|||
throw DeadlyImportError("Vertex buffer does not contain positions!");
|
||||
}
|
||||
|
||||
if (positions)
|
||||
{
|
||||
if (positions) {
|
||||
ASSIMP_LOG_DEBUG(" - Contains positions");
|
||||
dest->positions.reserve(dest->count);
|
||||
}
|
||||
if (normals)
|
||||
{
|
||||
if (normals) {
|
||||
ASSIMP_LOG_DEBUG(" - Contains normals");
|
||||
dest->normals.reserve(dest->count);
|
||||
}
|
||||
if (tangents)
|
||||
{
|
||||
if (tangents) {
|
||||
ASSIMP_LOG_DEBUG(" - Contains tangents");
|
||||
dest->tangents.reserve(dest->count);
|
||||
}
|
||||
if (uvs > 0)
|
||||
{
|
||||
if (uvs > 0) {
|
||||
ASSIMP_LOG_DEBUG_F(" - Contains ", uvs, " texture coords");
|
||||
dest->uvs.resize(uvs);
|
||||
for (size_t i = 0, len = dest->uvs.size(); i < len; ++i) {
|
||||
|
@ -420,42 +357,33 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
|
|||
m_currentNodeName == nnBinormal ||
|
||||
m_currentNodeName == nnTexCoord ||
|
||||
m_currentNodeName == nnColorDiffuse ||
|
||||
m_currentNodeName == nnColorSpecular)
|
||||
{
|
||||
m_currentNodeName == nnColorSpecular) {
|
||||
if (m_currentNodeName == nnVertex) {
|
||||
NextNode();
|
||||
}
|
||||
|
||||
/// @todo Implement nnBinormal, nnColorDiffuse and nnColorSpecular
|
||||
|
||||
if (positions && m_currentNodeName == nnPosition)
|
||||
{
|
||||
if (positions && m_currentNodeName == nnPosition) {
|
||||
aiVector3D pos;
|
||||
pos.x = ReadAttribute<float>(anX);
|
||||
pos.y = ReadAttribute<float>(anY);
|
||||
pos.z = ReadAttribute<float>(anZ);
|
||||
dest->positions.push_back(pos);
|
||||
}
|
||||
else if (normals && m_currentNodeName == nnNormal)
|
||||
{
|
||||
} else if (normals && m_currentNodeName == nnNormal) {
|
||||
aiVector3D normal;
|
||||
normal.x = ReadAttribute<float>(anX);
|
||||
normal.y = ReadAttribute<float>(anY);
|
||||
normal.z = ReadAttribute<float>(anZ);
|
||||
dest->normals.push_back(normal);
|
||||
}
|
||||
else if (tangents && m_currentNodeName == nnTangent)
|
||||
{
|
||||
} else if (tangents && m_currentNodeName == nnTangent) {
|
||||
aiVector3D tangent;
|
||||
tangent.x = ReadAttribute<float>(anX);
|
||||
tangent.y = ReadAttribute<float>(anY);
|
||||
tangent.z = ReadAttribute<float>(anZ);
|
||||
dest->tangents.push_back(tangent);
|
||||
}
|
||||
else if (uvs > 0 && m_currentNodeName == nnTexCoord)
|
||||
{
|
||||
for(auto &uvs : dest->uvs)
|
||||
{
|
||||
} else if (uvs > 0 && m_currentNodeName == nnTexCoord) {
|
||||
for (auto &curUvs : dest->uvs) {
|
||||
if (m_currentNodeName != nnTexCoord) {
|
||||
throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex");
|
||||
}
|
||||
|
@ -463,47 +391,31 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
|
|||
aiVector3D uv;
|
||||
uv.x = ReadAttribute<float>("u");
|
||||
uv.y = (ReadAttribute<float>("v") * -1) + 1; // Flip UV from Ogre to Assimp form
|
||||
uvs.push_back(uv);
|
||||
curUvs.push_back(uv);
|
||||
|
||||
NextNode();
|
||||
}
|
||||
// Continue main loop as above already read next node
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/// @todo Remove this stuff once implemented. We only want to log warnings once per element.
|
||||
bool warn = true;
|
||||
if (m_currentNodeName == nnBinormal)
|
||||
{
|
||||
if (warnBinormal)
|
||||
{
|
||||
if (m_currentNodeName == nnBinormal) {
|
||||
if (warnBinormal) {
|
||||
warnBinormal = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
warn = false;
|
||||
}
|
||||
}
|
||||
else if (m_currentNodeName == nnColorDiffuse)
|
||||
{
|
||||
if (warnColorDiffuse)
|
||||
{
|
||||
} else if (m_currentNodeName == nnColorDiffuse) {
|
||||
if (warnColorDiffuse) {
|
||||
warnColorDiffuse = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
warn = false;
|
||||
}
|
||||
}
|
||||
else if (m_currentNodeName == nnColorSpecular)
|
||||
{
|
||||
if (warnColorSpecular)
|
||||
{
|
||||
} else if (m_currentNodeName == nnColorSpecular) {
|
||||
if (warnColorSpecular) {
|
||||
warnColorSpecular = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
warn = false;
|
||||
}
|
||||
}
|
||||
|
@ -526,8 +438,7 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
|
|||
if (tangents && dest->tangents.size() != dest->count) {
|
||||
throw DeadlyImportError(Formatter::format() << "Read only " << dest->tangents.size() << " tangents when should have read " << dest->count);
|
||||
}
|
||||
for(unsigned int i=0; i<dest->uvs.size(); ++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < dest->uvs.size(); ++i) {
|
||||
if (dest->uvs[i].size() != dest->count) {
|
||||
throw DeadlyImportError(Formatter::format() << "Read only " << dest->uvs[i].size()
|
||||
<< " uvs for uv index " << i << " when should have read " << dest->count);
|
||||
|
@ -535,8 +446,7 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
|
|||
}
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
|
||||
{
|
||||
void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
|
||||
static const char *anMaterial = "material";
|
||||
static const char *anUseSharedVertices = "usesharedvertices";
|
||||
static const char *anCount = "count";
|
||||
|
@ -568,16 +478,13 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
|
|||
while (m_currentNodeName == nnFaces ||
|
||||
m_currentNodeName == nnGeometry ||
|
||||
m_currentNodeName == nnTextures ||
|
||||
m_currentNodeName == nnBoneAssignments)
|
||||
{
|
||||
if (m_currentNodeName == nnFaces)
|
||||
{
|
||||
m_currentNodeName == nnBoneAssignments) {
|
||||
if (m_currentNodeName == nnFaces) {
|
||||
submesh->indexData->faceCount = ReadAttribute<uint32_t>(anCount);
|
||||
submesh->indexData->faces.reserve(submesh->indexData->faceCount);
|
||||
|
||||
NextNode();
|
||||
while(m_currentNodeName == nnFace)
|
||||
{
|
||||
while (m_currentNodeName == nnFace) {
|
||||
aiFace face;
|
||||
face.mNumIndices = 3;
|
||||
face.mIndices = new unsigned int[3];
|
||||
|
@ -622,8 +529,7 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
|
|||
mesh->subMeshes.push_back(submesh);
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest)
|
||||
{
|
||||
void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) {
|
||||
if (!dest) {
|
||||
throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
|
||||
}
|
||||
|
@ -635,8 +541,7 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest)
|
|||
std::set<uint32_t> influencedVertices;
|
||||
|
||||
NextNode();
|
||||
while(m_currentNodeName == nnVertexBoneAssignment)
|
||||
{
|
||||
while (m_currentNodeName == nnVertexBoneAssignment) {
|
||||
VertexBoneAssignment ba;
|
||||
ba.vertexIndex = ReadAttribute<uint32_t>(anVertexIndex);
|
||||
ba.boneIndex = ReadAttribute<uint16_t>(anBoneIndex);
|
||||
|
@ -652,18 +557,14 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest)
|
|||
Some exporters won't care if the sum of all bone weights
|
||||
for a single vertex equals 1 or not, so validate here. */
|
||||
const float epsilon = 0.05f;
|
||||
for (const uint32_t vertexIndex : influencedVertices)
|
||||
{
|
||||
for (const uint32_t vertexIndex : influencedVertices) {
|
||||
float sum = 0.0f;
|
||||
for (VertexBoneAssignmentList::const_iterator baIter=dest->boneAssignments.begin(), baEnd=dest->boneAssignments.end(); baIter != baEnd; ++baIter)
|
||||
{
|
||||
for (VertexBoneAssignmentList::const_iterator baIter = dest->boneAssignments.begin(), baEnd = dest->boneAssignments.end(); baIter != baEnd; ++baIter) {
|
||||
if (baIter->vertexIndex == vertexIndex)
|
||||
sum += baIter->weight;
|
||||
}
|
||||
if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon)))
|
||||
{
|
||||
for (auto &boneAssign : dest->boneAssignments)
|
||||
{
|
||||
if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon))) {
|
||||
for (auto &boneAssign : dest->boneAssignments) {
|
||||
if (boneAssign.vertexIndex == vertexIndex)
|
||||
boneAssign.weight /= sum;
|
||||
}
|
||||
|
@ -675,15 +576,13 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest)
|
|||
|
||||
// Skeleton
|
||||
|
||||
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh)
|
||||
{
|
||||
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh) {
|
||||
if (!mesh || mesh->skeletonRef.empty())
|
||||
return false;
|
||||
|
||||
// Highly unusual to see in read world cases but support
|
||||
// XML mesh referencing a binary skeleton file.
|
||||
if (EndsWith(mesh->skeletonRef, ".skeleton", false))
|
||||
{
|
||||
if (EndsWith(mesh->skeletonRef, ".skeleton", false)) {
|
||||
if (OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh))
|
||||
return true;
|
||||
|
||||
|
@ -705,8 +604,7 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *me
|
|||
return true;
|
||||
}
|
||||
|
||||
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
|
||||
{
|
||||
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) {
|
||||
if (!mesh || mesh->skeletonRef.empty())
|
||||
return false;
|
||||
|
||||
|
@ -721,16 +619,13 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
|
|||
return true;
|
||||
}
|
||||
|
||||
XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename)
|
||||
{
|
||||
if (!EndsWith(filename, ".skeleton.xml", false))
|
||||
{
|
||||
XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename) {
|
||||
if (!EndsWith(filename, ".skeleton.xml", false)) {
|
||||
ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file.");
|
||||
return XmlReaderPtr();
|
||||
}
|
||||
|
||||
if (!pIOHandler->Exists(filename))
|
||||
{
|
||||
if (!pIOHandler->Exists(filename)) {
|
||||
ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh.");
|
||||
return XmlReaderPtr();
|
||||
}
|
||||
|
@ -748,8 +643,7 @@ XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const s
|
|||
return reader;
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton)
|
||||
{
|
||||
void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) {
|
||||
if (NextNode() != nnSkeleton) {
|
||||
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <skeleton>");
|
||||
}
|
||||
|
@ -758,8 +652,7 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton)
|
|||
|
||||
// Optional blend mode from root node
|
||||
if (HasAttribute("blendmode")) {
|
||||
skeleton->blendMode = (ToLower(ReadAttribute<std::string>("blendmode")) == "cumulative"
|
||||
? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
|
||||
skeleton->blendMode = (ToLower(ReadAttribute<std::string>("blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
|
||||
}
|
||||
|
||||
NextNode();
|
||||
|
@ -768,8 +661,7 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton)
|
|||
while (m_currentNodeName == nnBones ||
|
||||
m_currentNodeName == nnBoneHierarchy ||
|
||||
m_currentNodeName == nnAnimations ||
|
||||
m_currentNodeName == nnAnimationLinks)
|
||||
{
|
||||
m_currentNodeName == nnAnimationLinks) {
|
||||
if (m_currentNodeName == nnBones)
|
||||
ReadBones(skeleton);
|
||||
else if (m_currentNodeName == nnBoneHierarchy)
|
||||
|
@ -781,8 +673,7 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton)
|
|||
}
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton)
|
||||
{
|
||||
void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) {
|
||||
if (skeleton->bones.empty()) {
|
||||
throw DeadlyImportError("Cannot read <animations> for a Skeleton without bones");
|
||||
}
|
||||
|
@ -790,8 +681,7 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton)
|
|||
ASSIMP_LOG_DEBUG(" - Animations");
|
||||
|
||||
NextNode();
|
||||
while(m_currentNodeName == nnAnimation)
|
||||
{
|
||||
while (m_currentNodeName == nnAnimation) {
|
||||
Animation *anim = new Animation(skeleton);
|
||||
anim->name = ReadAttribute<std::string>("name");
|
||||
anim->length = ReadAttribute<float>("length");
|
||||
|
@ -807,11 +697,9 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton)
|
|||
}
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadAnimationTracks(Animation *dest)
|
||||
{
|
||||
void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) {
|
||||
NextNode();
|
||||
while(m_currentNodeName == nnTrack)
|
||||
{
|
||||
while (m_currentNodeName == nnTrack) {
|
||||
VertexAnimationTrack track;
|
||||
track.type = VertexAnimationTrack::VAT_TRANSFORM;
|
||||
track.boneName = ReadAttribute<std::string>("bone");
|
||||
|
@ -826,27 +714,21 @@ void OgreXmlSerializer::ReadAnimationTracks(Animation *dest)
|
|||
}
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest)
|
||||
{
|
||||
void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest) {
|
||||
const aiVector3D zeroVec(0.f, 0.f, 0.f);
|
||||
|
||||
NextNode();
|
||||
while(m_currentNodeName == nnKeyFrame)
|
||||
{
|
||||
while (m_currentNodeName == nnKeyFrame) {
|
||||
TransformKeyFrame keyframe;
|
||||
keyframe.timePos = ReadAttribute<float>("time");
|
||||
|
||||
NextNode();
|
||||
while(m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale)
|
||||
{
|
||||
if (m_currentNodeName == nnTranslate)
|
||||
{
|
||||
while (m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale) {
|
||||
if (m_currentNodeName == nnTranslate) {
|
||||
keyframe.position.x = ReadAttribute<float>(anX);
|
||||
keyframe.position.y = ReadAttribute<float>(anY);
|
||||
keyframe.position.z = ReadAttribute<float>(anZ);
|
||||
}
|
||||
else if (m_currentNodeName == nnRotate)
|
||||
{
|
||||
} else if (m_currentNodeName == nnRotate) {
|
||||
float angle = ReadAttribute<float>("angle");
|
||||
|
||||
if (NextNode() != nnAxis) {
|
||||
|
@ -857,17 +739,14 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT
|
|||
axis.x = ReadAttribute<float>(anX);
|
||||
axis.y = ReadAttribute<float>(anY);
|
||||
axis.z = ReadAttribute<float>(anZ);
|
||||
if (axis.Equal(zeroVec))
|
||||
{
|
||||
if (axis.Equal(zeroVec)) {
|
||||
axis.x = 1.0f;
|
||||
if (angle != 0) {
|
||||
ASSIMP_LOG_WARN_F("Found invalid a key frame with a zero rotation axis in animation: ", anim->name);
|
||||
}
|
||||
}
|
||||
keyframe.rotation = aiQuaternion(axis, angle);
|
||||
}
|
||||
else if (m_currentNodeName == nnScale)
|
||||
{
|
||||
} else if (m_currentNodeName == nnScale) {
|
||||
keyframe.scale.x = ReadAttribute<float>(anX);
|
||||
keyframe.scale.y = ReadAttribute<float>(anY);
|
||||
keyframe.scale.z = ReadAttribute<float>(anZ);
|
||||
|
@ -880,14 +759,12 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT
|
|||
}
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton)
|
||||
{
|
||||
void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) {
|
||||
if (skeleton->bones.empty()) {
|
||||
throw DeadlyImportError("Cannot read <bonehierarchy> for a Skeleton without bones");
|
||||
}
|
||||
|
||||
while(NextNode() == nnBoneParent)
|
||||
{
|
||||
while (NextNode() == nnBoneParent) {
|
||||
const std::string name = ReadAttribute<std::string>("bone");
|
||||
const std::string parentName = ReadAttribute<std::string>("parent");
|
||||
|
||||
|
@ -901,29 +778,25 @@ void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton)
|
|||
}
|
||||
|
||||
// Calculate bone matrices for root bones. Recursively calculates their children.
|
||||
for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
|
||||
{
|
||||
for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) {
|
||||
Bone *bone = skeleton->bones[i];
|
||||
if (!bone->IsParented())
|
||||
bone->CalculateWorldMatrixAndDefaultPose(skeleton);
|
||||
}
|
||||
}
|
||||
|
||||
static bool BoneCompare(Bone *a, Bone *b)
|
||||
{
|
||||
static bool BoneCompare(Bone *a, Bone *b) {
|
||||
ai_assert(nullptr != a);
|
||||
ai_assert(nullptr != b);
|
||||
|
||||
return (a->id < b->id);
|
||||
}
|
||||
|
||||
void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
|
||||
{
|
||||
void OgreXmlSerializer::ReadBones(Skeleton *skeleton) {
|
||||
ASSIMP_LOG_DEBUG(" - Bones");
|
||||
|
||||
NextNode();
|
||||
while(m_currentNodeName == nnBone)
|
||||
{
|
||||
while (m_currentNodeName == nnBone) {
|
||||
Bone *bone = new Bone();
|
||||
bone->id = ReadAttribute<uint16_t>("id");
|
||||
bone->name = ReadAttribute<std::string>("name");
|
||||
|
@ -931,16 +804,12 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
|
|||
NextNode();
|
||||
while (m_currentNodeName == nnPosition ||
|
||||
m_currentNodeName == nnRotation ||
|
||||
m_currentNodeName == nnScale)
|
||||
{
|
||||
if (m_currentNodeName == nnPosition)
|
||||
{
|
||||
m_currentNodeName == nnScale) {
|
||||
if (m_currentNodeName == nnPosition) {
|
||||
bone->position.x = ReadAttribute<float>(anX);
|
||||
bone->position.y = ReadAttribute<float>(anY);
|
||||
bone->position.z = ReadAttribute<float>(anZ);
|
||||
}
|
||||
else if (m_currentNodeName == nnRotation)
|
||||
{
|
||||
} else if (m_currentNodeName == nnRotation) {
|
||||
float angle = ReadAttribute<float>("angle");
|
||||
|
||||
if (NextNode() != nnAxis) {
|
||||
|
@ -953,17 +822,12 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
|
|||
axis.z = ReadAttribute<float>(anZ);
|
||||
|
||||
bone->rotation = aiQuaternion(axis, angle);
|
||||
}
|
||||
else if (m_currentNodeName == nnScale)
|
||||
{
|
||||
} else if (m_currentNodeName == nnScale) {
|
||||
/// @todo Implement taking scale into account in matrix/pose calculations!
|
||||
if (HasAttribute("factor"))
|
||||
{
|
||||
if (HasAttribute("factor")) {
|
||||
float factor = ReadAttribute<float>("factor");
|
||||
bone->scale.Set(factor, factor, factor);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (HasAttribute(anX))
|
||||
bone->scale.x = ReadAttribute<float>(anX);
|
||||
if (HasAttribute(anY))
|
||||
|
@ -985,8 +849,7 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
|
|||
// Validate that bone indexes are not skipped.
|
||||
/** @note Left this from original authors code, but not sure if this is strictly necessary
|
||||
as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */
|
||||
for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
|
||||
{
|
||||
for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) {
|
||||
Bone *b = skeleton->bones[i];
|
||||
ASSIMP_LOG_DEBUG_F(" ", b->id, " ", b->name);
|
||||
|
||||
|
@ -996,7 +859,7 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
|
|||
}
|
||||
}
|
||||
|
||||
} // Ogre
|
||||
} // Assimp
|
||||
} // namespace Ogre
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||
|
|
|
@ -1212,8 +1212,8 @@ void OpenGEXImporter::resolveReferences() {
|
|||
if( RefInfo::MeshRef == currentRefInfo->m_type ) {
|
||||
for( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) {
|
||||
const std::string &name( currentRefInfo->m_Names[ i ] );
|
||||
ReferenceMap::const_iterator it( m_mesh2refMap.find( name ) );
|
||||
if( m_mesh2refMap.end() != it ) {
|
||||
ReferenceMap::const_iterator curIt( m_mesh2refMap.find( name ) );
|
||||
if (m_mesh2refMap.end() != curIt) {
|
||||
unsigned int meshIdx = static_cast<unsigned int>(m_mesh2refMap[ name ]);
|
||||
node->mMeshes[ i ] = meshIdx;
|
||||
}
|
||||
|
@ -1221,8 +1221,8 @@ void OpenGEXImporter::resolveReferences() {
|
|||
} else if( RefInfo::MaterialRef == currentRefInfo->m_type ) {
|
||||
for ( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) {
|
||||
const std::string name( currentRefInfo->m_Names[ i ] );
|
||||
ReferenceMap::const_iterator it( m_material2refMap.find( name ) );
|
||||
if ( m_material2refMap.end() != it ) {
|
||||
ReferenceMap::const_iterator curIt(m_material2refMap.find(name));
|
||||
if (m_material2refMap.end() != curIt) {
|
||||
if ( nullptr != m_currentMesh ) {
|
||||
unsigned int matIdx = static_cast< unsigned int >( m_material2refMap[ name ] );
|
||||
if ( m_currentMesh->mMaterialIndex != 0 ) {
|
||||
|
|
|
@ -49,10 +49,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// internal headers
|
||||
#include "PlyLoader.h"
|
||||
#include <assimp/IOStreamBuffer.h>
|
||||
#include <memory>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
#include <memory>
|
||||
|
||||
using namespace ::Assimp;
|
||||
|
||||
|
@ -69,29 +69,25 @@ static const aiImporterDesc desc = {
|
|||
"ply"
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Internal stuff
|
||||
namespace {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Checks that property index is within range
|
||||
template <class T>
|
||||
inline
|
||||
const T &GetProperty(const std::vector<T> &props, int idx) {
|
||||
inline const T &GetProperty(const std::vector<T> &props, int idx) {
|
||||
if (static_cast<size_t>(idx) >= props.size()) {
|
||||
throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
|
||||
}
|
||||
|
||||
return props[idx];
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
PLYImporter::PLYImporter()
|
||||
: mBuffer(nullptr)
|
||||
, pcDOM(nullptr)
|
||||
, mGeneratedMesh(nullptr) {
|
||||
PLYImporter::PLYImporter() :
|
||||
mBuffer(nullptr), pcDOM(nullptr), mGeneratedMesh(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -397,19 +393,25 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
|
|||
bool haveColor = false;
|
||||
if (0xFFFFFFFF != aiColors[0]) {
|
||||
cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties,
|
||||
aiColors[0]).avList.front(), aiColorsTypes[0]);
|
||||
aiColors[0])
|
||||
.avList.front(),
|
||||
aiColorsTypes[0]);
|
||||
haveColor = true;
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF != aiColors[1]) {
|
||||
cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties,
|
||||
aiColors[1]).avList.front(), aiColorsTypes[1]);
|
||||
aiColors[1])
|
||||
.avList.front(),
|
||||
aiColorsTypes[1]);
|
||||
haveColor = true;
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF != aiColors[2]) {
|
||||
cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties,
|
||||
aiColors[2]).avList.front(), aiColorsTypes[2]);
|
||||
aiColors[2])
|
||||
.avList.front(),
|
||||
aiColorsTypes[2]);
|
||||
haveColor = true;
|
||||
}
|
||||
|
||||
|
@ -418,7 +420,9 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
|
|||
cOut.a = 1.0;
|
||||
} else {
|
||||
cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties,
|
||||
aiColors[3]).avList.front(), aiColorsTypes[3]);
|
||||
aiColors[3])
|
||||
.avList.front(),
|
||||
aiColorsTypes[3]);
|
||||
|
||||
haveColor = true;
|
||||
}
|
||||
|
@ -474,7 +478,6 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Convert a color component to [0...1]
|
||||
ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType) {
|
||||
|
@ -684,44 +687,50 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
|
|||
void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance> &avList,
|
||||
unsigned int aiPositions[4],
|
||||
PLY::EDataType aiTypes[4],
|
||||
aiColor4D* clrOut)
|
||||
{
|
||||
aiColor4D *clrOut) {
|
||||
ai_assert(NULL != clrOut);
|
||||
|
||||
if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
|
||||
else
|
||||
{
|
||||
if (0xFFFFFFFF == aiPositions[0])
|
||||
clrOut->r = 0.0f;
|
||||
else {
|
||||
clrOut->r = NormalizeColorValue(GetProperty(avList,
|
||||
aiPositions[0]).avList.front(), aiTypes[0]);
|
||||
aiPositions[0])
|
||||
.avList.front(),
|
||||
aiTypes[0]);
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
|
||||
else
|
||||
{
|
||||
if (0xFFFFFFFF == aiPositions[1])
|
||||
clrOut->g = 0.0f;
|
||||
else {
|
||||
clrOut->g = NormalizeColorValue(GetProperty(avList,
|
||||
aiPositions[1]).avList.front(), aiTypes[1]);
|
||||
aiPositions[1])
|
||||
.avList.front(),
|
||||
aiTypes[1]);
|
||||
}
|
||||
|
||||
if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
|
||||
else
|
||||
{
|
||||
if (0xFFFFFFFF == aiPositions[2])
|
||||
clrOut->b = 0.0f;
|
||||
else {
|
||||
clrOut->b = NormalizeColorValue(GetProperty(avList,
|
||||
aiPositions[2]).avList.front(), aiTypes[2]);
|
||||
aiPositions[2])
|
||||
.avList.front(),
|
||||
aiTypes[2]);
|
||||
}
|
||||
|
||||
// assume 1.0 for the alpha channel ifit is not set
|
||||
if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
|
||||
else
|
||||
{
|
||||
if (0xFFFFFFFF == aiPositions[3])
|
||||
clrOut->a = 1.0f;
|
||||
else {
|
||||
clrOut->a = NormalizeColorValue(GetProperty(avList,
|
||||
aiPositions[3]).avList.front(), aiTypes[3]);
|
||||
aiPositions[3])
|
||||
.avList.front(),
|
||||
aiTypes[3]);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Extract a material from the PLY DOM
|
||||
void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly)
|
||||
{
|
||||
void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &defaultTexture, const bool pointsOnly) {
|
||||
ai_assert(NULL != pvOut);
|
||||
|
||||
// diffuse[4], specular[4], ambient[4]
|
||||
|
@ -749,102 +758,74 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &def
|
|||
// search in the DOM for a vertex entry
|
||||
unsigned int _i = 0;
|
||||
for (std::vector<PLY::Element>::const_iterator i = this->pcDOM->alElements.begin();
|
||||
i != this->pcDOM->alElements.end(); ++i, ++_i)
|
||||
{
|
||||
if (PLY::EEST_Material == (*i).eSemantic)
|
||||
{
|
||||
i != this->pcDOM->alElements.end(); ++i, ++_i) {
|
||||
if (PLY::EEST_Material == (*i).eSemantic) {
|
||||
pcList = &this->pcDOM->alElementData[_i];
|
||||
|
||||
// now check whether which coordinate sets are available
|
||||
unsigned int _a = 0;
|
||||
for (std::vector<PLY::Property>::const_iterator
|
||||
a = (*i).alProperties.begin();
|
||||
a != (*i).alProperties.end(); ++a, ++_a)
|
||||
{
|
||||
a != (*i).alProperties.end(); ++a, ++_a) {
|
||||
if ((*a).bIsList) continue;
|
||||
|
||||
// pohng specularity -----------------------------------
|
||||
if (PLY::EST_PhongPower == (*a).Semantic)
|
||||
{
|
||||
if (PLY::EST_PhongPower == (*a).Semantic) {
|
||||
iPhong = _a;
|
||||
ePhong = (*a).eType;
|
||||
}
|
||||
|
||||
// general opacity -----------------------------------
|
||||
if (PLY::EST_Opacity == (*a).Semantic)
|
||||
{
|
||||
if (PLY::EST_Opacity == (*a).Semantic) {
|
||||
iOpacity = _a;
|
||||
eOpacity = (*a).eType;
|
||||
}
|
||||
|
||||
// diffuse color channels -----------------------------------
|
||||
if (PLY::EST_DiffuseRed == (*a).Semantic)
|
||||
{
|
||||
if (PLY::EST_DiffuseRed == (*a).Semantic) {
|
||||
aaiPositions[0][0] = _a;
|
||||
aaiTypes[0][0] = (*a).eType;
|
||||
}
|
||||
else if (PLY::EST_DiffuseGreen == (*a).Semantic)
|
||||
{
|
||||
} else if (PLY::EST_DiffuseGreen == (*a).Semantic) {
|
||||
aaiPositions[0][1] = _a;
|
||||
aaiTypes[0][1] = (*a).eType;
|
||||
}
|
||||
else if (PLY::EST_DiffuseBlue == (*a).Semantic)
|
||||
{
|
||||
} else if (PLY::EST_DiffuseBlue == (*a).Semantic) {
|
||||
aaiPositions[0][2] = _a;
|
||||
aaiTypes[0][2] = (*a).eType;
|
||||
}
|
||||
else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
|
||||
{
|
||||
} else if (PLY::EST_DiffuseAlpha == (*a).Semantic) {
|
||||
aaiPositions[0][3] = _a;
|
||||
aaiTypes[0][3] = (*a).eType;
|
||||
}
|
||||
// specular color channels -----------------------------------
|
||||
else if (PLY::EST_SpecularRed == (*a).Semantic)
|
||||
{
|
||||
else if (PLY::EST_SpecularRed == (*a).Semantic) {
|
||||
aaiPositions[1][0] = _a;
|
||||
aaiTypes[1][0] = (*a).eType;
|
||||
}
|
||||
else if (PLY::EST_SpecularGreen == (*a).Semantic)
|
||||
{
|
||||
} else if (PLY::EST_SpecularGreen == (*a).Semantic) {
|
||||
aaiPositions[1][1] = _a;
|
||||
aaiTypes[1][1] = (*a).eType;
|
||||
}
|
||||
else if (PLY::EST_SpecularBlue == (*a).Semantic)
|
||||
{
|
||||
} else if (PLY::EST_SpecularBlue == (*a).Semantic) {
|
||||
aaiPositions[1][2] = _a;
|
||||
aaiTypes[1][2] = (*a).eType;
|
||||
}
|
||||
else if (PLY::EST_SpecularAlpha == (*a).Semantic)
|
||||
{
|
||||
} else if (PLY::EST_SpecularAlpha == (*a).Semantic) {
|
||||
aaiPositions[1][3] = _a;
|
||||
aaiTypes[1][3] = (*a).eType;
|
||||
}
|
||||
// ambient color channels -----------------------------------
|
||||
else if (PLY::EST_AmbientRed == (*a).Semantic)
|
||||
{
|
||||
else if (PLY::EST_AmbientRed == (*a).Semantic) {
|
||||
aaiPositions[2][0] = _a;
|
||||
aaiTypes[2][0] = (*a).eType;
|
||||
}
|
||||
else if (PLY::EST_AmbientGreen == (*a).Semantic)
|
||||
{
|
||||
} else if (PLY::EST_AmbientGreen == (*a).Semantic) {
|
||||
aaiPositions[2][1] = _a;
|
||||
aaiTypes[2][1] = (*a).eType;
|
||||
}
|
||||
else if (PLY::EST_AmbientBlue == (*a).Semantic)
|
||||
{
|
||||
} else if (PLY::EST_AmbientBlue == (*a).Semantic) {
|
||||
aaiPositions[2][2] = _a;
|
||||
aaiTypes[2][2] = (*a).eType;
|
||||
}
|
||||
else if (PLY::EST_AmbientAlpha == (*a).Semantic)
|
||||
{
|
||||
} else if (PLY::EST_AmbientAlpha == (*a).Semantic) {
|
||||
aaiPositions[2][3] = _a;
|
||||
aaiTypes[2][3] = (*a).eType;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (PLY::EEST_TextureFile == (*i).eSemantic)
|
||||
{
|
||||
} else if (PLY::EEST_TextureFile == (*i).eSemantic) {
|
||||
defaultTexture = (*i).szName;
|
||||
}
|
||||
}
|
||||
|
@ -895,21 +876,17 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &def
|
|||
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
|
||||
|
||||
//default texture
|
||||
if (!defaultTexture.empty())
|
||||
{
|
||||
if (!defaultTexture.empty()) {
|
||||
const aiString name(defaultTexture.c_str());
|
||||
pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
|
||||
}
|
||||
|
||||
if (!pointsOnly)
|
||||
{
|
||||
const int two_sided = 1;
|
||||
if (!pointsOnly) {
|
||||
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
|
||||
}
|
||||
|
||||
//set to wireframe, so when using this material info we can switch to points rendering
|
||||
if (pointsOnly)
|
||||
{
|
||||
if (pointsOnly) {
|
||||
const int wireframe = 1;
|
||||
pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
|
||||
}
|
||||
|
@ -917,9 +894,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &def
|
|||
// add the newly created material instance to the list
|
||||
pvOut->push_back(pcHelper);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// generate a default material
|
||||
aiMaterial *pcHelper = new aiMaterial();
|
||||
|
||||
|
@ -938,22 +913,19 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &def
|
|||
|
||||
// The face order is absolutely undefined for PLY, so we have to
|
||||
// use two-sided rendering to be sure it's ok.
|
||||
if (!pointsOnly)
|
||||
{
|
||||
if (!pointsOnly) {
|
||||
const int two_sided = 1;
|
||||
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
|
||||
}
|
||||
|
||||
//default texture
|
||||
if (!defaultTexture.empty())
|
||||
{
|
||||
if (!defaultTexture.empty()) {
|
||||
const aiString name(defaultTexture.c_str());
|
||||
pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
|
||||
}
|
||||
|
||||
//set to wireframe, so when using this material info we can switch to points rendering
|
||||
if (pointsOnly)
|
||||
{
|
||||
if (pointsOnly) {
|
||||
const int wireframe = 1;
|
||||
pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
|
|||
pTexture->pcData = imageContent;
|
||||
|
||||
auto extension = path.substr(path.find_last_of('.') + 1u);
|
||||
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
|
||||
std::transform(extension.begin(), extension.end(), extension.begin(), ToLower<char> );
|
||||
if (extension == "jpeg") {
|
||||
extension = "jpg";
|
||||
}
|
||||
|
|
|
@ -105,7 +105,8 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
|
|||
if (info.mRotation)
|
||||
{
|
||||
float out = info.mRotation;
|
||||
if ((rounded = static_cast<int>((info.mRotation / static_cast<float>(AI_MATH_TWO_PI)))))
|
||||
rounded = static_cast<int>((info.mRotation / static_cast<float>(AI_MATH_TWO_PI)));
|
||||
if (rounded)
|
||||
{
|
||||
out -= rounded * static_cast<float>(AI_MATH_PI);
|
||||
ASSIMP_LOG_INFO_F("Texture coordinate rotation ", info.mRotation, " can be simplified to ", out);
|
||||
|
|
|
@ -517,8 +517,8 @@ outer:
|
|||
for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end();
|
||||
it != end; ++it, ++faces)
|
||||
{
|
||||
Mesh& m = meshes[(*it).first];
|
||||
Face& face = m.faces[(*it).second];
|
||||
Mesh& curMesh = meshes[(*it).first];
|
||||
Face &face = curMesh.faces[(*it).second];
|
||||
faces->mNumIndices = (unsigned int)face.indices.size();
|
||||
faces->mIndices = new unsigned int [faces->mNumIndices];
|
||||
|
||||
|
@ -528,29 +528,30 @@ outer:
|
|||
|
||||
for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts)
|
||||
{
|
||||
if (face.indices[n] >= m.verts.size())
|
||||
if (face.indices[n] >= curMesh.verts.size())
|
||||
{
|
||||
ASSIMP_LOG_WARN("Quick3D: Vertex index overflow");
|
||||
face.indices[n] = 0;
|
||||
}
|
||||
|
||||
// copy vertices
|
||||
*verts = m.verts[ face.indices[n] ];
|
||||
*verts = curMesh.verts[face.indices[n]];
|
||||
|
||||
if (face.indices[n] >= m.normals.size() && faces->mNumIndices >= 3)
|
||||
if (face.indices[n] >= curMesh.normals.size() && faces->mNumIndices >= 3)
|
||||
{
|
||||
// we have no normal here - assign the face normal
|
||||
if (!fnOK)
|
||||
{
|
||||
const aiVector3D& pV1 = m.verts[ face.indices[0] ];
|
||||
const aiVector3D& pV2 = m.verts[ face.indices[1] ];
|
||||
const aiVector3D& pV3 = m.verts[ face.indices.size() - 1 ];
|
||||
const aiVector3D &pV1 = curMesh.verts[face.indices[0]];
|
||||
const aiVector3D &pV2 = curMesh.verts[face.indices[1]];
|
||||
const aiVector3D &pV3 = curMesh.verts[face.indices.size() - 1];
|
||||
faceNormal = (pV2 - pV1) ^ (pV3 - pV1).Normalize();
|
||||
fnOK = true;
|
||||
}
|
||||
*norms = faceNormal;
|
||||
} else {
|
||||
*norms = curMesh.normals[face.indices[n]];
|
||||
}
|
||||
else *norms = m.normals[ face.indices[n] ];
|
||||
|
||||
// copy texture coordinates
|
||||
if (uv && m.uv.size())
|
||||
|
|
|
@ -44,16 +44,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define INCLUDED_AI_STEPFILE_H
|
||||
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "FBX/FBXDocument.h" //ObjectMap::value_type
|
||||
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4456 )
|
||||
#pragma warning(disable : 4245)
|
||||
//
|
||||
#if _MSC_VER > 1500 || (defined __GNUC___)
|
||||
#define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
|
||||
|
@ -86,7 +89,6 @@ namespace Assimp {
|
|||
// ********************************************************************************
|
||||
// before things get complicated, this is the basic outline:
|
||||
|
||||
|
||||
namespace STEP {
|
||||
|
||||
namespace EXPRESS {
|
||||
|
@ -107,16 +109,15 @@ namespace STEP {
|
|||
// is a list of pointers to conversion functions to build up the
|
||||
// object tree from an input file.
|
||||
class ConversionSchema;
|
||||
}
|
||||
} // namespace EXPRESS
|
||||
|
||||
struct HeaderInfo;
|
||||
class Object;
|
||||
class LazyObject;
|
||||
class DB;
|
||||
|
||||
|
||||
typedef Object *(*ConvertObjectProc)(const DB &db, const EXPRESS::LIST ¶ms);
|
||||
}
|
||||
} // namespace STEP
|
||||
|
||||
// ********************************************************************************
|
||||
|
||||
|
@ -134,7 +135,6 @@ namespace STEP {
|
|||
SyntaxError(const std::string &s, uint64_t line = LINE_NOT_SPECIFIED);
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Exception class used by the STEP loading & parsing code when a type
|
||||
* error (i.e. an entity expects a string but receives a bool) occurs.
|
||||
|
@ -149,31 +149,26 @@ namespace STEP {
|
|||
TypeError(const std::string &s, uint64_t entity = ENTITY_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED);
|
||||
};
|
||||
|
||||
|
||||
// hack to make a given member template-dependent
|
||||
template <typename T, typename T2>
|
||||
T2 &Couple(T2 &in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
namespace EXPRESS {
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
//** Base class for all STEP data types */
|
||||
// -------------------------------------------------------------------------------
|
||||
class DataType
|
||||
{
|
||||
class DataType {
|
||||
public:
|
||||
typedef std::shared_ptr<const DataType> Out;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~DataType() {
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template <typename T>
|
||||
const T &To() const {
|
||||
return dynamic_cast<const T &>(*this);
|
||||
|
@ -184,7 +179,6 @@ namespace STEP {
|
|||
return dynamic_cast<T &>(*this);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
const T *ToPtr() const {
|
||||
return dynamic_cast<const T *>(this);
|
||||
|
@ -209,7 +203,6 @@ namespace STEP {
|
|||
}
|
||||
|
||||
public:
|
||||
|
||||
/** parse a variable from a string and set 'inout' to the character
|
||||
* behind the last consumed character. An optional schema enables,
|
||||
* if specified, automatic conversion of custom data types.
|
||||
|
@ -229,8 +222,7 @@ namespace STEP {
|
|||
// -------------------------------------------------------------------------------
|
||||
/** Sentinel class to represent explicitly unset (optional) fields ($) */
|
||||
// -------------------------------------------------------------------------------
|
||||
class UNSET : public DataType
|
||||
{
|
||||
class UNSET : public DataType {
|
||||
public:
|
||||
private:
|
||||
};
|
||||
|
@ -238,8 +230,7 @@ namespace STEP {
|
|||
// -------------------------------------------------------------------------------
|
||||
/** Sentinel class to represent explicitly derived fields (*) */
|
||||
// -------------------------------------------------------------------------------
|
||||
class ISDERIVED : public DataType
|
||||
{
|
||||
class ISDERIVED : public DataType {
|
||||
public:
|
||||
private:
|
||||
};
|
||||
|
@ -248,28 +239,20 @@ namespace STEP {
|
|||
/** Shared implementation for some of the primitive data type, i.e. int, float */
|
||||
// -------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
class PrimitiveDataType : public DataType
|
||||
{
|
||||
class PrimitiveDataType : public DataType {
|
||||
public:
|
||||
|
||||
// This is the type that will cd ultimatively be used to
|
||||
// expose this data type to the user.
|
||||
typedef T Out;
|
||||
|
||||
public:
|
||||
|
||||
PrimitiveDataType() {}
|
||||
PrimitiveDataType(const T& val)
|
||||
: val(val)
|
||||
{}
|
||||
PrimitiveDataType(const T &val) :
|
||||
val(val) {}
|
||||
|
||||
PrimitiveDataType(const PrimitiveDataType &o) {
|
||||
(*this) = o;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
operator const T &() const {
|
||||
return val;
|
||||
}
|
||||
|
@ -281,7 +264,6 @@ namespace STEP {
|
|||
|
||||
protected:
|
||||
T val;
|
||||
|
||||
};
|
||||
|
||||
typedef PrimitiveDataType<int64_t> INTEGER;
|
||||
|
@ -289,18 +271,13 @@ namespace STEP {
|
|||
typedef PrimitiveDataType<double> NUMBER;
|
||||
typedef PrimitiveDataType<std::string> STRING;
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Generic base class for all enumerated types */
|
||||
// -------------------------------------------------------------------------------
|
||||
class ENUMERATION : public STRING
|
||||
{
|
||||
class ENUMERATION : public STRING {
|
||||
public:
|
||||
|
||||
ENUMERATION (const std::string& val)
|
||||
: STRING(val)
|
||||
{}
|
||||
ENUMERATION(const std::string &val) :
|
||||
STRING(val) {}
|
||||
|
||||
private:
|
||||
};
|
||||
|
@ -310,19 +287,16 @@ namespace STEP {
|
|||
// -------------------------------------------------------------------------------
|
||||
/** This is just a reference to an entity/object somewhere else */
|
||||
// -------------------------------------------------------------------------------
|
||||
class ENTITY : public PrimitiveDataType<uint64_t>
|
||||
{
|
||||
class ENTITY : public PrimitiveDataType<uint64_t> {
|
||||
public:
|
||||
|
||||
ENTITY(uint64_t val)
|
||||
: PrimitiveDataType<uint64_t>(val)
|
||||
{
|
||||
ENTITY(uint64_t val) :
|
||||
PrimitiveDataType<uint64_t>(val) {
|
||||
ai_assert(val != 0);
|
||||
}
|
||||
|
||||
ENTITY()
|
||||
: PrimitiveDataType<uint64_t>(TypeError::ENTITY_NOT_SPECIFIED)
|
||||
{
|
||||
ENTITY() :
|
||||
PrimitiveDataType<uint64_t>(TypeError::ENTITY_NOT_SPECIFIED) {
|
||||
// empty
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -331,10 +305,8 @@ namespace STEP {
|
|||
// -------------------------------------------------------------------------------
|
||||
/** Wrap any STEP aggregate: LIST, SET, ... */
|
||||
// -------------------------------------------------------------------------------
|
||||
class LIST : public DataType
|
||||
{
|
||||
class LIST : public DataType {
|
||||
public:
|
||||
|
||||
// access a particular list index, throw std::range_error for wrong indices
|
||||
std::shared_ptr<const DataType> operator[](size_t index) const {
|
||||
return members[index];
|
||||
|
@ -345,13 +317,11 @@ namespace STEP {
|
|||
}
|
||||
|
||||
public:
|
||||
|
||||
/** @see DaraType::Parse */
|
||||
static std::shared_ptr<const EXPRESS::LIST> Parse(const char *&inout,
|
||||
uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
|
||||
const EXPRESS::ConversionSchema *schema = NULL);
|
||||
|
||||
|
||||
private:
|
||||
typedef std::vector<std::shared_ptr<const DataType>> MemberList;
|
||||
MemberList members;
|
||||
|
@ -359,13 +329,13 @@ namespace STEP {
|
|||
|
||||
class BINARY : public PrimitiveDataType<uint32_t> {
|
||||
public:
|
||||
BINARY(uint32_t val)
|
||||
: PrimitiveDataType<uint32_t>(val) {
|
||||
BINARY(uint32_t val) :
|
||||
PrimitiveDataType<uint32_t>(val) {
|
||||
// empty
|
||||
}
|
||||
|
||||
BINARY()
|
||||
: PrimitiveDataType<uint32_t>(TypeError::ENTITY_NOT_SPECIFIED_32) {
|
||||
BINARY() :
|
||||
PrimitiveDataType<uint32_t>(TypeError::ENTITY_NOT_SPECIFIED_32) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
@ -378,9 +348,8 @@ namespace STEP {
|
|||
class ConversionSchema {
|
||||
public:
|
||||
struct SchemaEntry {
|
||||
SchemaEntry( const char *name, ConvertObjectProc func )
|
||||
: mName( name )
|
||||
, mFunc(func) {
|
||||
SchemaEntry(const char *name, ConvertObjectProc func) :
|
||||
mName(name), mFunc(func) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -396,7 +365,6 @@ namespace STEP {
|
|||
}
|
||||
|
||||
ConversionSchema() {
|
||||
|
||||
}
|
||||
|
||||
ConvertObjectProc GetConverterProc(const std::string &name) const {
|
||||
|
@ -413,7 +381,6 @@ namespace STEP {
|
|||
return it == converters.end() ? nullptr : (*it).first.c_str();
|
||||
}
|
||||
|
||||
|
||||
template <size_t N>
|
||||
const ConversionSchema &operator=(const SchemaEntry (&schemas)[N]) {
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
|
@ -426,31 +393,26 @@ namespace STEP {
|
|||
private:
|
||||
ConverterMap converters;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
} // namespace EXPRESS
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
/** Bundle all the relevant info from a STEP header, parts of which may later
|
||||
* be plainly dumped to the logfile, whereas others may help the caller pick an
|
||||
* appropriate loading strategy.*/
|
||||
// ------------------------------------------------------------------------------
|
||||
struct HeaderInfo
|
||||
{
|
||||
struct HeaderInfo {
|
||||
std::string timestamp;
|
||||
std::string app;
|
||||
std::string fileSchema;
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
/** Base class for all concrete object instances */
|
||||
// ------------------------------------------------------------------------------
|
||||
class Object {
|
||||
public:
|
||||
Object(const char* classname = "unknown")
|
||||
: id( 0 )
|
||||
, classname(classname) {
|
||||
Object(const char *classname = "unknown") :
|
||||
id(0), classname(classname) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -500,14 +462,13 @@ namespace STEP {
|
|||
size_t GenericFill(const STEP::DB &db, const EXPRESS::LIST ¶ms, T *in);
|
||||
// (intentionally undefined)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
/** CRTP shared base class for use by concrete entity implementation classes */
|
||||
// ------------------------------------------------------------------------------
|
||||
template <typename TDerived, size_t arg_count>
|
||||
struct ObjectHelper : virtual Object {
|
||||
ObjectHelper()
|
||||
: aux_is_derived(0) {
|
||||
ObjectHelper() :
|
||||
aux_is_derived(0) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -539,18 +500,16 @@ namespace STEP {
|
|||
// ------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct Maybe {
|
||||
Maybe()
|
||||
: have() {
|
||||
Maybe() :
|
||||
have() {
|
||||
// empty
|
||||
}
|
||||
|
||||
explicit Maybe(const T& ptr)
|
||||
: ptr(ptr)
|
||||
, have(true) {
|
||||
explicit Maybe(const T &ptr) :
|
||||
ptr(ptr), have(true) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
void flag_invalid() {
|
||||
have = false;
|
||||
}
|
||||
|
@ -559,7 +518,6 @@ namespace STEP {
|
|||
have = true;
|
||||
}
|
||||
|
||||
|
||||
bool operator!() const {
|
||||
return !have;
|
||||
}
|
||||
|
@ -584,7 +542,8 @@ namespace STEP {
|
|||
}
|
||||
|
||||
private:
|
||||
template <typename T2> friend struct InternGenericConvert;
|
||||
template <typename T2>
|
||||
friend struct InternGenericConvert;
|
||||
|
||||
operator T &() {
|
||||
return ptr;
|
||||
|
@ -673,14 +632,12 @@ namespace STEP {
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
inline
|
||||
bool operator==( std::shared_ptr<LazyObject> lo, T whatever ) {
|
||||
inline bool operator==(std::shared_ptr<LazyObject> lo, T whatever) {
|
||||
return *lo == whatever; // XXX use std::forward if we have 0x
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline
|
||||
bool operator==( const std::pair<uint64_t, std::shared_ptr<LazyObject> >& lo, T whatever ) {
|
||||
inline bool operator==(const std::pair<uint64_t, std::shared_ptr<LazyObject>> &lo, T whatever) {
|
||||
return *(lo.second) == whatever; // XXX use std::forward if we have 0x
|
||||
}
|
||||
|
||||
|
@ -690,8 +647,8 @@ namespace STEP {
|
|||
template <typename T>
|
||||
struct Lazy {
|
||||
typedef Lazy Out;
|
||||
Lazy(const LazyObject* obj = nullptr)
|
||||
: obj(obj) {
|
||||
Lazy(const LazyObject *obj = nullptr) :
|
||||
obj(obj) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -780,8 +737,7 @@ namespace STEP {
|
|||
// XXX is this really how the EXPRESS notation ([?:3],[1:3]) is intended?
|
||||
if (max_cnt && inp->GetSize() > max_cnt) {
|
||||
ASSIMP_LOG_WARN("too many aggregate elements");
|
||||
}
|
||||
else if (inp->GetSize() < min_cnt) {
|
||||
} else if (inp->GetSize() < min_cnt) {
|
||||
ASSIMP_LOG_WARN("too few aggregate elements");
|
||||
}
|
||||
|
||||
|
@ -791,8 +747,7 @@ namespace STEP {
|
|||
out.push_back(typename ListOf<T, min_cnt, max_cnt>::OutScalar());
|
||||
try {
|
||||
GenericConvert(out.back(), (*inp)[i], db);
|
||||
}
|
||||
catch(const TypeError& t) {
|
||||
} catch (const TypeError &t) {
|
||||
throw TypeError(t.what() + std::string(" of aggregate"));
|
||||
}
|
||||
}
|
||||
|
@ -825,13 +780,11 @@ namespace STEP {
|
|||
* STEP file. DB's are exclusively maintained by the functions in
|
||||
* STEPFileReader.h*/
|
||||
// -------------------------------------------------------------------------------
|
||||
class DB
|
||||
{
|
||||
class DB {
|
||||
friend DB *ReadFileHeader(std::shared_ptr<IOStream> stream);
|
||||
friend void ReadFile(DB &db, const EXPRESS::ConversionSchema &scheme,
|
||||
const char *const *types_to_track, size_t len,
|
||||
const char* const* inverse_indices_to_track, size_t len2
|
||||
);
|
||||
const char *const *inverse_indices_to_track, size_t len2);
|
||||
|
||||
friend class LazyObject;
|
||||
|
||||
|
@ -855,13 +808,8 @@ namespace STEP {
|
|||
typedef std::pair<RefMap::const_iterator, RefMap::const_iterator> RefMapRange;
|
||||
|
||||
private:
|
||||
|
||||
DB(std::shared_ptr<StreamReaderLE> reader)
|
||||
: reader(reader)
|
||||
, splitter(*reader,true,true)
|
||||
, evaluated_count()
|
||||
, schema( nullptr )
|
||||
{}
|
||||
DB(std::shared_ptr<StreamReaderLE> reader) :
|
||||
reader(reader), splitter(*reader, true, true), evaluated_count(), schema(nullptr) {}
|
||||
|
||||
public:
|
||||
~DB() {
|
||||
|
@ -902,7 +850,6 @@ namespace STEP {
|
|||
return inv_whitelist.find(type) != inv_whitelist.end();
|
||||
}
|
||||
|
||||
|
||||
// get the yet unevaluated object record with a given id
|
||||
const LazyObject *GetObject(uint64_t id) const {
|
||||
const ObjectMap::const_iterator it = objects.find(id);
|
||||
|
@ -912,7 +859,6 @@ namespace STEP {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
// get an arbitrary object out of the soup with the only restriction being its type.
|
||||
const LazyObject *GetObject(const std::string &type) const {
|
||||
const ObjectMapByType::const_iterator it = objects_bytype.find(type);
|
||||
|
@ -939,7 +885,6 @@ namespace STEP {
|
|||
return *o;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ASSIMP_IFC_TEST
|
||||
|
||||
// evaluate *all* entities in the file. this is a power test for the loader
|
||||
|
@ -953,7 +898,6 @@ namespace STEP {
|
|||
#endif
|
||||
|
||||
private:
|
||||
|
||||
// full access only offered to close friends - they should
|
||||
// use the provided getters rather than messing around with
|
||||
// the members directly.
|
||||
|
@ -974,7 +918,6 @@ namespace STEP {
|
|||
schema = &_schema;
|
||||
}
|
||||
|
||||
|
||||
void SetTypesToTrack(const char *const *types, size_t N) {
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
objects_bytype[types[i]] = ObjectSet();
|
||||
|
@ -1009,8 +952,10 @@ namespace STEP {
|
|||
const EXPRESS::ConversionSchema *schema;
|
||||
};
|
||||
|
||||
}
|
||||
#pragma warning( pop )
|
||||
|
||||
} // end Assimp
|
||||
} // namespace STEP
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // INCLUDED_AI_STEPFILE_H
|
||||
|
|
|
@ -297,8 +297,7 @@ std::string XGLImporter::GetElementName()
|
|||
|
||||
std::string ret;
|
||||
ret.resize(len);
|
||||
|
||||
std::transform(s,s+len,ret.begin(),::tolower);
|
||||
std::transform(s, s + len, ret.begin(), ::ToLower<char>);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -618,26 +617,22 @@ bool XGLImporter::ReadMesh(TempScope& scope)
|
|||
bool has[3] = {0};
|
||||
|
||||
while (ReadElementUpToClosing(s.c_str())) {
|
||||
const std::string& s = GetElementName();
|
||||
if (s == "fv1" || s == "lv1" || s == "pv1") {
|
||||
const std::string& elemName = GetElementName();
|
||||
if (elemName == "fv1" || elemName == "lv1" || elemName == "pv1") {
|
||||
ReadFaceVertex(t,tf[0]);
|
||||
has[0] = true;
|
||||
}
|
||||
else if (s == "fv2" || s == "lv2") {
|
||||
} else if (elemName == "fv2" || elemName == "lv2") {
|
||||
ReadFaceVertex(t, tf[1]);
|
||||
has[1] = true;
|
||||
}
|
||||
else if (s == "fv3") {
|
||||
} else if (elemName == "fv3") {
|
||||
ReadFaceVertex(t, tf[2]);
|
||||
has[2] = true;
|
||||
}
|
||||
else if (s == "mat") {
|
||||
} else if (elemName == "mat") {
|
||||
if (mid != ~0u) {
|
||||
LogWarn("only one material tag allowed per <f>");
|
||||
}
|
||||
mid = ResolveMaterialRef(scope);
|
||||
}
|
||||
else if (s == "matref") {
|
||||
} else if (elemName == "matref") {
|
||||
if (mid != ~0u) {
|
||||
LogWarn("only one material tag allowed per <f>");
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue