diff options
Diffstat (limited to 'src/mesh/assimp-master/code/AssetLib/AC/ACLoader.cpp')
-rw-r--r-- | src/mesh/assimp-master/code/AssetLib/AC/ACLoader.cpp | 865 |
1 files changed, 0 insertions, 865 deletions
diff --git a/src/mesh/assimp-master/code/AssetLib/AC/ACLoader.cpp b/src/mesh/assimp-master/code/AssetLib/AC/ACLoader.cpp deleted file mode 100644 index e93624b..0000000 --- a/src/mesh/assimp-master/code/AssetLib/AC/ACLoader.cpp +++ /dev/null @@ -1,865 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2022, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -/** @file Implementation of the AC3D importer class */ - -#ifndef ASSIMP_BUILD_NO_AC_IMPORTER - -// internal headers -#include "ACLoader.h" -#include "Common/Importer.h" -#include <assimp/BaseImporter.h> -#include <assimp/ParsingUtils.h> -#include <assimp/Subdivision.h> -#include <assimp/config.h> -#include <assimp/fast_atof.h> -#include <assimp/importerdesc.h> -#include <assimp/light.h> -#include <assimp/material.h> -#include <assimp/scene.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/IOSystem.hpp> -#include <assimp/Importer.hpp> -#include <memory> - -using namespace Assimp; - -static const aiImporterDesc desc = { - "AC3D Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour, - 0, - 0, - 0, - 0, - "ac acc ac3d" -}; - -// ------------------------------------------------------------------------------------------------ -// skip to the next token -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 " -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 -template <class T> -inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name, size_t name_length, size_t num, T *out) { - buffer = AcSkipToNextToken(buffer); - if (0 != name_length) { - if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { - ASSIMP_LOG_ERROR("AC3D: Unexpected token. ", name, " was expected."); - return buffer; - } - buffer += name_length + 1; - } - for (unsigned int _i = 0; _i < num; ++_i) { - buffer = AcSkipToNextToken(buffer); - buffer = fast_atoreal_move<float>(buffer, ((float *)out)[_i]); - } - - return buffer; -} - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -AC3DImporter::AC3DImporter() : - buffer(), - configSplitBFCull(), - configEvalSubdivision(), - mNumMeshes(), - mLights(), - mLightsCounter(0), - mGroupsCounter(0), - mPolysCounter(0), - mWorldsCounter(0) { - // nothing to be done here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -AC3DImporter::~AC3DImporter() { - // nothing to be done here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { - static const uint32_t tokens[] = { AI_MAKE_MAGIC("AC3D") }; - return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); -} - -// ------------------------------------------------------------------------------------------------ -// Loader meta information -const aiImporterDesc *AC3DImporter::GetInfo() const { - return &desc; -} - -// ------------------------------------------------------------------------------------------------ -// Get a pointer to the next line from the file -bool AC3DImporter::GetNextLine() { - SkipLine(&buffer); - return SkipSpaces(&buffer); -} - -// ------------------------------------------------------------------------------------------------ -// Parse an object section in an AC file -void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) { - if (!TokenMatch(buffer, "OBJECT", 6)) - return; - - SkipSpaces(&buffer); - - ++mNumMeshes; - - objects.push_back(Object()); - Object &obj = objects.back(); - - aiLight *light = nullptr; - if (!ASSIMP_strincmp(buffer, "light", 5)) { - // This is a light source. Add it to the list - mLights->push_back(light = new aiLight()); - - // Return a point light with no attenuation - light->mType = aiLightSource_POINT; - light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f, 1.f, 1.f); - light->mAttenuationConstant = 1.f; - - // Generate a default name for both the light source and the node - // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version. - light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1); - obj.name = std::string(light->mName.data); - - ASSIMP_LOG_VERBOSE_DEBUG("AC3D: Light source encountered"); - obj.type = Object::Light; - } else if (!ASSIMP_strincmp(buffer, "group", 5)) { - obj.type = Object::Group; - } else if (!ASSIMP_strincmp(buffer, "world", 5)) { - obj.type = Object::World; - } else - obj.type = Object::Poly; - while (GetNextLine()) { - if (TokenMatch(buffer, "kids", 4)) { - SkipSpaces(&buffer); - unsigned int num = strtoul10(buffer, &buffer); - GetNextLine(); - if (num) { - // load the children of this object recursively - obj.children.reserve(num); - for (unsigned int i = 0; i < num; ++i) - LoadObjectSection(obj.children); - } - return; - } else if (TokenMatch(buffer, "name", 4)) { - SkipSpaces(&buffer); - buffer = AcGetString(buffer, obj.name); - - // If this is a light source, we'll also need to store - // the name of the node in it. - if (light) { - light->mName.Set(obj.name); - } - } else if (TokenMatch(buffer, "texture", 7)) { - SkipSpaces(&buffer); - buffer = AcGetString(buffer, obj.texture); - } else if (TokenMatch(buffer, "texrep", 6)) { - SkipSpaces(&buffer); - 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); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texOffset); - } else if (TokenMatch(buffer, "rot", 3)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 9, &obj.rotation); - } else if (TokenMatch(buffer, "loc", 3)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &obj.translation); - } else if (TokenMatch(buffer, "subdiv", 6)) { - SkipSpaces(&buffer); - obj.subDiv = strtoul10(buffer, &buffer); - } else if (TokenMatch(buffer, "crease", 6)) { - SkipSpaces(&buffer); - obj.crease = fast_atof(buffer); - } else if (TokenMatch(buffer, "numvert", 7)) { - SkipSpaces(&buffer); - - unsigned int t = strtoul10(buffer, &buffer); - if (t >= AI_MAX_ALLOC(aiVector3D)) { - throw DeadlyImportError("AC3D: Too many vertices, would run out of memory"); - } - obj.vertices.reserve(t); - for (unsigned int i = 0; i < t; ++i) { - if (!GetNextLine()) { - ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet"); - break; - } else if (!IsNumeric(*buffer)) { - ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet"); - --buffer; // make sure the line is processed a second time - break; - } - obj.vertices.push_back(aiVector3D()); - aiVector3D &v = obj.vertices.back(); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &v.x); - } - } else if (TokenMatch(buffer, "numsurf", 7)) { - SkipSpaces(&buffer); - - bool Q3DWorkAround = false; - - const unsigned int t = strtoul10(buffer, &buffer); - obj.surfaces.reserve(t); - for (unsigned int i = 0; i < t; ++i) { - GetNextLine(); - if (!TokenMatch(buffer, "SURF", 4)) { - // FIX: this can occur for some files - Quick 3D for - // example writes no surf chunks - if (!Q3DWorkAround) { - ASSIMP_LOG_WARN("AC3D: SURF token was expected"); - ASSIMP_LOG_VERBOSE_DEBUG("Continuing with Quick3D Workaround enabled"); - } - --buffer; // make sure the line is processed a second time - // break; --- see fix notes above - - Q3DWorkAround = true; - } - SkipSpaces(&buffer); - obj.surfaces.push_back(Surface()); - Surface &surf = obj.surfaces.back(); - surf.flags = strtoul_cppstyle(buffer); - - while (1) { - if (!GetNextLine()) { - throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete"); - } - if (TokenMatch(buffer, "mat", 3)) { - SkipSpaces(&buffer); - surf.mat = strtoul10(buffer); - } else if (TokenMatch(buffer, "refs", 4)) { - // --- see fix notes above - if (Q3DWorkAround) { - if (!surf.entries.empty()) { - buffer -= 6; - break; - } - } - - SkipSpaces(&buffer); - const unsigned int m = strtoul10(buffer); - surf.entries.reserve(m); - - obj.numRefs += m; - - for (unsigned int k = 0; k < m; ++k) { - if (!GetNextLine()) { - ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: surface references are incomplete"); - break; - } - surf.entries.push_back(Surface::SurfaceEntry()); - Surface::SurfaceEntry &entry = surf.entries.back(); - - entry.first = strtoul10(buffer, &buffer); - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &entry.second); - } - } else { - --buffer; // make sure the line is processed a second time - break; - } - } - } - } - } - ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: \'kids\' line was expected"); -} - -// ------------------------------------------------------------------------------------------------ -// Convert a material from AC3DImporter::Material to aiMaterial -void AC3DImporter::ConvertMaterial(const Object &object, - const Material &matSrc, - aiMaterial &matDest) { - aiString s; - - if (matSrc.name.length()) { - s.Set(matSrc.name); - matDest.AddProperty(&s, AI_MATKEY_NAME); - } - if (object.texture.length()) { - s.Set(object.texture); - matDest.AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0)); - - // UV transformation - if (1.f != object.texRepeat.x || 1.f != object.texRepeat.y || - object.texOffset.x || object.texOffset.y) { - aiUVTransform transform; - transform.mScaling = object.texRepeat; - transform.mTranslation = object.texOffset; - matDest.AddProperty(&transform, 1, AI_MATKEY_UVTRANSFORM_DIFFUSE(0)); - } - } - - matDest.AddProperty<aiColor3D>(&matSrc.rgb, 1, AI_MATKEY_COLOR_DIFFUSE); - matDest.AddProperty<aiColor3D>(&matSrc.amb, 1, AI_MATKEY_COLOR_AMBIENT); - matDest.AddProperty<aiColor3D>(&matSrc.emis, 1, AI_MATKEY_COLOR_EMISSIVE); - matDest.AddProperty<aiColor3D>(&matSrc.spec, 1, AI_MATKEY_COLOR_SPECULAR); - - int n = -1; - if (matSrc.shin) { - n = aiShadingMode_Phong; - matDest.AddProperty<float>(&matSrc.shin, 1, AI_MATKEY_SHININESS); - } else { - n = aiShadingMode_Gouraud; - } - matDest.AddProperty<int>(&n, 1, AI_MATKEY_SHADING_MODEL); - - float f = 1.f - matSrc.trans; - matDest.AddProperty<float>(&f, 1, AI_MATKEY_OPACITY); -} - -// ------------------------------------------------------------------------------------------------ -// Converts the loaded data to the internal verbose representation -aiNode *AC3DImporter::ConvertObjectSection(Object &object, - std::vector<aiMesh *> &meshes, - std::vector<aiMaterial *> &outMaterials, - const std::vector<Material> &materials, - aiNode *parent) { - aiNode *node = new aiNode(); - node->mParent = parent; - if (object.vertices.size()) { - if (!object.surfaces.size() || !object.numRefs) { - /* " An object with 7 vertices (no surfaces, no materials defined). - This is a good way of getting point data into AC3D. - The Vertex->create convex-surface/object can be used on these - vertices to 'wrap' a 3d shape around them " - (http://www.opencity.info/html/ac3dfileformat.html) - - therefore: if no surfaces are defined return point data only - */ - - ASSIMP_LOG_INFO("AC3D: No surfaces defined in object definition, " - "a point list is returned"); - - meshes.push_back(new aiMesh()); - aiMesh *mesh = meshes.back(); - - mesh->mNumFaces = mesh->mNumVertices = (unsigned int)object.vertices.size(); - aiFace *faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; - aiVector3D *verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - - for (unsigned int i = 0; i < mesh->mNumVertices; ++i, ++faces, ++verts) { - *verts = object.vertices[i]; - faces->mNumIndices = 1; - faces->mIndices = new unsigned int[1]; - faces->mIndices[0] = i; - } - - // use the primary material in this case. this should be the - // default material if all objects of the file contain points - // and no faces. - mesh->mMaterialIndex = 0; - outMaterials.push_back(new aiMaterial()); - ConvertMaterial(object, materials[0], *outMaterials.back()); - } else { - // need to generate one or more meshes for this object. - // find out how many different materials we have - typedef std::pair<unsigned int, unsigned int> IntPair; - typedef std::vector<IntPair> MatTable; - MatTable needMat(materials.size(), IntPair(0, 0)); - - std::vector<Surface>::iterator it, end = object.surfaces.end(); - std::vector<Surface::SurfaceEntry>::iterator it2, end2; - - for (it = object.surfaces.begin(); it != end; ++it) { - unsigned int idx = (*it).mat; - if (idx >= needMat.size()) { - ASSIMP_LOG_ERROR("AC3D: material index is out of range"); - idx = 0; - } - if ((*it).entries.empty()) { - ASSIMP_LOG_WARN("AC3D: surface her zero vertex references"); - } - - // validate all vertex indices to make sure we won't crash here - for (it2 = (*it).entries.begin(), - end2 = (*it).entries.end(); - it2 != end2; ++it2) { - if ((*it2).first >= object.vertices.size()) { - ASSIMP_LOG_WARN("AC3D: Invalid vertex reference"); - (*it2).first = 0; - } - } - - if (!needMat[idx].first) { - ++node->mNumMeshes; - } - - switch ((*it).GetType()) { - // closed line - case Surface::ClosedLine: - needMat[idx].first += (unsigned int)(*it).entries.size(); - needMat[idx].second += (unsigned int)(*it).entries.size() << 1u; - break; - - // unclosed line - case Surface::OpenLine: - needMat[idx].first += (unsigned int)(*it).entries.size() - 1; - needMat[idx].second += ((unsigned int)(*it).entries.size() - 1) << 1u; - break; - - // triangle strip - case Surface::TriangleStrip: - needMat[idx].first += (unsigned int)(*it).entries.size() - 2; - needMat[idx].second += ((unsigned int)(*it).entries.size() - 2) * 3; - break; - - default: - // Coerce unknowns to a polygon and warn - ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown: ", (*it).flags); - (*it).flags &= ~(Surface::Mask); - // fallthrough - - // polygon - case Surface::Polygon: - // the number of faces increments by one, the number - // of vertices by surface.numref. - needMat[idx].first++; - needMat[idx].second += (unsigned int)(*it).entries.size(); - }; - } - unsigned int *pip = node->mMeshes = new unsigned int[node->mNumMeshes]; - unsigned int mat = 0; - const size_t oldm = meshes.size(); - for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end(); - cit != cend; ++cit, ++mat) { - if (!(*cit).first) { - continue; - } - - // allocate a new aiMesh object - *pip++ = (unsigned int)meshes.size(); - aiMesh *mesh = new aiMesh(); - meshes.push_back(mesh); - - mesh->mMaterialIndex = static_cast<unsigned int>(outMaterials.size()); - outMaterials.push_back(new aiMaterial()); - ConvertMaterial(object, materials[mat], *outMaterials.back()); - - // allocate storage for vertices and normals - mesh->mNumFaces = (*cit).first; - if (mesh->mNumFaces == 0) { - throw DeadlyImportError("AC3D: No faces"); - } else if (mesh->mNumFaces > AI_MAX_ALLOC(aiFace)) { - throw DeadlyImportError("AC3D: Too many faces, would run out of memory"); - } - aiFace *faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; - - mesh->mNumVertices = (*cit).second; - if (mesh->mNumVertices == 0) { - throw DeadlyImportError("AC3D: No vertices"); - } else if (mesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) { - throw DeadlyImportError("AC3D: Too many vertices, would run out of memory"); - } - aiVector3D *vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - unsigned int cur = 0; - - // allocate UV coordinates, but only if the texture name for the - // surface is not empty - aiVector3D *uv = nullptr; - if (object.texture.length()) { - uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; - mesh->mNumUVComponents[0] = 2; - } - - for (it = object.surfaces.begin(); it != end; ++it) { - if (mat == (*it).mat) { - const Surface &src = *it; - - // closed polygon - uint8_t type = (*it).GetType(); - if (type == Surface::Polygon) { - aiFace &face = *faces++; - 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]; - face.mIndices[i] = cur++; - - // copy vertex positions - if (static_cast<unsigned>(vertices - mesh->mVertices) >= mesh->mNumVertices) { - throw DeadlyImportError("AC3D: Invalid number of vertices"); - } - *vertices = object.vertices[entry.first] + object.translation; - - // copy texture coordinates - if (uv) { - uv->x = entry.second.x; - uv->y = entry.second.y; - ++uv; - } - } - } - } else if (type == Surface::TriangleStrip) { - for (unsigned int i = 0; i < (unsigned int)src.entries.size() - 2; ++i) { - const Surface::SurfaceEntry &entry1 = src.entries[i]; - const Surface::SurfaceEntry &entry2 = src.entries[i + 1]; - const Surface::SurfaceEntry &entry3 = src.entries[i + 2]; - - // skip degenerate triangles - if (object.vertices[entry1.first] == object.vertices[entry2.first] || - object.vertices[entry1.first] == object.vertices[entry3.first] || - object.vertices[entry2.first] == object.vertices[entry3.first]) { - mesh->mNumFaces--; - mesh->mNumVertices -= 3; - continue; - } - - aiFace &face = *faces++; - face.mNumIndices = 3; - face.mIndices = new unsigned int[face.mNumIndices]; - face.mIndices[0] = cur++; - face.mIndices[1] = cur++; - face.mIndices[2] = cur++; - if (!(i & 1)) { - *vertices++ = object.vertices[entry1.first] + object.translation; - if (uv) { - uv->x = entry1.second.x; - uv->y = entry1.second.y; - ++uv; - } - *vertices++ = object.vertices[entry2.first] + object.translation; - if (uv) { - uv->x = entry2.second.x; - uv->y = entry2.second.y; - ++uv; - } - } else { - *vertices++ = object.vertices[entry2.first] + object.translation; - if (uv) { - uv->x = entry2.second.x; - uv->y = entry2.second.y; - ++uv; - } - *vertices++ = object.vertices[entry1.first] + object.translation; - if (uv) { - uv->x = entry1.second.x; - uv->y = entry1.second.y; - ++uv; - } - } - if (static_cast<unsigned>(vertices - mesh->mVertices) >= mesh->mNumVertices) { - throw DeadlyImportError("AC3D: Invalid number of vertices"); - } - *vertices++ = object.vertices[entry3.first] + object.translation; - if (uv) { - uv->x = entry3.second.x; - uv->y = entry3.second.y; - ++uv; - } - } - } else { - - it2 = (*it).entries.begin(); - - // either a closed or an unclosed line - unsigned int tmp = (unsigned int)(*it).entries.size(); - if (Surface::OpenLine == type) --tmp; - for (unsigned int m = 0; m < tmp; ++m) { - aiFace &face = *faces++; - - face.mNumIndices = 2; - face.mIndices = new unsigned int[2]; - face.mIndices[0] = cur++; - face.mIndices[1] = cur++; - - // copy vertex positions - if (it2 == (*it).entries.end()) { - throw DeadlyImportError("AC3D: Bad line"); - } - ai_assert((*it2).first < object.vertices.size()); - *vertices++ = object.vertices[(*it2).first]; - - // copy texture coordinates - if (uv) { - uv->x = (*it2).second.x; - uv->y = (*it2).second.y; - ++uv; - } - - if (Surface::ClosedLine == type && tmp - 1 == m) { - // if this is a closed line repeat its beginning now - it2 = (*it).entries.begin(); - } else - ++it2; - - // second point - *vertices++ = object.vertices[(*it2).first]; - - if (uv) { - uv->x = (*it2).second.x; - uv->y = (*it2).second.y; - ++uv; - } - } - } - } - } - } - - // Now apply catmull clark subdivision if necessary. We split meshes into - // materials which is not done by AC3D during smoothing, so we need to - // collect all meshes using the same material group. - if (object.subDiv) { - if (configEvalSubdivision) { - std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); - ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: ", object.name); - - std::vector<aiMesh *> cpy(meshes.size() - oldm, nullptr); - div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true); - std::copy(cpy.begin(), cpy.end(), meshes.begin() + oldm); - - // previous meshes are deleted vy Subdivide(). - } else { - ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: ", object.name); - } - } - } - } - - if (object.name.length()) - node->mName.Set(object.name); - else { - // generate a name depending on the type of the node - switch (object.type) { - case Object::Group: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++); - break; - case Object::Poly: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++); - break; - case Object::Light: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++); - break; - - // there shouldn't be more than one world, but we don't care - case Object::World: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++); - break; - } - } - - // setup the local transformation matrix of the object - // compute the transformation offset to the parent node - node->mTransformation = aiMatrix4x4(object.rotation); - - if (object.type == Object::Group || !object.numRefs) { - node->mTransformation.a4 = object.translation.x; - node->mTransformation.b4 = object.translation.y; - node->mTransformation.c4 = object.translation.z; - } - - // add children to the object - if (object.children.size()) { - node->mNumChildren = (unsigned int)object.children.size(); - node->mChildren = new aiNode *[node->mNumChildren]; - for (unsigned int i = 0; i < node->mNumChildren; ++i) { - node->mChildren[i] = ConvertObjectSection(object.children[i], meshes, outMaterials, materials, node); - } - } - - return node; -} - -// ------------------------------------------------------------------------------------------------ -void AC3DImporter::SetupProperties(const Importer *pImp) { - configSplitBFCull = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL, 1) ? true : false; - configEvalSubdivision = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION, 1) ? true : false; -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void AC3DImporter::InternReadFile(const std::string &pFile, - aiScene *pScene, IOSystem *pIOHandler) { - std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb")); - - // Check whether we can read from the file - if (file.get() == nullptr) { - throw DeadlyImportError("Failed to open AC3D file ", pFile, "."); - } - - // allocate storage and copy the contents of the file to a memory buffer - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(), mBuffer2); - - buffer = &mBuffer2[0]; - mNumMeshes = 0; - - mLightsCounter = mPolysCounter = mWorldsCounter = mGroupsCounter = 0; - - if (::strncmp(buffer, "AC3D", 4)) { - throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found"); - } - - // print the file format version to the console - unsigned int version = HexDigitToDecimal(buffer[4]); - char msg[3]; - ASSIMP_itoa10(msg, 3, version); - ASSIMP_LOG_INFO("AC3D file format version: ", msg); - - std::vector<Material> materials; - materials.reserve(5); - - std::vector<Object> rootObjects; - rootObjects.reserve(5); - - std::vector<aiLight *> lights; - mLights = &lights; - - while (GetNextLine()) { - if (TokenMatch(buffer, "MATERIAL", 8)) { - materials.push_back(Material()); - Material &mat = materials.back(); - - // 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 - - buffer = AcSkipToNextToken(buffer); - if ('\"' == *buffer) { - buffer = AcGetString(buffer, mat.name); - buffer = AcSkipToNextToken(buffer); - } - - 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); - } - - if (rootObjects.empty() || !mNumMeshes) { - throw DeadlyImportError("AC3D: No meshes have been loaded"); - } - if (materials.empty()) { - ASSIMP_LOG_WARN("AC3D: No material has been found"); - materials.push_back(Material()); - } - - mNumMeshes += (mNumMeshes >> 2u) + 1; - std::vector<aiMesh *> meshes; - meshes.reserve(mNumMeshes); - - std::vector<aiMaterial *> omaterials; - materials.reserve(mNumMeshes); - - // generate a dummy root if there are multiple objects on the top layer - Object *root; - if (1 == rootObjects.size()) - root = &rootObjects[0]; - else { - root = new Object(); - } - - // now convert the imported stuff to our output data structure - pScene->mRootNode = ConvertObjectSection(*root, meshes, omaterials, materials); - if (1 != rootObjects.size()) { - delete root; - } - - if (!::strncmp(pScene->mRootNode->mName.data, "Node", 4)) { - pScene->mRootNode->mName.Set("<AC3DWorld>"); - } - - // copy meshes - if (meshes.empty()) { - throw DeadlyImportError("An unknown error occurred during converting"); - } - pScene->mNumMeshes = (unsigned int)meshes.size(); - pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; - ::memcpy(pScene->mMeshes, &meshes[0], pScene->mNumMeshes * sizeof(void *)); - - // copy materials - pScene->mNumMaterials = (unsigned int)omaterials.size(); - pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; - ::memcpy(pScene->mMaterials, &omaterials[0], pScene->mNumMaterials * sizeof(void *)); - - // copy lights - pScene->mNumLights = (unsigned int)lights.size(); - if (lights.size()) { - pScene->mLights = new aiLight *[lights.size()]; - ::memcpy(pScene->mLights, &lights[0], lights.size() * sizeof(void *)); - } -} - -#endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER |