Compare commits

..
Author SHA1 Message Date
Kim Kulling 30b20e07e7 Fix possible overflow 2025-09-23 21:28:54 +02:00
Kim Kulling fa18d3dde6 Fix possible overflow 2025-09-23 21:24:58 +02:00
121 changed files with 1015 additions and 1112 deletions
+3 -3
View File
@@ -109,7 +109,7 @@ jobs:
run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }}
shell: bash
- uses: actions/upload-artifact@v5
- uses: actions/upload-artifact@v4
if: matrix.name == 'windows-msvc'
with:
name: 'assimp-bins-${{ matrix.name }}'
@@ -141,7 +141,7 @@ jobs:
prerelease: true
- run: |
echo '${{steps.create-release.outputs.upload_url}}' > release_upload_url.txt
- uses: actions/upload-artifact@v5
- uses: actions/upload-artifact@v4
with:
name: create-release
path: release_upload_url.txt
@@ -188,7 +188,7 @@ jobs:
- id: upload-url
run: |
echo "url=$(cat create-release/release_upload_url.txt)" >> $GITHUB_OUTPUT
- uses: actions/download-artifact@v6
- uses: actions/download-artifact@v5
with:
name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'
- uses: actions/upload-release-asset@v1
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
dry-run: false
language: c++
- name: Upload Crash
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
+1 -1
View File
@@ -30,7 +30,7 @@ cmake --build .
Note that by default this builds a shared library into the `bin` directory. If you want to build it as a static library see the build options at the bottom of this file.
### Build instructions for Windows with Visual-Studio
First, you have to install Visual-Studio on your windows-system. You can get the Community-Version for free [here](https://visualstudio.microsoft.com/downloads/)
First, you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/
To generate the build environment for your IDE open a command prompt, navigate to your repo and type:
```bash
cmake CMakeLists.txt
+1 -1
View File
@@ -1,7 +1,7 @@
FROM gcc:1.5.1.0
RUN apt-get update \
apt-get install -y ninja-build cmake zlib1g-dev
apt-get install --no-install-recommends -y ninja-build cmake zlib1g-dev
WORKDIR /app
+7 -7
View File
@@ -64,7 +64,7 @@ Open Asset Import Library is implemented in C++. The directory structure looks l
/code Source code
/contrib Third-party libraries
/doc Documentation (Doxygen source and pre-compiled docs)
/fuzz Contains the test code for the Google Fuzzer project
/fuzz Contains the test code for the Google Fuzzer project
/include Public header C and C++ header files
/scripts Scripts are used to generate the loading code for some formats
/port Ports to other languages and scripts to maintain those.
@@ -74,12 +74,12 @@ Open Asset Import Library is implemented in C++. The directory structure looks l
The source code is organized in the following way:
code/Common The base implementation for importers and the infrastructure
code/CApi Special implementations which are only used for the C-API
code/Geometry A collection of geometry tools
code/Material The material system
code/PBR An exporter for physical-based models
code/PostProcessing The post-processing steps
code/Common The base implementation for importers and the infrastructure
code/CApi Special implementations which are only used for the C-API
code/Geometry A collection of geometry tools
code/Material The material system
code/PBR An exporter for physical-based models
code/PostProcessing The post-processing steps
code/AssetLib/<FormatName> Implementation for import and export of the format
### Contributing ###
+1 -1
View File
@@ -11,5 +11,5 @@ The current version of Assimp that's being supported with security updates:
## Reporting a Vulnerability
If you have found any security vulnerability you can contact us via
kim.kulling@assimp.org
kim.kulling@googlemail.com
+30 -33
View File
@@ -56,27 +56,23 @@ namespace Assimp {
static constexpr unsigned int NotSet = 0xcdcdcdcd;
using namespace D3DS;
// ------------------------------------------------------------------------------------------------
// Setup final material indices, generate a default material if necessary
// Setup final material indices, generae a default material if necessary
void Discreet3DSImporter::ReplaceDefaultMaterial() {
// Try to find an existing material that matches the
// typical default material setting:
// - no textures
// - diffuse color (in grey!)
// NOTE: This is here to work-around the fact that some
// NOTE: This is here to workaround the fact that some
// exporters are writing a default material, too.
unsigned int idx(NotSet);
for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
auto s = mScene->mMaterials[i].mName;
std::string s = mScene->mMaterials[i].mName;
for (char &it : s) {
it = static_cast<char>(::tolower(static_cast<unsigned char>(it)));
}
if (std::string::npos == s.find("default")) {
continue;
}
if (std::string::npos == s.find("default")) continue;
if (mScene->mMaterials[i].mDiffuse.r !=
mScene->mMaterials[i].mDiffuse.g ||
@@ -89,22 +85,22 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
idx = i;
}
if (NotSet == idx) {
idx = static_cast<unsigned int>(mScene->mMaterials.size());
idx = (unsigned int)mScene->mMaterials.size();
}
// now iterate through all meshes and through all faces and
// find all faces that are using the default material
unsigned int cnt = 0;
for (auto i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) {
for (auto a = i->mFaceMaterials.begin(); a != i->mFaceMaterials.end(); ++a) {
for (auto a = (*i).mFaceMaterials.begin(); a != (*i).mFaceMaterials.end(); ++a) {
// NOTE: The additional check seems to be necessary,
// some exporters seem to generate invalid data here
if (NotSet == *a) {
*a = idx;
if (NotSet == (*a)) {
(*a) = idx;
++cnt;
} else if ((*a) >= mScene->mMaterials.size()) {
*a = idx;
(*a) = idx;
ASSIMP_LOG_WARN("Material index overflow in 3DS file. Using default material");
++cnt;
}
@@ -323,14 +319,14 @@ void Discreet3DSImporter::ConvertMaterial(Material &oldMat, aiMaterial &mat) {
// ------------------------------------------------------------------------------------------------
// Split meshes by their materials and generate output aiMesh'es
void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
std::vector<aiMesh *> avOutMeshes;
MeshArray avOutMeshes;
avOutMeshes.reserve(mScene->mMeshes.size() * 2);
unsigned int iFaceCnt = 0, num = 0;
aiString name;
// we need to split all meshes by their materials
for (auto i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) {
for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) {
std::unique_ptr<std::vector<unsigned int>[]> aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]);
name.length = ASSIMP_itoa10(name.data, num++);
@@ -345,7 +341,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
if (aiSplit[p].empty()) {
continue;
}
auto *meshOut = new aiMesh();
aiMesh *meshOut = new aiMesh();
meshOut->mName = name;
meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
@@ -357,7 +353,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
avOutMeshes.push_back(meshOut);
// convert vertices
meshOut->mNumFaces = static_cast<unsigned int>(aiSplit[p].size());
meshOut->mNumFaces = (unsigned int)aiSplit[p].size();
meshOut->mNumVertices = meshOut->mNumFaces * 3;
// allocate enough storage for faces
@@ -405,7 +401,8 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
// ------------------------------------------------------------------------------------------------
// Add a node to the scenegraph and setup its final transformation
void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::Node *pcIn, aiMatrix4x4 & /*absTrafo*/) {
void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
D3DS::Node *pcIn, aiMatrix4x4 & /*absTrafo*/) {
std::vector<unsigned int> iArray;
iArray.reserve(3);
@@ -413,7 +410,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
// Find all meshes with the same name as the node
for (unsigned int a = 0; a < pcSOut->mNumMeshes; ++a) {
const auto *pcMesh = (const D3DS::Mesh *)pcSOut->mMeshes[a]->mColors[0];
const D3DS::Mesh *pcMesh = (const D3DS::Mesh *)pcSOut->mMeshes[a]->mColors[0];
ai_assert(nullptr != pcMesh);
if (pcIn->mName == pcMesh->mName)
@@ -422,7 +419,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
if (!iArray.empty()) {
// The matrix should be identical for all meshes with the
// same name. It HAS to be identical for all meshes .....
auto *imesh = ((D3DS::Mesh *)pcSOut->mMeshes[iArray[0]]->mColors[0]);
D3DS::Mesh *imesh = ((D3DS::Mesh *)pcSOut->mMeshes[iArray[0]]->mColors[0]);
// Compute the inverse of the transformation matrix to move the
// vertices back to their relative and local space
@@ -431,7 +428,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
mInvTransposed.Transpose();
aiVector3D pivot = pcIn->vPivot;
pcOut->mNumMeshes = static_cast<unsigned int>(iArray.size());
pcOut->mNumMeshes = (unsigned int)iArray.size();
pcOut->mMeshes = new unsigned int[iArray.size()];
for (unsigned int i = 0; i < iArray.size(); ++i) {
const unsigned int iIndex = iArray[i];
@@ -450,7 +447,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
// Handle negative transformation matrix determinant -> invert vertex x
if (imesh->mMat.Determinant() < 0.0f) {
// we *must* have normals
/* we *must* have normals */
for (pvCurrent = mesh->mVertices, t2 = mesh->mNormals; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
pvCurrent->x *= -1.f;
t2->x *= -1.f;
@@ -490,7 +487,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
if (pcIn->aRotationKeys.size()) {
// FIX to get to Assimp's quaternion conventions
for (auto it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) {
for (std::vector<aiQuatKey>::iterator it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) {
(*it).mValue.w *= -1.f;
}
@@ -602,11 +599,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
}
// Allocate a new node anim and setup its name
auto *nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
aiNodeAnim *nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
nda->mNodeName.Set(pcIn->mName);
// POSITION keys
if (!pcIn->aPositionKeys.empty()) {
if (pcIn->aPositionKeys.size() > 0) {
nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
::memcpy(nda->mPositionKeys, &pcIn->aPositionKeys[0],
@@ -614,7 +611,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
}
// ROTATION keys
if (!pcIn->aRotationKeys.empty()) {
if (pcIn->aRotationKeys.size() > 0) {
nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
@@ -630,7 +627,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
}
// SCALING keys
if (!pcIn->aScalingKeys.empty()) {
if (pcIn->aScalingKeys.size() > 0) {
nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
::memcpy(nda->mScalingKeys, &pcIn->aScalingKeys[0],
@@ -639,7 +636,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
}
// Allocate storage for children
const auto size = static_cast<unsigned int>(pcIn->mChildren.size());
const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
pcOut->mNumChildren = size;
if (size == 0) {
@@ -682,7 +679,7 @@ void CountTracks(D3DS::Node *node, unsigned int &cnt) {
// Generate the output node graph
void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
pcOut->mRootNode = new aiNode();
if (mRootNode->mChildren.empty()) {
if (0 == mRootNode->mChildren.size()) {
//////////////////////////////////////////////////////////////////////////////
// It seems the file is so messed up that it has not even a hierarchy.
// generate a flat hiearachy which looks like this:
@@ -716,7 +713,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Build dummy nodes for all cameras
for (unsigned int i = 0; i < (unsigned int)mScene->mCameras.size(); ++i, ++a) {
auto *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
aiNode *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
pcNode->mParent = pcOut->mRootNode;
// Build a name for the node
@@ -725,7 +722,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Build dummy nodes for all lights
for (unsigned int i = 0; i < (unsigned int)mScene->mLights.size(); ++i, ++a) {
auto *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
aiNode *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
pcNode->mParent = pcOut->mRootNode;
// Build a name for the node
@@ -741,7 +738,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Allocate a primary animation channel
pcOut->mNumAnimations = 1;
pcOut->mAnimations = new aiAnimation *[1];
auto *anim = pcOut->mAnimations[0] = new aiAnimation();
aiAnimation *anim = pcOut->mAnimations[0] = new aiAnimation();
anim->mName.Set("3DSMasterAnim");
@@ -784,7 +781,7 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
// ... and convert the 3DS materials to aiMaterial's
for (unsigned int i = 0; i < pcOut->mNumMaterials; ++i) {
auto *pcNew = new aiMaterial();
aiMaterial *pcNew = new aiMaterial();
ConvertMaterial(mScene->mMaterials[i], *pcNew);
pcOut->mMaterials[i] = pcNew;
}
+18 -15
View File
@@ -76,26 +76,26 @@ class ChunkWriter {
public:
ChunkWriter(StreamWriterLE &writer, uint16_t chunk_type) :
mWriter(writer) {
mChunkStartPos = writer.GetCurrentPos();
writer(writer) {
chunk_start_pos = writer.GetCurrentPos();
writer.PutU2(chunk_type);
writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET);
}
~ChunkWriter() {
std::size_t head_pos = mWriter.GetCurrentPos();
std::size_t head_pos = writer.GetCurrentPos();
ai_assert(head_pos > mChunkStartPos);
const std::size_t chunk_size = head_pos - mChunkStartPos;
ai_assert(head_pos > chunk_start_pos);
const std::size_t chunk_size = head_pos - chunk_start_pos;
mWriter.SetCurrentPos(mChunkStartPos + SIZE_OFFSET);
mWriter.PutU4(static_cast<uint32_t>(chunk_size));
mWriter.SetCurrentPos(head_pos);
writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
writer.PutU4(static_cast<uint32_t>(chunk_size));
writer.SetCurrentPos(head_pos);
}
private:
StreamWriterLE &mWriter;
std::size_t mChunkStartPos;
StreamWriterLE &writer;
std::size_t chunk_start_pos;
};
// Return an unique name for a given |mesh| attached to |node| that
@@ -122,7 +122,8 @@ std::string GetMaterialName(const aiMaterial &mat, unsigned int index) {
char postfix[10] = { 0 };
ASSIMP_itoa10(postfix, index);
if (aiString mat_name; AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
aiString mat_name;
if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
return mat_name.C_Str() + underscore + postfix;
}
@@ -302,7 +303,8 @@ void Discreet3DSExporter::WriteMaterials() {
WriteColor(color);
}
if (aiShadingMode shading_mode = aiShadingMode_Flat; mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
aiShadingMode shading_mode = aiShadingMode_Flat;
if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
Discreet3DS::shadetype3ds shading_mode_out;
@@ -330,7 +332,7 @@ void Discreet3DSExporter::WriteMaterials() {
default:
shading_mode_out = Discreet3DS::Flat;
ai_assert(false);
}
};
writer.PutU2(static_cast<uint16_t>(shading_mode_out));
}
@@ -344,7 +346,8 @@ void Discreet3DSExporter::WriteMaterials() {
WritePercentChunk(f);
}
if (int twosided; mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
int twosided;
if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
writer.PutI2(1);
}
@@ -538,7 +541,7 @@ void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh &mesh) {
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteString(const std::string &s) {
for (auto it = s.begin(); it != s.end(); ++it) {
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
writer.PutI1(*it);
}
writer.PutI1('\0');
+4 -2
View File
@@ -54,7 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/qnan.h>
#include <cstdio> //sprintf
namespace Assimp::D3DS {
namespace Assimp {
namespace D3DS {
#include <assimp/Compiler/pushpack1.h>
@@ -578,6 +579,7 @@ struct Scene {
// Node* pcRootNode;
};
} // end of namespace Assimp::D3DS
} // end of namespace D3DS
} // end of namespace Assimp
#endif // AI_XFILEHELPER_H_INC
+178 -177
View File
@@ -56,8 +56,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
using namespace D3DS;
static constexpr aiImporterDesc desc = {
"Discreet 3DS Importer",
"",
@@ -77,7 +75,7 @@ static constexpr aiImporterDesc desc = {
// - computes its length
#define ASSIMP_3DS_BEGIN_CHUNK() \
while (true) { \
if (mStream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)) { \
if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)) { \
return; \
} \
Discreet3DS::Chunk chunk; \
@@ -85,23 +83,23 @@ static constexpr aiImporterDesc desc = {
int chunkSize = chunk.Size - sizeof(Discreet3DS::Chunk); \
if (chunkSize <= 0) \
continue; \
const unsigned int oldReadLimit = mStream->SetReadLimit( \
mStream->GetCurrentPos() + chunkSize);
const unsigned int oldReadLimit = stream->SetReadLimit( \
stream->GetCurrentPos() + chunkSize);
// ------------------------------------------------------------------------------------------------
// End a parsing block
// Must follow at the end of each parsing block, reset chunk end marker to previous value
#define ASSIMP_3DS_END_CHUNK() \
mStream->SkipToReadLimit(); \
mStream->SetReadLimit(oldReadLimit); \
if (mStream->GetRemainingSizeToLimit() == 0) \
stream->SkipToReadLimit(); \
stream->SetReadLimit(oldReadLimit); \
if (stream->GetRemainingSizeToLimit() == 0) \
return; \
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
Discreet3DSImporter::Discreet3DSImporter() :
mStream(nullptr), mLastNodeIndex(), mCurrentNode(), mRootNode(), mScene(), mMasterScale(), bHasBG(), bIsPrj() {
stream(), mLastNodeIndex(), mCurrentNode(), mRootNode(), mScene(), mMasterScale(), bHasBG(), bIsPrj() {
// empty
}
@@ -126,7 +124,9 @@ void Discreet3DSImporter::SetupProperties(const Importer * /*pImp*/) {
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void Discreet3DSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
void Discreet3DSImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) {
auto theFile = pIOHandler->Open(pFile, "rb");
if (!theFile) {
throw DeadlyImportError("3DS: Could not open ", pFile);
@@ -138,14 +138,14 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile, aiScene *pSce
if (theStream.GetRemainingSize() < 16) {
throw DeadlyImportError("3DS file is either empty or corrupt: ", pFile);
}
mStream = &theStream;
this->stream = &theStream;
// Allocate our temporary 3DS representation
Scene _scene;
D3DS::Scene _scene;
mScene = &_scene;
// Initialize members
Node _rootNode("UNNAMED");
D3DS::Node _rootNode("UNNAMED");
mLastNodeIndex = -1;
mCurrentNode = &_rootNode;
mRootNode = mCurrentNode;
@@ -166,12 +166,12 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile, aiScene *pSce
// vectors from the smoothing groups we read from the
// file.
for (auto &mesh : mScene->mMeshes) {
if (!mesh.mFaces.empty() && mesh.mPositions.empty()) {
if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) {
throw DeadlyImportError("3DS file contains faces but no vertices: ", pFile);
}
CheckIndices(mesh);
MakeUnique(mesh);
ComputeNormalsWithSmoothingsGroups<Face>(mesh);
ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh);
}
// Replace all occurrences of the default material with a
@@ -196,12 +196,12 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile, aiScene *pSce
AI_DEBUG_INVALIDATE_PTR(mRootNode);
AI_DEBUG_INVALIDATE_PTR(mScene);
AI_DEBUG_INVALIDATE_PTR(mStream);
AI_DEBUG_INVALIDATE_PTR(this->stream);
}
// ------------------------------------------------------------------------------------------------
// Applies a master-scaling factor to the imported scene
void Discreet3DSImporter::ApplyMasterScale(const aiScene *pScene) {
void Discreet3DSImporter::ApplyMasterScale(aiScene *pScene) {
// There are some 3DS files with a zero scaling factor
if (!mMasterScale)
mMasterScale = 1.0f;
@@ -223,14 +223,14 @@ void Discreet3DSImporter::ApplyMasterScale(const aiScene *pScene) {
void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk *pcOut) {
ai_assert(pcOut != nullptr);
pcOut->Flag = mStream->GetI2();
pcOut->Size = mStream->GetI4();
pcOut->Flag = stream->GetI2();
pcOut->Size = stream->GetI4();
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > mStream->GetRemainingSize()) {
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize()) {
throw DeadlyImportError("Chunk is too large");
}
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > mStream->GetRemainingSizeToLimit()) {
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) {
ASSIMP_LOG_ERROR("3DS: Chunk overflow");
}
}
@@ -241,7 +241,8 @@ void Discreet3DSImporter::SkipChunk() {
Discreet3DS::Chunk psChunk;
ReadChunk(&psChunk);
mStream->IncPtr(psChunk.Size - sizeof(Discreet3DS::Chunk));
stream->IncPtr(psChunk.Size - sizeof(Discreet3DS::Chunk));
return;
}
// ------------------------------------------------------------------------------------------------
@@ -258,7 +259,7 @@ void Discreet3DSImporter::ParseMainChunk() {
case Discreet3DS::CHUNK_MAIN:
ParseEditorChunk();
break;
}
};
ASSIMP_3DS_END_CHUNK();
#if defined(__clang__)
@@ -274,29 +275,30 @@ void Discreet3DSImporter::ParseMainChunk() {
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseEditorChunk() {
ASSIMP_3DS_BEGIN_CHUNK()
ASSIMP_3DS_BEGIN_CHUNK();
// get chunk type
switch (chunk.Flag) {
case Discreet3DS::CHUNK_OBJMESH:
ParseObjectChunk();
break;
case Discreet3DS::CHUNK_OBJMESH:
// NOTE: In several documentations in the internet this
// chunk appears at different locations
case Discreet3DS::CHUNK_KEYFRAMER:
ParseKeyframeChunk();
break;
case Discreet3DS::CHUNK_VERSION: {
// print the version number
char buff[10];
ASSIMP_itoa10(buff, mStream->GetI2());
ASSIMP_LOG_INFO("3DS file format version: ", buff);
}
ParseObjectChunk();
break;
// NOTE: In several documentations in the internet this
// chunk appears at different locations
case Discreet3DS::CHUNK_KEYFRAMER:
ParseKeyframeChunk();
break;
case Discreet3DS::CHUNK_VERSION: {
// print the version number
char buff[10];
ASSIMP_itoa10(buff, stream->GetI2());
ASSIMP_LOG_INFO("3DS file format version: ", buff);
} break;
};
ASSIMP_3DS_END_CHUNK()
ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
@@ -307,10 +309,10 @@ void Discreet3DSImporter::ParseObjectChunk() {
switch (chunk.Flag) {
case Discreet3DS::CHUNK_OBJBLOCK: {
unsigned int cnt = 0;
const auto *sz = (const char *)mStream->GetPtr();
const char *sz = (const char *)stream->GetPtr();
// Get the name of the geometry object
while (mStream->GetI1())
while (stream->GetI1())
++cnt;
ParseChunk(sz, cnt);
} break;
@@ -338,8 +340,8 @@ void Discreet3DSImporter::ParseObjectChunk() {
// Specifies the background image. The string should already be
// properly 0 terminated but we need to be sure
unsigned int cnt = 0;
auto *sz = (const char *)mStream->GetPtr();
while (mStream->GetI1())
const char *sz = (const char *)stream->GetPtr();
while (stream->GetI1())
++cnt;
mBackgroundImage = std::string(sz, cnt);
} break;
@@ -350,7 +352,7 @@ void Discreet3DSImporter::ParseObjectChunk() {
case Discreet3DS::CHUNK_MASTER_SCALE:
// Scene master scaling factor
mMasterScale = mStream->GetF4();
mMasterScale = stream->GetF4();
break;
};
ASSIMP_3DS_END_CHUNK();
@@ -377,15 +379,15 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
case Discreet3DS::CHUNK_LIGHT: {
// This starts a new light
auto *light = new aiLight();
aiLight *light = new aiLight();
mScene->mLights.push_back(light);
light->mName.Set(std::string(name, num));
// First read the position of the light
light->mPosition.x = mStream->GetF4();
light->mPosition.y = mStream->GetF4();
light->mPosition.z = mStream->GetF4();
light->mPosition.x = stream->GetF4();
light->mPosition.y = stream->GetF4();
light->mPosition.z = stream->GetF4();
light->mColorDiffuse = aiColor3D(1.f, 1.f, 1.f);
@@ -406,19 +408,19 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
case Discreet3DS::CHUNK_CAMERA: {
// This starts a new camera
auto *camera = new aiCamera();
aiCamera *camera = new aiCamera();
mScene->mCameras.push_back(camera);
camera->mName.Set(std::string(name, num));
// First read the position of the camera
camera->mPosition.x = mStream->GetF4();
camera->mPosition.y = mStream->GetF4();
camera->mPosition.z = mStream->GetF4();
camera->mPosition.x = stream->GetF4();
camera->mPosition.y = stream->GetF4();
camera->mPosition.z = stream->GetF4();
// Then the camera target
camera->mLookAt.x = mStream->GetF4() - camera->mPosition.x;
camera->mLookAt.y = mStream->GetF4() - camera->mPosition.y;
camera->mLookAt.z = mStream->GetF4() - camera->mPosition.z;
camera->mLookAt.x = stream->GetF4() - camera->mPosition.x;
camera->mLookAt.y = stream->GetF4() - camera->mPosition.y;
camera->mLookAt.z = stream->GetF4() - camera->mPosition.z;
ai_real len = camera->mLookAt.Length();
if (len < 1e-5) {
@@ -430,12 +432,12 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
camera->mLookAt /= len;
// And finally - the camera rotation angle, in counter clockwise direction
const ai_real angle = AI_DEG_TO_RAD(mStream->GetF4());
const ai_real angle = AI_DEG_TO_RAD(stream->GetF4());
aiQuaternion quat(camera->mLookAt, angle);
camera->mUp = quat.GetMatrix() * aiVector3D(0.0, 1.0, 0.0);
// Read the lense angle
camera->mHorizontalFOV = AI_DEG_TO_RAD(mStream->GetF4());
camera->mHorizontalFOV = AI_DEG_TO_RAD(stream->GetF4());
if (camera->mHorizontalFOV < 0.001f) {
camera->mHorizontalFOV = float(AI_DEG_TO_RAD(45.f));
}
@@ -461,34 +463,34 @@ void Discreet3DSImporter::ParseLightChunk() {
light->mType = aiLightSource_SPOT;
// We wouldn't need to normalize here, but we do it
light->mDirection.x = mStream->GetF4() - light->mPosition.x;
light->mDirection.y = mStream->GetF4() - light->mPosition.y;
light->mDirection.z = mStream->GetF4() - light->mPosition.z;
light->mDirection.x = stream->GetF4() - light->mPosition.x;
light->mDirection.y = stream->GetF4() - light->mPosition.y;
light->mDirection.z = stream->GetF4() - light->mPosition.z;
light->mDirection.Normalize();
// Now the hotspot and falloff angles - in degrees
light->mAngleInnerCone = AI_DEG_TO_RAD(mStream->GetF4());
light->mAngleInnerCone = AI_DEG_TO_RAD(stream->GetF4());
// FIX: the falloff angle is just an offset
light->mAngleOuterCone = light->mAngleInnerCone + AI_DEG_TO_RAD(mStream->GetF4());
light->mAngleOuterCone = light->mAngleInnerCone + AI_DEG_TO_RAD(stream->GetF4());
break;
// intensity multiplier
case Discreet3DS::CHUNK_DL_MULTIPLIER:
light->mColorDiffuse = light->mColorDiffuse * mStream->GetF4();
light->mColorDiffuse = light->mColorDiffuse * stream->GetF4();
break;
// light color
case Discreet3DS::CHUNK_RGBF:
case Discreet3DS::CHUNK_LINRGBF:
light->mColorDiffuse.r *= mStream->GetF4();
light->mColorDiffuse.g *= mStream->GetF4();
light->mColorDiffuse.b *= mStream->GetF4();
light->mColorDiffuse.r *= stream->GetF4();
light->mColorDiffuse.g *= stream->GetF4();
light->mColorDiffuse.b *= stream->GetF4();
break;
// light attenuation
case Discreet3DS::CHUNK_DL_ATTENUATE:
light->mAttenuationLinear = mStream->GetF4();
light->mAttenuationLinear = stream->GetF4();
break;
};
@@ -503,10 +505,10 @@ void Discreet3DSImporter::ParseCameraChunk() {
// get chunk type
switch (chunk.Flag) {
// near and far clip plane
case Discreet3DS::CHUNK_CAM_RANGES:
camera->mClipPlaneNear = mStream->GetF4();
camera->mClipPlaneFar = mStream->GetF4();
break;
case Discreet3DS::CHUNK_CAM_RANGES:
camera->mClipPlaneNear = stream->GetF4();
camera->mClipPlaneFar = stream->GetF4();
break;
}
ASSIMP_3DS_END_CHUNK();
@@ -553,13 +555,14 @@ void Discreet3DSImporter::InverseNodeSearch(D3DS::Node *pcNode, D3DS::Node *pcCu
// ------------------------------------------------------------------------------------------------
// Find a node with a specific name in the import hierarchy
Node *FindNode(Node *root, const std::string &name) {
D3DS::Node *FindNode(D3DS::Node *root, const std::string &name) {
if (root->mName == name) {
return root;
}
for (auto it = root->mChildren.begin(); it != root->mChildren.end(); ++it) {
if (auto *nd = FindNode(*it, name); nullptr != nd) {
for (std::vector<D3DS::Node *>::iterator it = root->mChildren.begin(); it != root->mChildren.end(); ++it) {
D3DS::Node *nd = FindNode(*it, name);
if (nullptr != nd) {
return nd;
}
}
@@ -577,7 +580,7 @@ bool KeyUniqueCompare(const T &first, const T &second) {
// ------------------------------------------------------------------------------------------------
// Skip some additional import data.
void Discreet3DSImporter::SkipTCBInfo() {
unsigned int flags = mStream->GetI2();
unsigned int flags = stream->GetI2();
if (!flags) {
// Currently we can't do anything with these values. They occur
@@ -588,19 +591,19 @@ void Discreet3DSImporter::SkipTCBInfo() {
}
if (flags & Discreet3DS::KEY_USE_TENS) {
mStream->IncPtr(4);
stream->IncPtr(4);
}
if (flags & Discreet3DS::KEY_USE_BIAS) {
mStream->IncPtr(4);
stream->IncPtr(4);
}
if (flags & Discreet3DS::KEY_USE_CONT) {
mStream->IncPtr(4);
stream->IncPtr(4);
}
if (flags & Discreet3DS::KEY_USE_EASE_FROM) {
mStream->IncPtr(4);
stream->IncPtr(4);
}
if (flags & Discreet3DS::KEY_USE_EASE_TO) {
mStream->IncPtr(4);
stream->IncPtr(4);
}
}
@@ -619,15 +622,15 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// First of all: get the name of the object
unsigned int cnt = 0;
auto *sz = (const char *)mStream->GetPtr();
const char *sz = (const char *)stream->GetPtr();
while (mStream->GetI1())
while (stream->GetI1())
++cnt;
std::string name = std::string(sz, cnt);
// Now find out whether we have this node already (target animation channels
// are stored with a separate object ID)
Node *pcNode = FindNode(mRootNode, name);
D3DS::Node *pcNode = FindNode(mRootNode, name);
int instanceNumber = 1;
if (pcNode) {
@@ -643,10 +646,10 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
pcNode->mInstanceNumber = instanceNumber;
// There are two unknown values which we can safely ignore
mStream->IncPtr(4);
stream->IncPtr(4);
// Now read the hierarchy position of the object
uint16_t hierarchy = mStream->GetI2() + 1;
uint16_t hierarchy = stream->GetI2() + 1;
pcNode->mHierarchyPos = hierarchy;
pcNode->mHierarchyIndex = mLastNodeIndex;
@@ -675,8 +678,8 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// This is the "real" name of a $$$DUMMY object
{
const char *sz = (const char *)mStream->GetPtr();
while (mStream->GetI1())
const char *sz = (const char *)stream->GetPtr();
while (stream->GetI1())
;
// If object name is DUMMY, take this one instead
@@ -695,16 +698,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
}
// Pivot = origin of rotation and scaling
mCurrentNode->vPivot.x = mStream->GetF4();
mCurrentNode->vPivot.y = mStream->GetF4();
mCurrentNode->vPivot.z = mStream->GetF4();
mCurrentNode->vPivot.x = stream->GetF4();
mCurrentNode->vPivot.y = stream->GetF4();
mCurrentNode->vPivot.z = stream->GetF4();
break;
// ////////////////////////////////////////////////////////////////////
// POSITION KEYFRAME
case Discreet3DS::CHUNK_TRACKPOS: {
mStream->IncPtr(10);
const unsigned int numFrames = mStream->GetI4();
stream->IncPtr(10);
const unsigned int numFrames = stream->GetI4();
bool sortKeys = false;
// This could also be meant as the target position for
@@ -717,16 +720,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = mStream->GetI4();
const unsigned int fidx = stream->GetI4();
// Setup a new position key
aiVectorKey v;
v.mTime = (double)fidx;
SkipTCBInfo();
v.mValue.x = mStream->GetF4();
v.mValue.y = mStream->GetF4();
v.mValue.z = mStream->GetF4();
v.mValue.x = stream->GetF4();
v.mValue.y = stream->GetF4();
v.mValue.z = stream->GetF4();
// check whether we'll need to sort the keys
if (!l->empty() && v.mTime <= l->back().mTime)
@@ -756,11 +759,11 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
bool sortKeys = false;
std::vector<aiFloatKey> *l = &mCurrentNode->aCameraRollKeys;
mStream->IncPtr(10);
const unsigned int numFrames = mStream->GetI4();
stream->IncPtr(10);
const unsigned int numFrames = stream->GetI4();
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = mStream->GetI4();
const unsigned int fidx = stream->GetI4();
// Setup a new position key
aiFloatKey v;
@@ -768,7 +771,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// This is just a single float
SkipTCBInfo();
v.mValue = mStream->GetF4();
v.mValue = stream->GetF4();
// Check whether we'll need to sort the keys
if (!l->empty() && v.mTime <= l->back().mTime)
@@ -795,26 +798,26 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// ////////////////////////////////////////////////////////////////////
// ROTATION KEYFRAME
case Discreet3DS::CHUNK_TRACKROTATE: {
mStream->IncPtr(10);
const unsigned int numFrames = mStream->GetI4();
stream->IncPtr(10);
const unsigned int numFrames = stream->GetI4();
bool sortKeys = false;
std::vector<aiQuatKey> *l = &mCurrentNode->aRotationKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = mStream->GetI4();
const unsigned int fidx = stream->GetI4();
SkipTCBInfo();
aiQuatKey v;
v.mTime = (double)fidx;
// The rotation keyframe is given as an axis-angle pair
const float rad = mStream->GetF4();
const float rad = stream->GetF4();
aiVector3D axis;
axis.x = mStream->GetF4();
axis.y = mStream->GetF4();
axis.z = mStream->GetF4();
axis.x = stream->GetF4();
axis.y = stream->GetF4();
axis.z = stream->GetF4();
if (!axis.x && !axis.y && !axis.z)
axis.y = 1.f;
@@ -839,16 +842,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
// ////////////////////////////////////////////////////////////////////
// SCALING KEYFRAME
case Discreet3DS::CHUNK_TRACKSCALE: {
mStream->IncPtr(10);
const unsigned int numFrames = mStream->GetI2();
mStream->IncPtr(2);
stream->IncPtr(10);
const unsigned int numFrames = stream->GetI2();
stream->IncPtr(2);
bool sortKeys = false;
std::vector<aiVectorKey> *l = &mCurrentNode->aScalingKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames; ++i) {
const unsigned int fidx = mStream->GetI4();
const unsigned int fidx = stream->GetI4();
SkipTCBInfo();
// Setup a new key
@@ -856,9 +859,9 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) {
v.mTime = (double)fidx;
// ... and read its value
v.mValue.x = mStream->GetF4();
v.mValue.y = mStream->GetF4();
v.mValue.z = mStream->GetF4();
v.mValue.x = stream->GetF4();
v.mValue.y = stream->GetF4();
v.mValue.z = stream->GetF4();
// check whether we'll need to sort the keys
if (!l->empty() && v.mTime <= l->back().mTime)
@@ -899,23 +902,23 @@ void Discreet3DSImporter::ParseFaceChunk() {
if (num > mMesh.mFaces.size()) {
throw DeadlyImportError("3DS: More smoothing groups than faces");
}
for (auto i = mMesh.mFaces.begin(); m != num; ++i, ++m) {
for (std::vector<D3DS::Face>::iterator i = mMesh.mFaces.begin(); m != num; ++i, ++m) {
// nth bit is set for nth smoothing group
i->iSmoothGroup = mStream->GetI4();
(*i).iSmoothGroup = stream->GetI4();
}
} break;
case Discreet3DS::CHUNK_FACEMAT: {
// at fist an asciiz with the material name
const char *sz = (const char *)mStream->GetPtr();
while (mStream->GetI1())
const char *sz = (const char *)stream->GetPtr();
while (stream->GetI1())
;
// find the index of the material
unsigned int idx = 0xcdcdcdcd, cnt = 0;
for (auto i = mScene->mMaterials.begin(); i != mScene->mMaterials.end(); ++i, ++cnt) {
for (std::vector<D3DS::Material>::const_iterator i = mScene->mMaterials.begin(); i != mScene->mMaterials.end(); ++i, ++cnt) {
// use case independent comparisons. hopefully it will work.
if (i->mName.length() && !ASSIMP_stricmp(sz, i->mName.c_str())) {
if ((*i).mName.length() && !ASSIMP_stricmp(sz, (*i).mName.c_str())) {
idx = cnt;
break;
}
@@ -925,9 +928,9 @@ void Discreet3DSImporter::ParseFaceChunk() {
}
// Now continue and read all material indices
cnt = (uint16_t)mStream->GetI2();
cnt = (uint16_t)stream->GetI2();
for (unsigned int i = 0; i < cnt; ++i) {
unsigned int fidx = (uint16_t)mStream->GetI2();
unsigned int fidx = (uint16_t)stream->GetI2();
// check range
if (fidx >= mMesh.mFaceMaterials.size()) {
@@ -952,59 +955,59 @@ void Discreet3DSImporter::ParseMeshChunk() {
switch (chunk.Flag) {
case Discreet3DS::CHUNK_VERTLIST: {
// This is the list of all vertices in the current mesh
int num = (int)(uint16_t)mStream->GetI2();
int num = (int)(uint16_t)stream->GetI2();
mMesh.mPositions.reserve(num);
while (num-- > 0) {
aiVector3D v;
v.x = mStream->GetF4();
v.y = mStream->GetF4();
v.z = mStream->GetF4();
v.x = stream->GetF4();
v.y = stream->GetF4();
v.z = stream->GetF4();
mMesh.mPositions.push_back(v);
}
} break;
case Discreet3DS::CHUNK_TRMATRIX: {
// This is the RLEATIVE transformation matrix of the current mesh. Vertices are
// pretransformed by this matrix wonder.
mMesh.mMat.a1 = mStream->GetF4();
mMesh.mMat.b1 = mStream->GetF4();
mMesh.mMat.c1 = mStream->GetF4();
mMesh.mMat.a2 = mStream->GetF4();
mMesh.mMat.b2 = mStream->GetF4();
mMesh.mMat.c2 = mStream->GetF4();
mMesh.mMat.a3 = mStream->GetF4();
mMesh.mMat.b3 = mStream->GetF4();
mMesh.mMat.c3 = mStream->GetF4();
mMesh.mMat.a4 = mStream->GetF4();
mMesh.mMat.b4 = mStream->GetF4();
mMesh.mMat.c4 = mStream->GetF4();
mMesh.mMat.a1 = stream->GetF4();
mMesh.mMat.b1 = stream->GetF4();
mMesh.mMat.c1 = stream->GetF4();
mMesh.mMat.a2 = stream->GetF4();
mMesh.mMat.b2 = stream->GetF4();
mMesh.mMat.c2 = stream->GetF4();
mMesh.mMat.a3 = stream->GetF4();
mMesh.mMat.b3 = stream->GetF4();
mMesh.mMat.c3 = stream->GetF4();
mMesh.mMat.a4 = stream->GetF4();
mMesh.mMat.b4 = stream->GetF4();
mMesh.mMat.c4 = stream->GetF4();
} break;
case Discreet3DS::CHUNK_MAPLIST: {
// This is the list of all UV coords in the current mesh
int num = (int)(uint16_t)mStream->GetI2();
int num = (int)(uint16_t)stream->GetI2();
mMesh.mTexCoords.reserve(num);
while (num-- > 0) {
aiVector3D v;
v.x = mStream->GetF4();
v.y = mStream->GetF4();
v.x = stream->GetF4();
v.y = stream->GetF4();
mMesh.mTexCoords.push_back(v);
}
} break;
case Discreet3DS::CHUNK_FACELIST: {
// This is the list of all faces in the current mesh
int num = (int)(uint16_t)mStream->GetI2();
int num = (int)(uint16_t)stream->GetI2();
mMesh.mFaces.reserve(num);
while (num-- > 0) {
// 3DS faces are ALWAYS triangles
mMesh.mFaces.emplace_back();
Face &sFace = mMesh.mFaces.back();
D3DS::Face &sFace = mMesh.mFaces.back();
sFace.mIndices[0] = (uint16_t)mStream->GetI2();
sFace.mIndices[1] = (uint16_t)mStream->GetI2();
sFace.mIndices[2] = (uint16_t)mStream->GetI2();
sFace.mIndices[0] = (uint16_t)stream->GetI2();
sFace.mIndices[1] = (uint16_t)stream->GetI2();
sFace.mIndices[2] = (uint16_t)stream->GetI2();
mStream->IncPtr(2); // skip edge visibility flag
stream->IncPtr(2); // skip edge visibility flag
}
// Resize the material array (0xcdcdcdcd marks the default material; so if a face is
@@ -1012,7 +1015,7 @@ void Discreet3DSImporter::ParseMeshChunk() {
mMesh.mFaceMaterials.resize(mMesh.mFaces.size(), 0xcdcdcdcd);
// Larger 3DS files could have multiple FACE chunks here
chunkSize = (int)mStream->GetRemainingSizeToLimit();
chunkSize = (int)stream->GetRemainingSizeToLimit();
if (chunkSize > (int)sizeof(Discreet3DS::Chunk))
ParseFaceChunk();
} break;
@@ -1029,9 +1032,9 @@ void Discreet3DSImporter::ParseMaterialChunk() {
{
// The material name string is already zero-terminated, but we need to be sure ...
const char *sz = (const char *)mStream->GetPtr();
const char *sz = (const char *)stream->GetPtr();
unsigned int cnt = 0;
while (mStream->GetI1())
while (stream->GetI1())
++cnt;
if (!cnt) {
@@ -1099,7 +1102,7 @@ void Discreet3DSImporter::ParseMaterialChunk() {
case Discreet3DS::CHUNK_MAT_SHADING:
// This is the material shading mode
mScene->mMaterials.back().mShading = (Discreet3DS::shadetype3ds)mStream->GetI2();
mScene->mMaterials.back().mShading = (D3DS::Discreet3DS::shadetype3ds)stream->GetI2();
break;
case Discreet3DS::CHUNK_MAT_TWO_SIDE:
@@ -1175,31 +1178,31 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) {
switch (chunk.Flag) {
case Discreet3DS::CHUNK_MAPFILE: {
// The material name string is already zero-terminated, but we need to be sure ...
const char *sz = (const char *)mStream->GetPtr();
const char *sz = (const char *)stream->GetPtr();
unsigned int cnt = 0;
while (mStream->GetI1())
while (stream->GetI1())
++cnt;
pcOut->mMapName = std::string(sz, cnt);
} break;
case Discreet3DS::CHUNK_PERCENTD:
// Manually parse the blend factor
pcOut->mTextureBlend = ai_real(mStream->GetF8());
pcOut->mTextureBlend = ai_real(stream->GetF8());
break;
case Discreet3DS::CHUNK_PERCENTF:
// Manually parse the blend factor
pcOut->mTextureBlend = mStream->GetF4();
pcOut->mTextureBlend = stream->GetF4();
break;
case Discreet3DS::CHUNK_PERCENTW:
// Manually parse the blend factor
pcOut->mTextureBlend = (ai_real)((uint16_t) mStream->GetI2()) / ai_real(100.0);
pcOut->mTextureBlend = (ai_real)((uint16_t)stream->GetI2()) / ai_real(100.0);
break;
case Discreet3DS::CHUNK_MAT_MAP_USCALE:
// Texture coordinate scaling in the U direction
pcOut->mScaleU = mStream->GetF4();
pcOut->mScaleU = stream->GetF4();
if (0.0f == pcOut->mScaleU) {
ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1.");
pcOut->mScaleU = 1.0f;
@@ -1207,7 +1210,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) {
break;
case Discreet3DS::CHUNK_MAT_MAP_VSCALE:
// Texture coordinate scaling in the V direction
pcOut->mScaleV = mStream->GetF4();
pcOut->mScaleV = stream->GetF4();
if (0.0f == pcOut->mScaleV) {
ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1.");
pcOut->mScaleV = 1.0f;
@@ -1216,21 +1219,21 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) {
case Discreet3DS::CHUNK_MAT_MAP_UOFFSET:
// Texture coordinate offset in the U direction
pcOut->mOffsetU = -mStream->GetF4();
pcOut->mOffsetU = -stream->GetF4();
break;
case Discreet3DS::CHUNK_MAT_MAP_VOFFSET:
// Texture coordinate offset in the V direction
pcOut->mOffsetV = mStream->GetF4();
pcOut->mOffsetV = stream->GetF4();
break;
case Discreet3DS::CHUNK_MAT_MAP_ANG:
// Texture coordinate rotation, CCW in DEGREES
pcOut->mRotation = -AI_DEG_TO_RAD(mStream->GetF4());
pcOut->mRotation = -AI_DEG_TO_RAD(stream->GetF4());
break;
case Discreet3DS::CHUNK_MAT_MAP_TILING: {
const uint16_t iFlags = mStream->GetI2();
const uint16_t iFlags = stream->GetI2();
// Get the mapping mode (for both axes)
if (iFlags & 0x2u)
@@ -1255,11 +1258,9 @@ ai_real Discreet3DSImporter::ParsePercentageChunk() {
ReadChunk(&chunk);
if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) {
return mStream->GetF4() * ai_real(100) / ai_real(0xFFFF);
}
if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) {
return (ai_real)((uint16_t)mStream->GetI2()) / (ai_real)0xFFFF;
return stream->GetF4() * ai_real(100) / ai_real(0xFFFF);
} else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) {
return (ai_real)((uint16_t)stream->GetI2()) / (ai_real)0xFFFF;
}
return get_qnan();
@@ -1290,9 +1291,9 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
*out = clrError;
return;
}
out->r = mStream->GetF4();
out->g = mStream->GetF4();
out->b = mStream->GetF4();
out->r = stream->GetF4();
out->g = stream->GetF4();
out->b = stream->GetF4();
break;
case Discreet3DS::CHUNK_LINRGBB:
@@ -1304,15 +1305,15 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
return;
}
const ai_real invVal = ai_real(1.0) / ai_real(255.0);
out->r = (ai_real)(uint8_t)mStream->GetI1() * invVal;
out->g = (ai_real)(uint8_t)mStream->GetI1() * invVal;
out->b = (ai_real)(uint8_t)mStream->GetI1() * invVal;
out->r = (ai_real)(uint8_t)stream->GetI1() * invVal;
out->g = (ai_real)(uint8_t)stream->GetI1() * invVal;
out->b = (ai_real)(uint8_t)stream->GetI1() * invVal;
} break;
// Percentage chunks are accepted, too.
case Discreet3DS::CHUNK_PERCENTF:
if (acceptPercent && 4 <= diff) {
out->g = out->b = out->r = mStream->GetF4();
out->g = out->b = out->r = stream->GetF4();
break;
}
*out = clrError;
@@ -1320,14 +1321,14 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
case Discreet3DS::CHUNK_PERCENTW:
if (acceptPercent && 1 <= diff) {
out->g = out->b = out->r = (ai_real)(uint8_t)mStream->GetI1() / ai_real(255.0);
out->g = out->b = out->r = (ai_real)(uint8_t)stream->GetI1() / ai_real(255.0);
break;
}
*out = clrError;
return;
default:
mStream->IncPtr(diff);
stream->IncPtr(diff);
// Skip unknown chunks, hope this won't cause any problems.
return ParseColorChunk(out, acceptPercent);
};
+35 -24
View File
@@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h>
#include <assimp/types.h>
#include "3DSHelper.h"
#include <assimp/StreamReader.h>
@@ -56,6 +57,8 @@ struct aiNode;
namespace Assimp {
using namespace D3DS;
// ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files
*/
@@ -96,14 +99,15 @@ protected:
// -------------------------------------------------------------------
/** Converts a temporary material to the outer representation
*/
void ConvertMaterial(D3DS::Material& p_cMat, aiMaterial& p_pcOut);
void ConvertMaterial(D3DS::Material& p_cMat,
aiMaterial& p_pcOut);
// -------------------------------------------------------------------
/** Read a chunk
*
* @param pcOut Receives the current chunk
*/
void ReadChunk(D3DS::Discreet3DS::Chunk* pcOut);
void ReadChunk(Discreet3DS::Chunk* pcOut);
// -------------------------------------------------------------------
/** Parse a percentage chunk. mCurrent will point to the next
@@ -113,10 +117,12 @@ protected:
ai_real ParsePercentageChunk();
// -------------------------------------------------------------------
/** Parse a color chunk. mCurrent will point to the next chunk behind
* afterward. If no color chunk is found QNAN is returned in all members.
*/
void ParseColorChunk(aiColor3D* p_pcOut, bool p_bAcceptPercent = true);
/** Parse a color chunk. mCurrent will point to the next
* chunk behind afterwards. If no color chunk is found
* QNAN is returned in all members.
*/
void ParseColorChunk(aiColor3D* p_pcOut,
bool p_bAcceptPercent = true);
// -------------------------------------------------------------------
/** Skip a chunk in the file
@@ -124,7 +130,7 @@ protected:
void SkipChunk();
// -------------------------------------------------------------------
/** Generate the node-graph
/** Generate the nodegraph
*/
void GenerateNodeGraph(aiScene* pcOut);
@@ -220,19 +226,19 @@ protected:
// -------------------------------------------------------------------
/** Add a node to the node graph
*/
void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, D3DS::Node* pcIn,
void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
aiMatrix4x4& absTrafo);
// -------------------------------------------------------------------
/** Search for a node in the graph.
* Called recursively
*/
void InverseNodeSearch(D3DS::Node* pcNode, D3DS::Node* pcCurrent);
void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent);
// -------------------------------------------------------------------
/** Apply the master scaling factor to the mesh
*/
void ApplyMasterScale(const aiScene* pScene);
void ApplyMasterScale(aiScene* pScene);
// -------------------------------------------------------------------
/** Clamp all indices in the file to a valid range
@@ -244,26 +250,31 @@ protected:
*/
void SkipTCBInfo();
private:
/// Stream to read from
StreamReaderLE* mStream;
/// Last touched node index
protected:
/** Stream to read from */
StreamReaderLE* stream;
/** Last touched node index */
short mLastNodeIndex;
/// Current node
D3DS::Node* mCurrentNode;
/// Root node
D3DS::Node *mRootNode;
/// Scene under construction
/** Current node, root node */
D3DS::Node* mCurrentNode, *mRootNode;
/** Scene under construction */
D3DS::Scene* mScene;
/// Ambient base color of the scene
/** Ambient base color of the scene */
aiColor3D mClrAmbient;
/// Master scaling factor of the scene
/** Master scaling factor of the scene */
ai_real mMasterScale;
/// Path to the background image of the scene
/** Path to the background image of the scene */
std::string mBackgroundImage;
/// true for has a background
bool bHasBG;
/// true if PRJ file
/** true if PRJ file */
bool bIsPrj;
};
+27 -16
View File
@@ -49,7 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiMaterial;
struct aiMesh;
namespace Assimp:: D3MF {
namespace Assimp {
namespace D3MF {
enum class ResourceType {
RT_Object,
@@ -64,7 +65,8 @@ class Resource {
public:
int mId;
explicit Resource(int id) : mId(id) {
Resource(int id) :
mId(id) {
// empty
}
@@ -75,7 +77,7 @@ public:
}
};
class EmbeddedTexture final : public Resource {
class EmbeddedTexture : public Resource {
public:
std::string mPath;
std::string mContentType;
@@ -83,7 +85,12 @@ public:
std::string mTilestyleV;
std::vector<char> mBuffer;
explicit EmbeddedTexture(int id) : Resource(id) {
EmbeddedTexture(int id) :
Resource(id),
mPath(),
mContentType(),
mTilestyleU(),
mTilestyleV() {
// empty
}
@@ -94,12 +101,13 @@ public:
}
};
class Texture2DGroup final : public Resource {
class Texture2DGroup : public Resource {
public:
std::vector<aiVector2D> mTex2dCoords;
int mTexId;
explicit Texture2DGroup(int id) : Resource(id), mTexId(-1) {
Texture2DGroup(int id) :
Resource(id),
mTexId(-1) {
// empty
}
@@ -110,11 +118,11 @@ public:
}
};
class ColorGroup final : public Resource {
class ColorGroup : public Resource {
public:
std::vector<aiColor4D> mColors;
explicit ColorGroup(int id) : Resource(id) {
ColorGroup(int id) :
Resource(id){
// empty
}
@@ -125,11 +133,13 @@ public:
}
};
class BaseMaterials final : public Resource {
class BaseMaterials : public Resource {
public:
std::vector<unsigned int> mMaterialIndex;
explicit BaseMaterials(int id) : Resource(id) {
BaseMaterials(int id) :
Resource(id),
mMaterialIndex() {
// empty
}
@@ -145,14 +155,14 @@ struct Component {
aiMatrix4x4 mTransformation;
};
class Object final : public Resource {
class Object : public Resource {
public:
std::vector<aiMesh *> mMeshes;
MeshArray mMeshes;
std::vector<unsigned int> mMeshIndex;
std::vector<Component> mComponents;
std::string mName;
explicit Object(int id) :
Object(int id) :
Resource(id),
mName(std::string("Object_") + ai_to_string(id)) {
// empty
@@ -165,4 +175,5 @@ public:
}
};
} // namespace Assimp::D3MF
} // namespace D3MF
} // namespace Assimp
+70 -65
View File
@@ -40,80 +40,85 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
namespace Assimp::D3MF::XmlTag {
namespace Assimp {
namespace D3MF {
namespace XmlTag {
// Root tag
constexpr char RootTag[] = "3MF";
const char* const RootTag = "3MF";
// Meta-data
constexpr char meta[] = "metadata";
constexpr char meta_name[] = "name";
const char* const meta = "metadata";
const char* const meta_name = "name";
// Model-data specific tags
constexpr char model[] = "model";
constexpr char model_unit[] = "unit";
constexpr char metadata[] = "metadata";
constexpr char resources[] = "resources";
constexpr char object[] = "object";
constexpr char mesh[] = "mesh";
constexpr char components[] = "components";
constexpr char component[] = "component";
constexpr char vertices[] = "vertices";
constexpr char vertex[] = "vertex";
constexpr char triangles[] = "triangles";
constexpr char triangle[] = "triangle";
constexpr char x[] = "x";
constexpr char y[] = "y";
constexpr char z[] = "z";
constexpr char v1[] = "v1";
constexpr char v2[] = "v2";
constexpr char v3[] = "v3";
constexpr char id[] = "id";
constexpr char pid[] = "pid";
constexpr char pindex[] = "pindex";
constexpr char p1[] = "p1";
constexpr char p2[] = "p2";
constexpr char p3[] = "p3";
constexpr char name[] = "name";
constexpr char type[] = "type";
constexpr char build[] = "build";
constexpr char item[] = "item";
constexpr char objectid[] = "objectid";
constexpr char transform[] = "transform";
constexpr char path[] = "path";
const char* const model = "model";
const char* const model_unit = "unit";
const char* const metadata = "metadata";
const char* const resources = "resources";
const char* const object = "object";
const char* const mesh = "mesh";
const char* const components = "components";
const char* const component = "component";
const char* const vertices = "vertices";
const char* const vertex = "vertex";
const char* const triangles = "triangles";
const char* const triangle = "triangle";
const char* const x = "x";
const char* const y = "y";
const char* const z = "z";
const char* const v1 = "v1";
const char* const v2 = "v2";
const char* const v3 = "v3";
const char* const id = "id";
const char* const pid = "pid";
const char* const pindex = "pindex";
const char* const p1 = "p1";
const char *const p2 = "p2";
const char *const p3 = "p3";
const char* const name = "name";
const char* const type = "type";
const char* const build = "build";
const char* const item = "item";
const char* const objectid = "objectid";
const char* const transform = "transform";
const char *const path = "path";
// Material definitions
constexpr char basematerials[] = "basematerials";
constexpr char basematerials_base[] = "base";
constexpr char basematerials_name[] = "name";
constexpr char basematerials_displaycolor[] = "displaycolor";
constexpr char texture_2d[] = "m:texture2d";
constexpr char texture_group[] = "m:texture2dgroup";
constexpr char texture_content_type[] = "contenttype";
constexpr char texture_tilestyleu[] = "tilestyleu";
constexpr char texture_tilestylev[] = "tilestylev";
constexpr char texture_2d_coord[] = "m:tex2coord";
constexpr char texture_cuurd_u[] = "u";
constexpr char texture_cuurd_v[] = "v";
const char* const basematerials = "basematerials";
const char* const basematerials_base = "base";
const char* const basematerials_name = "name";
const char* const basematerials_displaycolor = "displaycolor";
const char* const texture_2d = "m:texture2d";
const char *const texture_group = "m:texture2dgroup";
const char *const texture_content_type = "contenttype";
const char *const texture_tilestyleu = "tilestyleu";
const char *const texture_tilestylev = "tilestylev";
const char *const texture_2d_coord = "m:tex2coord";
const char *const texture_cuurd_u = "u";
const char *const texture_cuurd_v = "v";
// vertex color definitions
constexpr char colorgroup[] = "m:colorgroup";
constexpr char color_item[] = "m:color";
constexpr char color_value[] = "color";
const char *const colorgroup = "m:colorgroup";
const char *const color_item = "m:color";
const char *const color_vaule = "color";
// Meta info tags
constexpr char CONTENT_TYPES_ARCHIVE[] = "[Content_Types].xml";
constexpr char ROOT_RELATIONSHIPS_ARCHIVE[] = "_rels/.rels";
constexpr char SCHEMA_CONTENTTYPES[] = "http://schemas.openxmlformats.org/package/2006/content-types";
constexpr char SCHEMA_RELATIONSHIPS[] = "http://schemas.openxmlformats.org/package/2006/relationships";
constexpr char RELS_RELATIONSHIP_CONTAINER[] = "Relationships";
constexpr char RELS_RELATIONSHIP_NODE[] = "Relationship";
constexpr char RELS_ATTRIB_TARGET[] = "Target";
constexpr char RELS_ATTRIB_TYPE[] = "Type";
constexpr char RELS_ATTRIB_ID[] = "Id";
constexpr char PACKAGE_START_PART_RELATIONSHIP_TYPE[] = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
constexpr char PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE[] = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
constexpr char PACKAGE_TEXTURE_RELATIONSHIP_TYPE[] = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
constexpr char PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE[] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
constexpr char PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE[] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
const char* const SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
const char* const SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
const char* const RELS_RELATIONSHIP_CONTAINER = "Relationships";
const char* const RELS_RELATIONSHIP_NODE = "Relationship";
const char* const RELS_ATTRIB_TARGET = "Target";
const char* const RELS_ATTRIB_TYPE = "Type";
const char* const RELS_ATTRIB_ID = "Id";
const char* const PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
const char* const PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
}
} // namespace Assimp::D3MF
} // Namespace D3MF
} // Namespace Assimp
+2 -1
View File
@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include "3MFXmlTags.h"
@@ -93,7 +94,7 @@ D3MFExporter::~D3MFExporter() {
mRelations.clear();
}
bool D3MFExporter::validate() const {
bool D3MFExporter::validate() {
if (mArchiveName.empty()) {
return false;
}
+1 -1
View File
@@ -68,7 +68,7 @@ class D3MFExporter {
public:
D3MFExporter( const char* pFile, const aiScene* pScene );
~D3MFExporter();
bool validate() const;
bool validate();
bool exportArchive( const char *file );
bool exportContentTypes();
bool exportRelations();
+1 -1
View File
@@ -53,7 +53,7 @@ namespace Assimp {
///
/// Implements the basic topology import and embedded textures.
// ---------------------------------------------------------------------------
class D3MFImporter final : public BaseImporter {
class D3MFImporter : public BaseImporter {
public:
/// @brief The default class constructor.
D3MFImporter() = default;
+11 -8
View File
@@ -58,16 +58,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map>
#include <vector>
namespace Assimp {
namespace Assimp::D3MF {
namespace D3MF {
// ------------------------------------------------------------------------------------------------
using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
class OpcPackageRelationshipReader final {
class OpcPackageRelationshipReader {
public:
explicit OpcPackageRelationshipReader(XmlParser &parser) : mRelations() {
OpcPackageRelationshipReader(XmlParser &parser) :
mRelations() {
XmlNode root = parser.getRootNode();
ParseRootNode(root);
}
@@ -131,9 +131,11 @@ static bool IsEmbeddedTexture( const std::string &filename ) {
// ------------------------------------------------------------------------------------------------
D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
mRootStream(nullptr),
mZipArchive() {
mZipArchive(nullptr) {
mZipArchive = new ZipArchiveIOSystem(pIOHandler, rFile);
if (!mZipArchive->isOpen()) {
delete mZipArchive;
mZipArchive = nullptr;
throw DeadlyImportError("Failed to open file ", rFile, ".");
}
@@ -183,7 +185,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
}
D3MFOpcPackage::~D3MFOpcPackage() {
mZipArchive->Close(mRootStream);
if (mRootStream && mZipArchive) {
mZipArchive->Close(mRootStream);
}
delete mZipArchive;
}
@@ -249,7 +253,6 @@ void D3MFOpcPackage::LoadEmbeddedTextures(IOStream *fileStream, const std::strin
mEmbeddedTextures.emplace_back(texture);
}
} // Namespace D3MF
} // Namespace Assimp
} // Namespace Assimp::D3MF
#endif //ASSIMP_BUILD_NO_3MF_IMPORTER
+8 -2
View File
@@ -495,13 +495,16 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
}
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
for (unsigned int vertex_index = 0; vertex_index < mesh->mNumVertices; vertex_index++) {
mesh->mTextureCoords[0][vertex_index].z = IdNotSet;//mark not set
mesh->mTextureCoords[0][vertex_index].z = IdNotSet; //mark not set
}
}
auto update_texture = [&](int idx) {
if (pindex[idx] != IdNotSet) {
size_t vertex_index = face.mIndices[idx];
if (vertex_index >= mesh->mNumVertices) {
return;
}
mesh->mTextureCoords[0][vertex_index] =
aiVector3D(group->mTex2dCoords[pindex[idx]].x, group->mTex2dCoords[pindex[idx]].y, 0.0f);
}
@@ -521,6 +524,9 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
auto update_color = [&](int idx) {
if (pindex[idx] != IdNotSet) {
size_t vertex_index = face.mIndices[idx];
if (vertex_index >= mesh->mNumVertices) {
return;
}
mesh->mColors[0][vertex_index] = group->mColors[pindex[idx]];
}
};
@@ -680,7 +686,7 @@ void XmlSerializer::ReadColor(XmlNode &node, ColorGroup *colorGroup) {
for (XmlNode currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == XmlTag::color_item) {
const char *color = currentNode.attribute(XmlTag::color_value).as_string();
const char *color = currentNode.attribute(XmlTag::color_vaule).as_string();
aiColor4D color_value;
if (parseColor(color, color_value)) {
colorGroup->mColors.push_back(color_value);
+1 -2
View File
@@ -59,10 +59,9 @@ class Texture2DGroup;
class EmbeddedTexture;
class ColorGroup;
/// @brief his class implements ther 3mf serialization.
class XmlSerializer final {
public:
explicit XmlSerializer(XmlParser &xmlParser);
XmlSerializer(XmlParser &xmlParser);
~XmlSerializer();
void ImportXml(aiScene *scene);
+3 -3
View File
@@ -418,7 +418,7 @@ void AC3DImporter::ConvertMaterial(const Object &object,
// ------------------------------------------------------------------------------------------------
// Converts the loaded data to the internal verbose representation
aiNode *AC3DImporter::ConvertObjectSection(Object &object,
std::vector<aiMesh *> &meshes,
MeshArray &meshes,
std::vector<aiMaterial *> &outMaterials,
const std::vector<Material> &materials,
aiNode *parent) {
@@ -710,7 +710,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
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);
MeshArray 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);
@@ -846,7 +846,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
}
mNumMeshes += (mNumMeshes >> 2u) + 1;
std::vector<aiMesh *> meshes;
MeshArray meshes;
meshes.reserve(mNumMeshes);
std::vector<aiMaterial *> omaterials;
+2 -2
View File
@@ -60,7 +60,7 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** AC3D (*.ac) importer class
*/
class AC3DImporter final : public BaseImporter {
class AC3DImporter : public BaseImporter {
public:
AC3DImporter();
~AC3DImporter() override = default;
@@ -226,7 +226,7 @@ private:
* @param materials Material list
* @param Scenegraph node for the object */
aiNode *ConvertObjectSection(Object &object,
std::vector<aiMesh *> &meshes,
MeshArray &meshes,
std::vector<aiMaterial *> &outMaterials,
const std::vector<Material> &materials,
aiNode *parent = nullptr);
+2 -1
View File
@@ -327,7 +327,8 @@ void AMFImporter::ParseNode_Root() {
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Constellation(XmlNode &node) {
std::string id = node.attribute("id").as_string();
std::string id;
id = node.attribute("id").as_string();
// create and if needed - define new grouping object.
AMFNodeElementBase *ne = new AMFConstellation(mNodeElement_Cur);
+1 -3
View File
@@ -97,10 +97,8 @@ namespace Assimp {
/// new - <texmap> and children <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>
/// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3>
///
class AMFImporter final : public BaseImporter {
class AMFImporter : public BaseImporter {
using AMFMetaDataArray = std::vector<AMFMetadata *>;
using MeshArray = std::vector<aiMesh *>;
using NodeArray = std::vector<aiNode *>;
public:
struct SPP_Material;
+31 -48
View File
@@ -107,16 +107,16 @@ protected:
}; // class IAMFImporter_NodeElement
/// A collection of objects or constellations with specific relative locations.
struct AMFConstellation final : public AMFNodeElementBase {
struct AMFConstellation : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFConstellation(AMFNodeElementBase *pParent) :
AMFConstellation(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Constellation, pParent) {}
}; // struct CAMFImporter_NodeElement_Constellation
/// Part of constellation.
struct AMFInstance final : public AMFNodeElementBase {
struct AMFInstance : public AMFNodeElementBase {
std::string ObjectID; ///< ID of object for instantiation.
/// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to
@@ -129,7 +129,7 @@ struct AMFInstance final : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFInstance(AMFNodeElementBase *pParent) :
AMFInstance(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Instance, pParent) {}
};
@@ -141,10 +141,8 @@ struct AMFMetadata : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFMetadata(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Metadata, pParent) {
// empty
}
AMFMetadata(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Metadata, pParent) {}
};
/// Structure that define root node.
@@ -155,10 +153,8 @@ struct AMFRoot : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFRoot(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Root, pParent) {
// empty
}
AMFRoot(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Root, pParent) {}
};
/// Structure that define object node.
@@ -170,7 +166,7 @@ struct AMFColor : public AMFNodeElementBase {
/// @brief Constructor.
/// @param [in] pParent - pointer to parent node.
explicit AMFColor(AMFNodeElementBase *pParent) :
AMFColor(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color() {
// empty
}
@@ -178,62 +174,53 @@ struct AMFColor : public AMFNodeElementBase {
/// Structure that define material node.
struct AMFMaterial : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFMaterial(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Material, pParent) {
// empty
}
AMFMaterial(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Material, pParent) {}
};
/// Structure that define object node.
struct AMFObject : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFObject(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Object, pParent) {
// empty
}
AMFObject(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Object, pParent) {}
};
/// \struct CAMFImporter_NodeElement_Mesh
/// Structure that define mesh node.
struct AMFMesh : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFMesh(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Mesh, pParent) {
// empty
}
AMFMesh(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Mesh, pParent) {}
};
/// Structure that define vertex node.
struct AMFVertex : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFVertex(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertex, pParent) {
// empty
}
AMFVertex(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertex, pParent) {}
};
/// Structure that define edge node.
struct AMFEdge : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFEdge(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Edge, pParent) {
// empty
}
AMFEdge(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Edge, pParent) {}
};
/// Structure that define vertices node.
struct AMFVertices : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFVertices(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertices, pParent) {
// empty
}
AMFVertices(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Vertices, pParent) {}
};
/// Structure that define volume node.
@@ -243,10 +230,8 @@ struct AMFVolume : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFVolume(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Volume, pParent) {
// empty
}
AMFVolume(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Volume, pParent) {}
};
/// Structure that define coordinates node.
@@ -255,10 +240,8 @@ struct AMFCoordinates : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFCoordinates(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Coordinates, pParent) {
// empty
}
AMFCoordinates(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Coordinates, pParent) {}
};
/// Structure that define texture coordinates node.
@@ -271,7 +254,7 @@ struct AMFTexMap : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFTexMap(AMFNodeElementBase *pParent) :
AMFTexMap(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{} {
// empty
}
@@ -283,7 +266,7 @@ struct AMFTriangle : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFTriangle(AMFNodeElementBase *pParent) :
AMFTriangle(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Triangle, pParent) {
// empty
}
@@ -297,7 +280,7 @@ struct AMFTexture : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
explicit AMFTexture(AMFNodeElementBase *pParent) :
AMFTexture(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Texture, pParent), Width(0), Height(0), Depth(0), Data(), Tiled(false) {
// empty
}
@@ -57,6 +57,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*pY*/, const float /*pZ*/) const {
aiColor4D tcol;
// Check if stored data are supported.
if (!Composition.empty()) {
throw DeadlyImportError("IME. GetColor for composition");
@@ -66,7 +68,7 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
throw DeadlyImportError("IME. GetColor, composed color");
}
aiColor4D tcol = Color->Color;
tcol = Color->Color;
// Check if default color must be used
if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) {
@@ -530,9 +532,11 @@ void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const st
col_arr.reserve(VertexCount_Max * 2);
{ // fill arrays
size_t vert_idx_from, vert_idx_to;
// first iteration.
size_t vert_idx_to = 0;
size_t vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr);
vert_idx_to = 0;
vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr);
vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from));
col_arr.push_back(Vertex_CalculateColor(vert_idx_from));
if (vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to);
+5 -4
View File
@@ -162,7 +162,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
// process all meshes
bool tookNormals = false;
std::vector<aiMesh *> avOutMeshes;
MeshArray avOutMeshes;
avOutMeshes.reserve(mParser->m_vMeshes.size() * 2);
for (std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin(); i != mParser->m_vMeshes.end(); ++i) {
if ((*i).bSkip) {
@@ -187,7 +187,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
// Now build the output mesh list. Remove dummies
pScene->mNumMeshes = (unsigned int)avOutMeshes.size();
aiMesh **pp = pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
for (std::vector<aiMesh *>::const_iterator i = avOutMeshes.begin(); i != avOutMeshes.end(); ++i) {
for (MeshArray::const_iterator i = avOutMeshes.begin(); i != avOutMeshes.end(); ++i) {
if (!(*i)->mNumFaces) {
continue;
}
@@ -902,7 +902,7 @@ void ASEImporter::ConvertMaterial(ASE::Material &mat) {
// ------------------------------------------------------------------------------------------------
// Build output meshes
void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, std::vector<aiMesh *> &avOutMeshes) {
void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, MeshArray &avOutMeshes) {
// validate the material index of the mesh
if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) {
mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size() - 1;
@@ -1270,4 +1270,5 @@ bool ASEImporter::GenerateNormals(ASE::Mesh &mesh) {
}
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
#endif // ASSIMP_BUILD_NO_ASE_IMPORTER
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
+1 -1
View File
@@ -59,7 +59,7 @@ namespace Assimp {
/** Importer class for the 3DS ASE ASCII format.
*
*/
class ASEImporter final : public BaseImporter {
class ASEImporter : public BaseImporter {
public:
ASEImporter();
~ASEImporter() override = default;
+8 -6
View File
@@ -57,13 +57,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ASE is quite similar to 3ds. We can reuse some structures
#include "AssetLib/3DS/3DSLoader.h"
namespace Assimp::ASE {
namespace Assimp {
namespace ASE {
using namespace D3DS;
// ---------------------------------------------------------------------------
/** Helper structure representing an ASE material */
struct Material final : D3DS::Material {
struct Material : public D3DS::Material {
//! Default constructor has been deleted
Material() = delete;
@@ -114,7 +115,7 @@ struct Material final : D3DS::Material {
return *this;
}
~Material() override = default;
~Material() = default;
//! Contains all sub materials of this material
std::vector<Material> avSubMaterials;
@@ -372,8 +373,8 @@ struct Dummy : public BaseNode {
};
// Parameters to Parser::Parse()
static constexpr unsigned int AI_ASE_NEW_FILE_FORMAT = 200;
static constexpr unsigned int AI_ASE_OLD_FILE_FORMAT = 110;
#define AI_ASE_NEW_FILE_FORMAT 200
#define AI_ASE_OLD_FILE_FORMAT 110
// Internally we're a little bit more tolerant
#define AI_ASE_IS_NEW_FILE_FORMAT() (iFileFormat >= 200)
@@ -667,7 +668,8 @@ public:
unsigned int iFileFormat;
};
} // Namespace Assimp::ASE
} // Namespace ASE
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+23 -23
View File
@@ -239,7 +239,29 @@ inline size_t WriteArray(IOStream *stream, const T *in, unsigned int size) {
* and the chunk contents to the container stream. This allows relatively easy chunk
* chunk construction, even recursively.
*/
class AssbinChunkWriter final : public IOStream {
class AssbinChunkWriter : public IOStream {
private:
uint8_t *buffer;
uint32_t magic;
IOStream *container;
size_t cur_size, cursor, initial;
private:
// -------------------------------------------------------------------
void Grow(size_t need = 0) {
size_t new_size = std::max(initial, std::max(need, cur_size + (cur_size >> 1)));
const uint8_t *const old = buffer;
buffer = new uint8_t[new_size];
if (old) {
memcpy(buffer, old, cur_size);
delete[] old;
}
cur_size = new_size;
}
public:
AssbinChunkWriter(IOStream *container, uint32_t magic, size_t initial = 4096) :
buffer(nullptr),
@@ -293,28 +315,6 @@ public:
return pCount;
}
private:
// -------------------------------------------------------------------
void Grow(size_t need = 0) {
size_t new_size = std::max(initial, std::max(need, cur_size + (cur_size >> 1)));
const uint8_t *const old = buffer;
buffer = new uint8_t[new_size];
if (old) {
memcpy(buffer, old, cur_size);
delete[] old;
}
cur_size = new_size;
}
private:
uint8_t *buffer;
uint32_t magic;
IOStream *container;
size_t cur_size, cursor, initial;
};
// ----------------------------------------------------------------------------------
+4 -7
View File
@@ -77,7 +77,8 @@ static int ioprintf(IOStream *io, const char *format, ...) {
}
static const int Size = 4096;
char sz[Size] = {};
char sz[Size];
::memset(sz, '\0', Size);
va_list va;
va_start(va, format);
const unsigned int nSize = vsnprintf(sz, Size - 1, format, va);
@@ -301,11 +302,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
bool compressed = (tex->mHeight == 0);
// mesh header
std::string texName = "unknown";
if (tex->mFilename.length != 0u) {
texName = tex->mFilename.data;
}
ioprintf(io, "\t<Texture name=\"%s\" width=\"%u\" height=\"%u\" compressed=\"%s\"> \n", texName.c_str(),
ioprintf(io, "\t<Texture width=\"%u\" height=\"%u\" compressed=\"%s\"> \n",
(compressed ? -1 : tex->mWidth), (compressed ? -1 : tex->mHeight),
(compressed ? "true" : "false"));
@@ -353,7 +350,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
for (unsigned int n = 0; n < mat->mNumProperties; ++n) {
const aiMaterialProperty *prop = mat->mProperties[n];
auto sz = "";
const char *sz = "";
if (prop->mType == aiPTI_Float) {
sz = "float";
} else if (prop->mType == aiPTI_Integer) {
+1 -1
View File
@@ -60,7 +60,7 @@ struct aiAnimation;
namespace Assimp{
class B3DImporter final : public BaseImporter{
class B3DImporter : public BaseImporter{
public:
B3DImporter() = default;
~B3DImporter() override;
+1 -1
View File
@@ -61,7 +61,7 @@ namespace Assimp {
* the hierarchy. It contains no actual mesh data, but we generate a dummy mesh
* inside the loader just to be able to see something.
*/
class BVHLoader final : public BaseImporter {
class BVHLoader : public BaseImporter {
/** Possible animation channels for which the motion data holds the values */
enum ChannelType {
+1 -3
View File
@@ -74,9 +74,7 @@ BlenderBMeshConverter::~BlenderBMeshConverter() {
// ------------------------------------------------------------------------------------------------
bool BlenderBMeshConverter::ContainsBMesh() const {
if (BMesh == nullptr) {
return false;
}
// TODO - Should probably do some additional verification here
return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
}
+6 -4
View File
@@ -63,12 +63,14 @@ namespace Assimp
struct MLoop;
}
class BlenderBMeshConverter final : public LogFunctions< BlenderBMeshConverter >
class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
{
public:
explicit BlenderBMeshConverter( const Blender::Mesh* mesh );
~BlenderBMeshConverter();
bool ContainsBMesh() const;
BlenderBMeshConverter( const Blender::Mesh* mesh );
~BlenderBMeshConverter( );
bool ContainsBMesh( ) const;
const Blender::Mesh* TriangulateBMesh( );
private:
+2 -3
View File
@@ -96,7 +96,7 @@ struct CustomDataTypeDescription {
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
* use a special readfunction for that cases
*/
static const std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
static std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
@@ -142,8 +142,7 @@ static const std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDe
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
} };
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION } };
bool isValidCustomDataType(const int cdtype) {
return cdtype >= 0 && cdtype < CD_NUMTYPES;
+59 -34
View File
@@ -55,14 +55,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// enable verbose log output. really verbose, so be careful.
#ifdef ASSIMP_BUILD_DEBUG
# define ASSIMP_BUILD_BLENDER_DEBUG
#define ASSIMP_BUILD_BLENDER_DEBUG
#endif
// set this to non-zero to dump BlenderDNA stuff to dna.txt.
// you could set it on the assimp build command line too without touching it here.
// !!! please make sure this is set to 0 in the repo !!!
#ifndef ASSIMP_BUILD_BLENDER_DEBUG_DNA
# define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0
#define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0
#endif
// #define ASSIMP_BUILD_BLENDER_NO_STATS
@@ -124,14 +124,22 @@ struct ElemBase {
* they used to point to.*/
// -------------------------------------------------------------------------------
struct Pointer {
uint64_t val{0};
Pointer() :
val() {
// empty
}
uint64_t val;
};
// -------------------------------------------------------------------------------
/** Represents a generic offset within a BLEND file */
// -------------------------------------------------------------------------------
struct FileOffset {
uint64_t val{0};
FileOffset() :
val() {
// empty
}
uint64_t val;
};
// -------------------------------------------------------------------------------
@@ -196,7 +204,7 @@ enum ErrorPolicy {
};
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
# define ErrorPolicy_Igno ErrorPolicy_Warn
#define ErrorPolicy_Igno ErrorPolicy_Warn
#endif
// -------------------------------------------------------------------------------
@@ -388,9 +396,10 @@ private:
mutable size_t cache_idx;
};
// -------------------------------------------------------------------------------------------------------
template<>
// --------------------------------------------------------
template <>
struct Structure::_defaultInitializer<ErrorPolicy_Warn> {
template <typename T>
void operator()(T &out, const char *reason = "<add reason>") {
ASSIMP_LOG_WARN(reason);
@@ -400,9 +409,9 @@ struct Structure::_defaultInitializer<ErrorPolicy_Warn> {
}
};
// -------------------------------------------------------------------------------------------------------
template<>
template <>
struct Structure::_defaultInitializer<ErrorPolicy_Fail> {
template <typename T>
void operator()(T & /*out*/, const char *message = "") {
// obviously, it is crucial that _DefaultInitializer is used
@@ -610,23 +619,31 @@ public:
/** Import statistics, i.e. number of file blocks read*/
// -------------------------------------------------------------------------------
class Statistics {
public:
Statistics() = default;
~Statistics() = default;
/// total number of fields we read
public:
Statistics() :
fields_read(), pointers_resolved(), cache_hits()
// , blocks_read ()
,
cached_objects() {}
public:
/** total number of fields we read */
unsigned int fields_read;
/// total number of resolved pointers
/** total number of resolved pointers */
unsigned int pointers_resolved;
/// number of pointers resolved from the cache
/** number of pointers resolved from the cache */
unsigned int cache_hits;
/// objects in FileData::cache
/** number of blocks (from FileDatabase::entries)
we did actually read from. */
// unsigned int blocks_read;
/** objects in FileData::cache */
unsigned int cached_objects;
};
#endif
// -------------------------------------------------------------------------------
@@ -639,13 +656,15 @@ public:
typedef std::map<Pointer, TOUT<ElemBase>> StructureCache;
public:
explicit ObjectCache(const FileDatabase &db) : db(db) {
ObjectCache(const FileDatabase &db) :
db(db) {
// currently there are only ~400 structure records per blend file.
// we read only a small part of them and don't cache objects
// which we don't need, so this should suffice.
caches.reserve(64);
}
public:
// --------------------------------------------------------
/** Check whether a specific item is in the cache.
* @param s Data type of the item
@@ -653,7 +672,10 @@ public:
* cache doesn't know the item yet.
* @param ptr Item address to look for. */
template <typename T>
void get( const Structure &s,TOUT<T> &out, const Pointer &ptr) const;
void get(
const Structure &s,
TOUT<T> &out,
const Pointer &ptr) const;
// --------------------------------------------------------
/** Add an item to the cache after the item has
@@ -678,7 +700,7 @@ private:
template <>
class ObjectCache<Blender::vector> {
public:
explicit ObjectCache(const FileDatabase &) {}
ObjectCache(const FileDatabase &) {}
template <typename T>
void get(const Structure &, vector<T> &, const Pointer &) {}
@@ -687,7 +709,7 @@ public:
};
#ifdef _MSC_VER
# pragma warning(disable : 4355)
#pragma warning(disable : 4355)
#endif
// -------------------------------------------------------------------------------
@@ -702,6 +724,16 @@ public:
FileDatabase() :
_cacheArrays(*this), _cache(*this), next_cache_idx() {}
public:
// publicly accessible fields
bool i64bit;
bool little;
DNA dna;
std::shared_ptr<StreamReaderAny> reader;
vector<FileBlockHead> entries;
public:
Statistics &stats() const {
return _stats;
}
@@ -720,15 +752,6 @@ public:
return _cacheArrays;
}
public:
// publicly accessible fields
bool i64bit;
bool little;
DNA dna;
std::shared_ptr<StreamReaderAny> reader;
vector<FileBlockHead> entries;
private:
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
mutable Statistics _stats;
@@ -741,19 +764,20 @@ private:
};
#ifdef _MSC_VER
# pragma warning(default : 4355)
#pragma warning(default : 4355)
#endif
// -------------------------------------------------------------------------------
/** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */
// -------------------------------------------------------------------------------
class DNAParser {
public:
/** Bind the parser to a empty DNA and an input stream */
explicit DNAParser(FileDatabase &db) : db(db) {
// empty
}
DNAParser(FileDatabase &db) :
db(db) {}
public:
// --------------------------------------------------------
/** Locate the DNA in the file and parse it. The input
* stream is expected to point to the beginning of the DN1
@@ -764,6 +788,7 @@ public:
* afterwards.*/
void Parse();
public:
/** Obtain a reference to the extracted DNA information */
const Blender::DNA &GetDNA() const {
return db.dna;
+3 -3
View File
@@ -961,7 +961,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
if (mesh->totface > static_cast<int>(mesh->mtface.size())) {
ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)");
}
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
for (MeshArray::iterator it = temp->begin() + old; it != temp->end(); ++it) {
ai_assert(0 != (*it)->mNumVertices);
ai_assert(0 != (*it)->mNumFaces);
const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
@@ -1030,7 +1030,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
if (mesh->totface > static_cast<int>(mesh->tface.size())) {
ThrowException("Number of faces is larger than the corresponding UV face array (#2)");
}
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
for (MeshArray::iterator it = temp->begin() + old; it != temp->end(); ++it) {
ai_assert(0 != (*it)->mNumVertices);
ai_assert(0 != (*it)->mNumFaces);
@@ -1057,7 +1057,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
if (mesh->totface > static_cast<int>((mesh->mcol.size() / 4))) {
ThrowException("Number of faces is larger than the corresponding color face array");
}
for (std::vector<aiMesh *>::iterator it = temp->begin() + old; it != temp->end(); ++it) {
for (MeshArray::iterator it = temp->begin() + old; it != temp->end(); ++it) {
ai_assert(0 != (*it)->mNumVertices);
ai_assert(0 != (*it)->mNumFaces);
+1 -1
View File
@@ -105,7 +105,7 @@ class BlenderModifier;
* call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the
* conversion from intermediate format to aiScene. */
// -------------------------------------------------------------------------------------------
class BlenderImporter final : public BaseImporter, public LogFunctions<BlenderImporter> {
class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter> {
public:
BlenderImporter();
~BlenderImporter() override;
+2 -2
View File
@@ -114,7 +114,7 @@ private:
* Mirror modifier. Status: implemented.
*/
// -------------------------------------------------------------------------------------------
class BlenderModifier_Mirror final : public BlenderModifier {
class BlenderModifier_Mirror : public BlenderModifier {
public:
// --------------------
virtual bool IsActive( const ModifierData& modin);
@@ -131,7 +131,7 @@ public:
// -------------------------------------------------------------------------------------------
/** Subdivision modifier. Status: dummy. */
// -------------------------------------------------------------------------------------------
class BlenderModifier_Subdivision final : public BlenderModifier {
class BlenderModifier_Subdivision : public BlenderModifier {
public:
// --------------------
+48 -45
View File
@@ -47,7 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h"
namespace Assimp::Blender {
namespace Assimp {
namespace Blender {
// Minor parts of this file are extracts from blender data structures,
// declared in the ./source/blender/makesdna directory.
@@ -114,32 +115,32 @@ struct Collection;
static const size_t MaxNameLen = 1024;
// -------------------------------------------------------------------------------
struct ID final : ElemBase {
struct ID : ElemBase {
char name[MaxNameLen] WARN;
short flag;
};
// -------------------------------------------------------------------------------
struct ListBase final : ElemBase {
struct ListBase : ElemBase {
std::shared_ptr<ElemBase> first;
std::weak_ptr<ElemBase> last;
};
// -------------------------------------------------------------------------------
struct PackedFile final : ElemBase {
struct PackedFile : ElemBase {
int size WARN;
int seek WARN;
std::shared_ptr<FileOffset> data WARN;
};
// -------------------------------------------------------------------------------
struct GroupObject final : ElemBase {
struct GroupObject : ElemBase {
std::shared_ptr<GroupObject> prev, next FAIL;
std::shared_ptr<Object> ob;
};
// -------------------------------------------------------------------------------
struct Group final : ElemBase {
struct Group : ElemBase {
ID id FAIL;
int layer;
@@ -147,32 +148,32 @@ struct Group final : ElemBase {
};
// -------------------------------------------------------------------------------
struct CollectionObject final : ElemBase {
struct CollectionObject : ElemBase {
//CollectionObject* prev;
std::shared_ptr<CollectionObject> next;
Object *ob;
};
// -------------------------------------------------------------------------------
struct CollectionChild final : ElemBase {
struct CollectionChild : ElemBase {
std::shared_ptr<CollectionChild> next, prev;
std::shared_ptr<Collection> collection;
};
// -------------------------------------------------------------------------------
struct Collection final : ElemBase {
struct Collection : ElemBase {
ID id FAIL;
ListBase gobject; // CollectionObject
ListBase children; // CollectionChild
};
// -------------------------------------------------------------------------------
struct World final : ElemBase {
struct World : ElemBase {
ID id FAIL;
};
// -------------------------------------------------------------------------------
struct MVert final : ElemBase {
struct MVert : ElemBase {
float co[3] FAIL;
float no[3] FAIL; // read as short and divided through / 32767.f
char flag;
@@ -184,31 +185,31 @@ struct MVert final : ElemBase {
};
// -------------------------------------------------------------------------------
struct MEdge final : ElemBase {
struct MEdge : ElemBase {
int v1, v2 FAIL;
char crease, bweight;
short flag;
};
// -------------------------------------------------------------------------------
struct MLoop final : ElemBase {
struct MLoop : ElemBase {
int v, e;
};
// -------------------------------------------------------------------------------
struct MLoopUV final : ElemBase {
struct MLoopUV : ElemBase {
float uv[2];
int flag;
};
// -------------------------------------------------------------------------------
// Note that red and blue are not swapped, as with MCol
struct MLoopCol final : ElemBase {
struct MLoopCol : ElemBase {
unsigned char r, g, b, a;
};
// -------------------------------------------------------------------------------
struct MPoly final : ElemBase {
struct MPoly : ElemBase {
int loopstart;
int totloop;
short mat_nr;
@@ -216,26 +217,26 @@ struct MPoly final : ElemBase {
};
// -------------------------------------------------------------------------------
struct MTexPoly final : ElemBase {
struct MTexPoly : ElemBase {
Image *tpage;
char flag, transp;
short mode, tile, pad;
};
// -------------------------------------------------------------------------------
struct MCol final : ElemBase {
struct MCol : ElemBase {
char r, g, b, a FAIL;
};
// -------------------------------------------------------------------------------
struct MFace final : ElemBase {
struct MFace : ElemBase {
int v1, v2, v3, v4 FAIL;
int mat_nr FAIL;
char flag;
};
// -------------------------------------------------------------------------------
struct TFace final : ElemBase {
struct TFace : ElemBase {
float uv[4][2] FAIL;
int col[4] FAIL;
char flag;
@@ -245,7 +246,7 @@ struct TFace final : ElemBase {
};
// -------------------------------------------------------------------------------
struct MTFace final : ElemBase {
struct MTFace : ElemBase {
MTFace() :
flag(0),
mode(0),
@@ -263,24 +264,24 @@ struct MTFace final : ElemBase {
};
// -------------------------------------------------------------------------------
struct MDeformWeight final : ElemBase {
struct MDeformWeight : ElemBase {
int def_nr FAIL;
float weight FAIL;
};
// -------------------------------------------------------------------------------
struct MDeformVert final : ElemBase {
struct MDeformVert : ElemBase {
vector<MDeformWeight> dw WARN;
int totweight;
};
// -------------------------------------------------------------------------------
constexpr uint32_t MA_RAYMIRROR = 0x40000;
constexpr uint32_t MA_TRANSPARENCY = 0x10000;
constexpr uint32_t MA_RAYTRANSP = 0x20000;
constexpr uint32_t MA_ZTRANSP = 0x00040;
#define MA_RAYMIRROR 0x40000
#define MA_TRANSPARENCY 0x10000
#define MA_RAYTRANSP 0x20000
#define MA_ZTRANSP 0x00040
struct Material final : ElemBase {
struct Material : ElemBase {
ID id FAIL;
float r, g, b WARN;
@@ -402,7 +403,7 @@ CustomDataLayer 104
char name 32 64
void *data 96 8
*/
struct CustomDataLayer final : ElemBase {
struct CustomDataLayer : ElemBase {
int type;
int offset;
int flag;
@@ -440,7 +441,7 @@ CustomData 208
BLI_mempool *pool 192 8
CustomDataExternal *external 200 8
*/
struct CustomData final : ElemBase {
struct CustomData : ElemBase {
vector<std::shared_ptr<struct CustomDataLayer>> layers;
int typemap[42]; // CD_NUMTYPES
int totlayer;
@@ -453,7 +454,7 @@ struct CustomData final : ElemBase {
};
// -------------------------------------------------------------------------------
struct Mesh final : ElemBase {
struct Mesh : ElemBase {
ID id FAIL;
int totface FAIL;
@@ -490,7 +491,7 @@ struct Mesh final : ElemBase {
};
// -------------------------------------------------------------------------------
struct Library final : ElemBase {
struct Library : ElemBase {
ID id FAIL;
char name[240] WARN;
@@ -514,7 +515,7 @@ struct Camera : ElemBase {
};
// -------------------------------------------------------------------------------
struct Lamp final : ElemBase {
struct Lamp : ElemBase {
enum FalloffType {
FalloffType_Constant = 0x0,
@@ -601,7 +602,7 @@ struct Lamp final : ElemBase {
};
// -------------------------------------------------------------------------------
struct ModifierData final : ElemBase {
struct ModifierData : ElemBase {
enum ModifierType {
eModifierType_None = 0,
eModifierType_Subsurf,
@@ -651,8 +652,9 @@ struct SharedModifierData : ElemBase {
ModifierData modifier;
};
// -------------------------------------------------------------------------------
struct SubsurfModifierData final : SharedModifierData {
struct SubsurfModifierData : SharedModifierData {
enum Type {
@@ -672,7 +674,7 @@ struct SubsurfModifierData final : SharedModifierData {
};
// -------------------------------------------------------------------------------
struct MirrorModifierData final : SharedModifierData {
struct MirrorModifierData : SharedModifierData {
enum Flags {
Flags_CLIPPING = 1 << 0,
@@ -690,7 +692,7 @@ struct MirrorModifierData final : SharedModifierData {
};
// -------------------------------------------------------------------------------
struct Object final : ElemBase {
struct Object : ElemBase {
ID id FAIL;
enum Type {
@@ -731,7 +733,7 @@ struct Object final : ElemBase {
};
// -------------------------------------------------------------------------------
struct Base final : ElemBase {
struct Base : ElemBase {
Base *prev WARN;
std::shared_ptr<Base> next WARN;
std::shared_ptr<Object> object WARN;
@@ -743,7 +745,7 @@ struct Base final : ElemBase {
};
// -------------------------------------------------------------------------------
struct Scene final : ElemBase {
struct Scene : ElemBase {
ID id FAIL;
std::shared_ptr<Object> camera WARN;
@@ -757,7 +759,7 @@ struct Scene final : ElemBase {
};
// -------------------------------------------------------------------------------
struct Image final : ElemBase {
struct Image : ElemBase {
ID id FAIL;
char name[240] WARN;
@@ -787,7 +789,7 @@ struct Image final : ElemBase {
};
// -------------------------------------------------------------------------------
struct Tex final : ElemBase {
struct Tex : ElemBase {
// actually, the only texture type we support is Type_IMAGE
enum Type {
@@ -872,13 +874,14 @@ struct Tex final : ElemBase {
//char use_nodes;
Tex() : imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS) {
Tex() :
imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS) {
// empty
}
};
// -------------------------------------------------------------------------------
struct MTex final : ElemBase {
struct MTex : ElemBase {
enum Projection {
Proj_N = 0,
@@ -967,6 +970,6 @@ struct MTex final : ElemBase {
MTex() = default;
};
} // namespace Assimp::Blender
} // namespace Blender
} // namespace Assimp
#endif
@@ -381,14 +381,7 @@ inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& poi
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Winvalid-offsetof"
#endif // __clang__
#if defined __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Winvalid-offsetof"
#endif // __GNUC__
unsigned int pointOffset = offsetof( PointP2T, point2D );
#if defined __GNUC__
# pragma GCC diagnostic pop
#endif // __GNUC__
#if defined __clang__
# pragma clang diagnostic pop
#endif
+8 -8
View File
@@ -166,10 +166,10 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
// copy meshes over
pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
std::copy(meshes.begin(), meshes.end(), pScene->mMeshes);
std::copy(mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
// copy materials over, adding a default material if necessary
unsigned int mat_count = static_cast<unsigned int>(materials.size());
unsigned int mat_count = static_cast<unsigned int>(mMaterials.size());
for(aiMesh* mesh : meshes) {
ai_assert(mesh->mMaterialIndex <= mat_count);
if(mesh->mMaterialIndex >= mat_count) {
@@ -179,14 +179,14 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
const aiString name(AI_DEFAULT_MATERIAL_NAME);
def_material->AddProperty(&name, AI_MATKEY_NAME);
materials.push_back(def_material.release());
mMaterials.push_back(def_material.release());
break;
}
}
pScene->mNumMaterials = static_cast<unsigned int>(materials.size());
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
std::copy(materials.begin(), materials.end(), pScene->mMaterials);
std::copy(mMaterials.begin(), mMaterials.end(), pScene->mMaterials);
}
// ------------------------------------------------------------------------------------------------
@@ -251,8 +251,8 @@ void C4DImporter::ReadMaterials(BaseMaterial* mat) {
while (mat) {
if (mat->GetType() == Mmaterial) {
aiMaterial* out = new aiMaterial();
material_mapping[mat] = static_cast<unsigned int>(materials.size());
materials.push_back(out);
mMaterialMapping[mat] = static_cast<unsigned int>(mMaterials.size());
mMaterials.push_back(out);
auto const ai_name = aiStringFrom(mat->GetName());
out->AddProperty(&ai_name, AI_MATKEY_NAME);
@@ -289,7 +289,7 @@ void C4DImporter::ReadMaterials(BaseMaterial* mat) {
// ------------------------------------------------------------------------------------------------
void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
ai_assert(parent != nullptr );
std::vector<aiNode*> nodes;
NodeArray nodes;
// based on Cineware sample code
while (object) {
@@ -577,7 +577,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) {
ai_assert(obj != nullptr);
const unsigned int mat_count = static_cast<unsigned int>(materials.size());
const unsigned int mat_count = static_cast<unsigned int>(mMaterials.size());
BaseTag* tag = obj->GetTag(Ttexture);
if(tag == nullptr) {
+5 -4
View File
@@ -97,11 +97,12 @@ private:
bool ReadShader(aiMaterial* out, cineware::BaseShader* shader);
std::vector<aiMesh*> meshes;
std::vector<aiMaterial*> materials;
private:
MeshArray mMeshes;
MaterialArray materials;
typedef std::map<cineware::BaseMaterial*, unsigned int> MaterialMap;
MaterialMap material_mapping;
using MaterialMap = std::map<cineware::BaseMaterial*, unsigned int> ;
MaterialMap mMaterialMapping;
}; // !class C4DImporter
+12 -28
View File
@@ -62,7 +62,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
namespace Assimp {
using namespace Assimp::COB;
using namespace Assimp::Formatter;
@@ -110,29 +109,10 @@ void COBImporter::SetupProperties(const Importer * /*pImp*/) {
}
// ------------------------------------------------------------------------------------------------
AI_WONT_RETURN void COBImporter::ThrowException(const std::string &msg) {
/*static*/ AI_WONT_RETURN void COBImporter::ThrowException(const std::string &msg) {
throw DeadlyImportError("COB: ", msg);
}
// ------------------------------------------------------------------------------------------------
static bool isValidASCIIHeader(const char *head) {
ai_assert(head != nullptr);
if (strncmp(head, "Caligari ", 9) != 0) {
COBImporter::ThrowException("Could not found magic id: `Caligari`");
}
if (strncmp(&head[9], "V00.", 4) != 0) {
COBImporter::ThrowException("Could not found Version tag: `V00.`");
}
ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6));
if (head[16] != 'L') {
COBImporter::ThrowException("File is big-endian, which is not supported");
}
return true;
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
@@ -146,15 +126,19 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(file));
// check header
static constexpr size_t HeaderSize = 32u;
char head[HeaderSize] = {};
stream->CopyAndAdvance(head, HeaderSize);
char head[32];
stream->CopyAndAdvance(head, 32);
if (strncmp(head, "Caligari ", 9) != 0) {
ThrowException("Could not found magic id: `Caligari`");
}
ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6));
if (head[16] != 'L') {
ThrowException("File is big-endian, which is not supported");
}
// load data into intermediate structures
if (head[15] == 'A') {
if (!isValidASCIIHeader(head)) {
ThrowException("Invalid ASCII file header");
}
ReadAsciiFile(scene, stream.get());
} else {
ReadBinaryFile(scene, stream.get());
@@ -1186,6 +1170,6 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
}
} // namespace Assimp
}
#endif // ASSIMP_BUILD_NO_COB_IMPORTER
+5 -6
View File
@@ -72,7 +72,7 @@ namespace COB {
*
* Currently relatively limited, loads only ASCII files and needs more test coverage. */
// -------------------------------------------------------------------------------------------
class COBImporter final : public BaseImporter {
class COBImporter : public BaseImporter {
public:
COBImporter() = default;
~COBImporter() override = default;
@@ -81,10 +81,6 @@ public:
bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
bool checkSig) const override;
// -------------------------------------------------------------------
/** Prepend 'COB: ' and throw msg.*/
AI_WONT_RETURN static void ThrowException(const std::string &msg) AI_WONT_RETURN_SUFFIX;
protected:
// --------------------
const aiImporterDesc *GetInfo() const override;
@@ -97,6 +93,10 @@ protected:
IOSystem *pIOHandler) override;
private:
// -------------------------------------------------------------------
/** Prepend 'COB: ' and throw msg.*/
AI_WONT_RETURN static void ThrowException(const std::string &msg) AI_WONT_RETURN_SUFFIX;
// -------------------------------------------------------------------
/** @brief Read from an ascii scene/object file
* @param out Receives output data.
@@ -148,5 +148,4 @@ private:
}; // !class COBImporter
} // end of namespace Assimp
#endif // AI_UNREALIMPORTER_H_INC
+75 -82
View File
@@ -52,66 +52,68 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <deque>
#include <map>
namespace Assimp::COB {
namespace Assimp {
namespace COB {
// ------------------
/** Represents a single vertex index in a face */
struct VertexIndex {
struct VertexIndex
{
// intentionally uninitialized
unsigned int pos_idx,uv_idx;
};
// ------------------
/** COB Face data structure */
struct Face {
struct Face
{
// intentionally uninitialized
unsigned int material;
unsigned int flags;
unsigned int material, flags;
std::vector<VertexIndex> indices;
};
// ------------------
/** COB chunk header information */
constexpr unsigned int NO_SIZE = UINT_MAX;
const unsigned int NO_SIZE = UINT_MAX;
struct ChunkInfo {
ChunkInfo() = default;
virtual ~ChunkInfo() = default;
struct ChunkInfo
{
ChunkInfo ()
: id (0)
, parent_id (0)
, version (0)
, size (NO_SIZE)
{}
// Id of this chunk, unique within file
unsigned int id{ 0 };
unsigned int id;
// and the corresponding parent
unsigned int parent_id{ 0 };
unsigned int parent_id;
// version. v1.23 becomes 123
unsigned int version{ 0 };
unsigned int version;
// chunk size in bytes, only relevant for binary files
// NO_SIZE is also valid.
unsigned int size{NO_SIZE};
unsigned int size;
};
// ------------------
/** A node in the scenegraph */
struct Node : ChunkInfo {
struct Node : public ChunkInfo
{
enum Type {
TYPE_INVALID = -1,
TYPE_MESH = 0,
TYPE_GROUP,
TYPE_LIGHT,
TYPE_CAMERA,
TYPE_BONE,
TYPE_COUNT
TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
};
~Node() override = default;
explicit Node(Type type) : type(type), unit_scale(1.f){}
virtual ~Node() = default;
Node(Type type) : type(type), unit_scale(1.f){}
Type type;
// used during resolving
using ChildList = std::deque<const Node*> ;
typedef std::deque<const Node*> ChildList;
mutable ChildList temp_children;
// unique name
@@ -126,7 +128,8 @@ struct Node : ChunkInfo {
// ------------------
/** COB Mesh data structure */
struct Mesh final : Node {
struct Mesh : public Node
{
using ChunkInfo::operator=;
enum DrawFlags {
SOLID = 0x1,
@@ -159,118 +162,107 @@ struct Mesh final : Node {
// ------------------
/** COB Group data structure */
struct Group final : Node {
struct Group : public Node
{
using ChunkInfo::operator=;
Group() : Node(TYPE_GROUP) {
// empty
}
Group() : Node(TYPE_GROUP) {}
};
// ------------------
/** COB Bone data structure */
struct Bone final : Node {
struct Bone : public Node
{
using ChunkInfo::operator=;
Bone() : Node(TYPE_BONE) {
// empty
}
Bone() : Node(TYPE_BONE) {}
};
// ------------------
/** COB Light data structure */
struct Light final : Node {
struct Light : public Node
{
enum LightType {
SPOT,
LOCAL,
INFINITE
SPOT,LOCAL,INFINITE
};
using ChunkInfo::operator=;
Light() : Node(TYPE_LIGHT), ltype() {
// empty
}
Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {}
aiColor3D color;
float angle{ 0.0f };
float inner_angle{ 0.0f };
float angle,inner_angle;
LightType ltype{SPOT};
LightType ltype;
};
// ------------------
/** COB Camera data structure */
struct Camera final : Node {
struct Camera : public Node
{
using ChunkInfo::operator=;
Camera() : Node(TYPE_CAMERA) {
// empty
}
Camera() : Node(TYPE_CAMERA) {}
};
// ------------------
/** COB Texture data structure */
struct Texture {
struct Texture
{
std::string path;
aiUVTransform transform;
};
// ------------------
/** COB Material data structure */
struct Material : ChunkInfo {
struct Material : ChunkInfo
{
using ChunkInfo::operator=;
enum Shader {
FLAT,
PHONG,
METAL
FLAT,PHONG,METAL
};
enum AutoFacet {
FACETED,
AUTOFACETED,
SMOOTH
FACETED,AUTOFACETED,SMOOTH
};
Material() : shader(FLAT) {
// empty
}
Material() : alpha(),exp(),ior(),ka(),ks(1.f),
matnum(UINT_MAX),
shader(FLAT),autofacet(FACETED),
autofacet_angle()
{}
std::string type;
aiColor3D rgb;
float alpha{ 0.0f };
float exp{ 0.0f };
float ior{ 0.0f };
float ka{ 0.0f };
float ks{ 1.0f };
unsigned int matnum{ UINT_MAX };
float alpha, exp, ior,ka,ks;
unsigned int matnum;
Shader shader;
AutoFacet autofacet{FACETED};
float autofacet_angle{ 0.0f };
AutoFacet autofacet;
float autofacet_angle;
std::shared_ptr<Texture> tex_env,tex_bump,tex_color;
};
// ------------------
/** Embedded bitmap, for instance for the thumbnail image */
struct Bitmap : ChunkInfo {
Bitmap() = default;
struct BitmapHeader {
// empty
struct Bitmap : ChunkInfo
{
Bitmap() : orig_size() {}
struct BitmapHeader
{
};
BitmapHeader head;
size_t orig_size{ 0u };
size_t orig_size;
std::vector<char> buff_zipped;
};
using NodeList = std::deque< std::shared_ptr<Node>>;
using MaterialList = std::vector< Material >;
typedef std::deque< std::shared_ptr<Node> > NodeList;
typedef std::vector< Material > MaterialList;
// ------------------
/** Represents a master COB scene, even if we loaded just a single COB file */
struct Scene {
struct Scene
{
NodeList nodes;
MaterialList materials;
@@ -278,6 +270,7 @@ struct Scene {
Bitmap thumbnail;
};
} // end Assimp::COB
} // end COB
} // end Assimp
#endif // INCLUDED_AI_COB_SCENE_H
#endif
+1 -1
View File
@@ -58,7 +58,7 @@ namespace Assimp {
* Link to file format specification:
* <max_8_dvd>\samples\Motion\Docs\CSM.rtf
*/
class CSMImporter final : public BaseImporter {
class CSMImporter : public BaseImporter {
public:
CSMImporter();
~CSMImporter() override = default;
+1 -1
View File
@@ -65,7 +65,7 @@ class IOSystem;
/// Helper class to export a given scene to a Collada file. Just for my personal
/// comfort when implementing it.
class ColladaExporter final {
class ColladaExporter {
public:
/// Constructor for a specific scene to export
ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file);
+1 -1
View File
@@ -341,7 +341,7 @@ struct SubMesh {
/// Contains data for a single mesh
struct Mesh {
explicit Mesh(const std::string &id) :
Mesh(const std::string &id) :
mId(id) {
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
mNumUVComponents[i] = 2;
+5 -5
View File
@@ -77,12 +77,12 @@ static constexpr aiImporterDesc desc = {
"dae xml zae"
};
static constexpr float kMillisecondsFromSeconds = 1000.f;
static const float kMillisecondsFromSeconds = 1000.f;
// Add an item of metadata to a node
// Assumes the key is not already in the list
template <typename T>
void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) {
inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) {
if (nullptr == node->mMetaData) {
node->mMetaData = new aiMetadata();
}
@@ -92,7 +92,7 @@ void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) {
// ------------------------------------------------------------------------------------------------
// Reads a float value from an accessor and its data array.
static ai_real ReadFloat(const Accessor &pAccessor, const Data &pData, size_t pIndex, size_t pOffset) {
const size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size());
return pData.mValues[pos];
}
@@ -668,7 +668,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
}
// create morph target meshes if any
std::vector<aiMesh *> targetMeshes;
MeshArray targetMeshes;
std::vector<float> targetWeights;
Collada::MorphMethod method = Normalized;
@@ -1819,4 +1819,4 @@ std::string ColladaLoader::FindNameForNode(const Node *pNode) {
} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_COLLADA_IMPORTER
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER
+3 -3
View File
@@ -82,7 +82,7 @@ struct ColladaMeshIndex {
* Collada is over-engineered to death, with every new iteration bringing more useless stuff,
* so I limited the data to what I think is useful for games.
*/
class ColladaLoader final : public BaseImporter {
class ColladaLoader : public BaseImporter {
public:
/// The class constructor.
ColladaLoader();
@@ -206,10 +206,10 @@ private:
std::map<std::string, size_t> mMaterialIndexByName;
/** Accumulated meshes for the target scene */
std::vector<aiMesh *> mMeshes;
MeshArray mMeshes;
/** Accumulated morph target meshes */
std::vector<aiMesh *> mTargetMeshes;
MeshArray mTargetMeshes;
/** Temporary material list */
std::vector<std::pair<Collada::Effect *, aiMaterial *>> newMats;
+2 -5
View File
@@ -1929,7 +1929,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh &pMesh,
std::vector<InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices) {
// calculate the base offset of the vertex whose attributes we ant to copy
const auto baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets;
size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets;
// don't overrun the boundaries of the index list
ai_assert((baseOffset + numOffsets - 1) < indices.size());
@@ -1944,9 +1944,6 @@ void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t n
}
// store the vertex-data index for later assignment of bone vertex weights
if (const auto indexOffset = baseOffset + perVertexOffset; indexOffset >= indices.size()) {
throw DeadlyImportError("index offset out of range");
}
pMesh.mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]);
}
@@ -2426,4 +2423,4 @@ InputType ColladaParser::GetTypeForSemantic(const std::string &semantic) {
return IT_Invalid;
}
#endif // !! ASSIMP_BUILD_NO_COLLADA_IMPORTER
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER
+5 -3
View File
@@ -53,14 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <assimp/DefaultLogger.hpp>
namespace Assimp::DXF {
namespace Assimp {
namespace DXF {
// read pairs of lines, parse group code and value and provide utilities
// to convert the data to the target data type.
// do NOT skip empty lines. In DXF files, they count as valid data.
class LineReader {
public:
explicit LineReader(StreamReaderLE& reader) : splitter(reader,false,true), groupcode( 0 ), end() {
LineReader(StreamReaderLE& reader) : splitter(reader,false,true), groupcode( 0 ), end() {
// empty
}
@@ -202,6 +203,7 @@ struct FileData {
std::vector<Block> blocks;
};
} // namespace Assimp::DXF
} // namespace DXF
} // namespace Assimp
#endif // INCLUDED_DXFHELPER_H
+1 -1
View File
@@ -66,7 +66,7 @@ namespace DXF {
/**
* @brief DXF importer implementation.
*/
class DXFImporter final : public BaseImporter {
class DXFImporter : public BaseImporter {
public:
DXFImporter() = default;
~DXFImporter() override = default;
+1 -1
View File
@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <set>
//
#if _MSC_VER > 1500 || (defined __GNUC__)
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
# else
# define fbx_unordered_map map
+29 -30
View File
@@ -72,7 +72,7 @@ namespace FBX {
using namespace Util;
#define MAGIC_NODE_TAG "_$AssimpFbx$"
static constexpr char MAGIC_NODE_TAG[] = "_$AssimpFbx$";
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL
@@ -125,21 +125,10 @@ static void correctRootTransform(const aiScene *scene) {
FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) :
defaultMaterialIndex(),
mMeshes(),
lights(),
cameras(),
textures(),
materials_converted(),
textures_converted(),
meshes_converted(),
node_anim_chain_bits(),
mNodeNames(),
anim_fps(),
mSceneOut(out),
doc(doc),
mRemoveEmptyBones(removeEmptyBones) {
// animations need to be converted first since this will
// populate the node_anim_chain_bits map, which is needed
// to determine which nodes need to be generated.
@@ -162,7 +151,7 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
continue;
}
const Material *mat = dynamic_cast<const Material *>(ob);
auto mat = dynamic_cast<const Material *>(ob);
if (mat) {
if (materials_converted.find(mat) == materials_converted.end()) {
@@ -222,7 +211,6 @@ static std::string getAncestorBaseName(const aiNode *node) {
return std::string(nodeName, length);
}
// Make unique name
std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiNode &parent) {
std::string original_name = FixNodeName(model->Name());
if (original_name.empty()) {
@@ -236,9 +224,18 @@ std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiN
/// This struct manages nodes which may or may not end up in the node hierarchy.
/// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
struct FBXConverter::PotentialNode {
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
explicit PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
aiNode* operator->() { return mNode; }
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {
// empty
}
explicit PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {
// empty
}
aiNode* operator->() {
return mNode;
}
std::unique_ptr<aiNode> mOwnership;
aiNode* mNode;
};
@@ -1092,14 +1089,14 @@ aiMesh *FBXConverter::SetupEmptyMesh(const Geometry &mesh, aiNode *parent) {
}
static aiSkeleton *createAiSkeleton(SkeletonBoneContainer &sbc) {
if (sbc.MeshArray.empty() || sbc.SkeletonBoneToMeshLookup.empty()) {
if (sbc.meshArray.empty() || sbc.skeletonBoneToMeshLookup.empty()) {
return nullptr;
}
aiSkeleton *skeleton = new aiSkeleton;
for (auto *mesh : sbc.MeshArray) {
auto it = sbc.SkeletonBoneToMeshLookup.find(mesh);
if (it == sbc.SkeletonBoneToMeshLookup.end()) {
for (auto *mesh : sbc.meshArray) {
auto it = sbc.skeletonBoneToMeshLookup.find(mesh);
if (it == sbc.skeletonBoneToMeshLookup.end()) {
continue;
}
SkeletonBoneArray *ba = it->second;
@@ -1547,12 +1544,12 @@ static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *s
void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent, unsigned int materialIndex,
std::vector<unsigned int> *outputVertStartIndices, SkeletonBoneContainer &skeletonContainer) {
if (skeletonContainer.SkeletonBoneToMeshLookup.find(out) != skeletonContainer.SkeletonBoneToMeshLookup.end()) {
if (skeletonContainer.skeletonBoneToMeshLookup.find(out) != skeletonContainer.skeletonBoneToMeshLookup.end()) {
return;
}
ConvertWeights(out, geo, absolute_transform, parent, materialIndex, outputVertStartIndices);
skeletonContainer.MeshArray.emplace_back(out);
skeletonContainer.meshArray.emplace_back(out);
SkeletonBoneArray *ba = new SkeletonBoneArray;
for (size_t i = 0; i < out->mNumBones; ++i) {
aiBone *bone = out->mBones[i];
@@ -1563,7 +1560,7 @@ void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo
copyBoneToSkeletonBone(out, bone, skeletonBone);
ba->emplace_back(skeletonBone);
}
skeletonContainer.SkeletonBoneToMeshLookup[out] = ba;
skeletonContainer.skeletonBoneToMeshLookup[out] = ba;
}
void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
@@ -1571,8 +1568,6 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
std::vector<unsigned int> *outputVertStartIndices) {
ai_assert(geo.DeformerSkin());
std::vector<size_t> out_indices, index_out_indices, count_out_indices;
const Skin &sk = *geo.DeformerSkin();
std::vector<aiBone*> bones;
@@ -1580,6 +1575,10 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
ai_assert(no_mat_check || outputVertStartIndices);
try {
std::vector<size_t> count_out_indices;
std::vector<size_t> index_out_indices;
std::vector<size_t> out_indices;
// iterate over the sub deformers
for (const Cluster *cluster : sk.Clusters()) {
ai_assert(cluster);
@@ -1751,10 +1750,10 @@ unsigned int FBXConverter::GetDefaultMaterial() {
return defaultMaterialIndex - 1;
}
aiMaterial *out_mat = new aiMaterial();
auto out_mat = new aiMaterial();
materials.push_back(out_mat);
const aiColor3D diffuse = aiColor3D(0.8f, 0.8f, 0.8f);
const auto diffuse = aiColor3D(0.8f, 0.8f, 0.8f);
out_mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
aiString s;
@@ -1770,7 +1769,7 @@ unsigned int FBXConverter::ConvertMaterial(const Material &material, const MeshG
const PropertyTable &props = material.Props();
// generate empty output material
aiMaterial *out_mat = new aiMaterial();
auto out_mat = new aiMaterial();
materials_converted[&material] = static_cast<unsigned int>(materials.size());
materials.push_back(out_mat);
@@ -1809,7 +1808,7 @@ unsigned int FBXConverter::ConvertMaterial(const Material &material, const MeshG
unsigned int FBXConverter::ConvertVideo(const Video &video) {
// generate empty output texture
aiTexture *out_tex = new aiTexture();
auto out_tex = new aiTexture();
textures.push_back(out_tex);
// assuming the texture is compressed
+2 -2
View File
@@ -80,8 +80,8 @@ using SkeletonBoneArray = std::vector<aiSkeletonBone *>;
using SkeletonBoneToMesh = std::map<aiMesh*, SkeletonBoneArray*>;
struct SkeletonBoneContainer {
std::vector<aiMesh *> MeshArray;
SkeletonBoneToMesh SkeletonBoneToMeshLookup;
MeshArray meshArray;
SkeletonBoneToMesh skeletonBoneToMeshLookup;
};
class Document;
+29 -29
View File
@@ -174,7 +174,7 @@ class NodeAttribute : public Object {
public:
NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~NodeAttribute() override = default;
virtual ~NodeAttribute() = default;
const PropertyTable& Props() const {
ai_assert(props.get());
@@ -186,11 +186,11 @@ private:
};
/** DOM base class for FBX camera settings attached to a node */
class CameraSwitcher final : public NodeAttribute {
class CameraSwitcher : public NodeAttribute {
public:
CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~CameraSwitcher() override= default;
virtual ~CameraSwitcher() = default;
int CameraID() const {
return cameraId;
@@ -231,11 +231,11 @@ private:
/** DOM base class for FBX cameras attached to a node */
class Camera final : public NodeAttribute {
class Camera : public NodeAttribute {
public:
Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~Camera() override = default;
virtual ~Camera() = default;
fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
@@ -257,24 +257,24 @@ public:
};
/** DOM base class for FBX null markers attached to a node */
class Null final : public NodeAttribute {
class Null : public NodeAttribute {
public:
Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~Null() override = default;
virtual ~Null() = default;
};
/** DOM base class for FBX limb node markers attached to a node */
class LimbNode final : public NodeAttribute {
class LimbNode : public NodeAttribute {
public:
LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~LimbNode() override = default;
virtual ~LimbNode() = default;
};
/** DOM base class for FBX lights attached to a node */
class Light final : public NodeAttribute {
class Light : public NodeAttribute {
public:
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~Light() override = default;
virtual ~Light() = default;
enum Type {
Type_Point,
@@ -329,7 +329,7 @@ public:
};
/** DOM base class for FBX models (even though its semantics are more "node" than "model" */
class Model final : public Object {
class Model : public Object {
public:
enum RotOrder {
RotOrder_EulerXYZ = 0,
@@ -354,7 +354,7 @@ public:
Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~Model() override = default;
virtual ~Model() = default;
fbx_simple_property(QuaternionInterpolate, int, 0)
@@ -477,11 +477,11 @@ private:
};
/** DOM class for generic FBX textures */
class Texture final : public Object {
class Texture : public Object {
public:
Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~Texture() override;
virtual ~Texture();
const std::string& Type() const {
return type;
@@ -542,10 +542,10 @@ private:
};
/** DOM class for layered FBX textures */
class LayeredTexture final : public Object {
class LayeredTexture : public Object {
public:
LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~LayeredTexture() override;
virtual ~LayeredTexture();
// Can only be called after construction of the layered texture object due to construction flag.
void fillTexture(const Document& doc);
@@ -608,11 +608,11 @@ using TextureMap = std::fbx_unordered_map<std::string, const Texture*>;
using LayeredTextureMap = std::fbx_unordered_map<std::string, const LayeredTexture*>;
/** DOM class for generic FBX videos */
class Video final : public Object {
class Video : public Object {
public:
Video(uint64_t id, const Element& element, const Document& doc, const std::string& name);
~Video() override;
virtual ~Video();
const std::string& Type() const {
return type;
@@ -697,10 +697,10 @@ using KeyTimeList = std::vector<int64_t>;
using KeyValueList = std::vector<float>;
/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */
class AnimationCurve final : public Object {
class AnimationCurve : public Object {
public:
AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
~AnimationCurve() override = default;
virtual ~AnimationCurve() = default;
/** get list of keyframe positions (time).
* Invariant: |GetKeys()| > 0 */
@@ -733,7 +733,7 @@ private:
using AnimationCurveMap = std::map<std::string, const AnimationCurve*>;
/** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
class AnimationCurveNode final : public Object {
class AnimationCurveNode : public Object {
public:
/* the optional white list specifies a list of property names for which the caller
wants animations for. If the curve node does not match one of these, std::range_error
@@ -741,7 +741,7 @@ public:
AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
~AnimationCurveNode() override = default;
virtual ~AnimationCurveNode() = default;
const PropertyTable& Props() const {
ai_assert(props.get());
@@ -783,7 +783,7 @@ private:
using AnimationCurveNodeList = std::vector<const AnimationCurveNode*>;
/** Represents a FBX animation layer (i.e. a list of node animations) */
class AnimationLayer final : public Object {
class AnimationLayer : public Object {
public:
AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationLayer() = default;
@@ -806,7 +806,7 @@ private:
using AnimationLayerList = std::vector<const AnimationLayer*>;
/** Represents a FBX animation stack (i.e. a list of animation layers) */
class AnimationStack final : public Object {
class AnimationStack : public Object {
public:
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationStack() = default;
@@ -851,7 +851,7 @@ using WeightIndexArray = std::vector<unsigned int>;
/** DOM class for BlendShapeChannel deformers */
class BlendShapeChannel final : public Deformer {
class BlendShapeChannel : public Deformer {
public:
BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name);
@@ -876,7 +876,7 @@ private:
};
/** DOM class for BlendShape deformers */
class BlendShape final : public Deformer {
class BlendShape : public Deformer {
public:
BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name);
@@ -891,7 +891,7 @@ private:
};
/** DOM class for skin deformer clusters (aka sub-deformers) */
class Cluster final : public Deformer {
class Cluster : public Deformer {
public:
Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name);
@@ -935,7 +935,7 @@ private:
};
/** DOM class for skin deformers */
class Skin final : public Deformer {
class Skin : public Deformer {
public:
Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+1 -1
View File
@@ -67,7 +67,7 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
///
/// See http://en.wikipedia.org/wiki/FBX
// -------------------------------------------------------------------------------------------
class FBXImporter final : public BaseImporter, public LogFunctions<FBXImporter> {
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
public:
/// @brief The class constructor.
FBXImporter() = default;
+3 -3
View File
@@ -162,7 +162,7 @@ aiMesh *IRRImporter::BuildSingleQuadMesh(const SkyboxVertex &v1,
}
// ------------------------------------------------------------------------------------------------
void IRRImporter::BuildSkybox(std::vector<aiMesh *> &meshes, std::vector<aiMaterial *> materials) {
void IRRImporter::BuildSkybox(MeshArray &meshes, std::vector<aiMaterial *> materials) {
// Update the material of the skybox - replace the name and disable shading for skyboxes.
for (unsigned int i = 0; i < 6; ++i) {
aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i)));
@@ -602,7 +602,7 @@ void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis
// ------------------------------------------------------------------------------------------------
void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
BatchLoader &batch,
std::vector<aiMesh *> &meshes,
MeshArray &meshes,
std::vector<aiNodeAnim *> &anims,
std::vector<AttachmentInfo> &attach,
std::vector<aiMaterial *> &materials,
@@ -1283,7 +1283,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
std::vector<aiNodeAnim *> anims;
std::vector<aiMaterial *> materials;
std::vector<AttachmentInfo> attach;
std::vector<aiMesh *> meshes;
MeshArray meshes;
// try to guess how much storage we'll need
anims.reserve(guessedAnimCnt + (guessedAnimCnt >> 2));
+2 -2
View File
@@ -229,7 +229,7 @@ private:
/// Fill the scene-graph recursively
void GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
BatchLoader &batch,
std::vector<aiMesh *> &meshes,
MeshArray &meshes,
std::vector<aiNodeAnim *> &anims,
std::vector<AttachmentInfo> &attach,
std::vector<aiMaterial *> &materials,
@@ -248,7 +248,7 @@ private:
/// @param meshes Receives 6 output meshes
/// @param materials The last 6 materials are assigned to the newly
/// created meshes. The names of the materials are adjusted.
void BuildSkybox(std::vector<aiMesh *> &meshes,
void BuildSkybox(MeshArray &meshes,
std::vector<aiMaterial *> materials);
// -------------------------------------------------------------------
+1 -1
View File
@@ -121,7 +121,7 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
// final data
std::vector<aiMaterial *> materials;
std::vector<aiMesh *> meshes;
MeshArray meshes;
materials.reserve(5);
meshes.reserve(5);
+1 -1
View File
@@ -239,7 +239,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
ResolveClips();
// now process all layers and build meshes and nodes
std::vector<aiMesh *> apcMeshes;
MeshArray apcMeshes;
std::map<uint16_t, aiNode *> apcNodes;
apcMeshes.reserve(mLayers->size() * std::min(((unsigned int)mSurfaces->size() / 2u), 1u));
+3 -1
View File
@@ -5,6 +5,8 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2025, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -1148,4 +1150,4 @@ void LWOImporter::LoadLWO3Surface(unsigned int size) {
}
}
#endif // ASSIMP_BUILD_NO_LWO_IMPORTER
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER
+1 -1
View File
@@ -332,7 +332,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) {
/* if we have the texture loaded, set format hint and pcData too */
tx->mWidth = t->w;
tx->mHeight = t->h;
strncpy(tx->achFormatHint, formatHint[t->f - 1], 8);
strcpy(tx->achFormatHint, formatHint[t->f - 1]);
tx->pcData = new aiTexel[tx->mWidth * tx->mHeight];
for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) {
switch (t->f) {
+2 -6
View File
@@ -393,15 +393,11 @@ MD5MeshParser::MD5MeshParser(SectionArray &mSections) {
else if (TokenMatch(sz, "tri", 3)) {
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
const unsigned int idx = strtoul10(sz, &sz);
if (idx >= desc.mFaces.size()) {
if (idx >= desc.mFaces.size())
desc.mFaces.resize(idx + 1);
}
aiFace &face = desc.mFaces[idx];
if (face.mNumIndices != 3) {
delete [] face.mIndices;
face.mIndices = new unsigned int[face.mNumIndices = 3];
}
face.mIndices = new unsigned int[face.mNumIndices = 3];
for (unsigned int i = 0; i < 3; ++i) {
AI_MD5_SKIP_SPACES(&sz, elem.end, elem.iLineNumber);
face.mIndices[i] = strtoul10(sz, &sz);
+2 -2
View File
@@ -1405,10 +1405,10 @@ void MDLImporter::InternReadFile_3DGS_MDL7() {
sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
// vector to held all created meshes
std::vector<aiMesh *> *avOutList;
MeshArray *avOutList;
// 3 meshes per group - that should be OK for most models
avOutList = new std::vector<aiMesh *>[pcHeader->groups_num];
avOutList = new MeshArray[pcHeader->groups_num];
for (uint32_t i = 0; i < pcHeader->groups_num; ++i)
avOutList[i].reserve(3);
+7 -4
View File
@@ -5,6 +5,8 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2025, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,8 +46,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Written against http://chumbalum.swissquake.ch/ms3d/ms3dspec.txt
*/
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
// internal headers
#include "MS3DLoader.h"
#include <assimp/StreamReader.h>
#include <assimp/DefaultLogger.hpp>
@@ -388,14 +392,13 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
if (need_default && materials.size()) {
ASSIMP_LOG_WARN("MS3D: Found group with no material assigned, spawning default material");
// if one of the groups has no material assigned, but there are other
// if one of the groups has no material assigned, but there are other
// groups with materials, a default material needs to be added (
// scenepreprocessor adds a default material only if nummat==0).
materials.emplace_back();
TempMaterial& m = materials.back();
constexpr char DefaultMat[18] = "<MS3D_DefaultMat>";
strncpy(m.name, DefaultMat, sizeof(m.name));
m.name[18]='\0';
strcpy(m.name,"<MS3D_DefaultMat>");
m.diffuse = aiColor4D(0.6f,0.6f,0.6f,1.0);
m.transparency = 1.f;
m.shininess = 0.f;
+1 -1
View File
@@ -270,7 +270,7 @@ void Q3BSPFileImporter::CreateNodes(const Q3BSP::Q3BSPModel *pModel, aiScene *pS
}
unsigned int matIdx(0);
std::vector<aiMesh *> MeshArray;
MeshArray MeshArray;
std::vector<aiNode *> NodeArray;
for (FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) {
std::vector<Q3BSP::sQ3BSPFace *> *pArray = (*it).second;
-7
View File
@@ -55,8 +55,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <limits>
namespace Assimp {
static constexpr aiImporterDesc desc = {
@@ -311,11 +309,6 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero");
}
const unsigned int uint_max = std::numeric_limits<unsigned int>::max();
if (tex->mWidth > (uint_max / tex->mHeight)) {
throw DeadlyImportError("Quick3D: Texture dimensions are too large, resulting in overflow.");
}
unsigned int mul = tex->mWidth * tex->mHeight;
aiTexel *begin = tex->pcData = new aiTexel[mul];
aiTexel *const end = &begin[mul - 1] + 1;
+1 -1
View File
@@ -116,7 +116,7 @@ struct SIBObject {
struct SIB {
std::vector<aiMaterial *> mtls;
std::vector<aiMesh *> meshes;
MeshArray meshes;
std::vector<aiLight *> lights;
std::vector<SIBObject> objs, insts;
};
+1 -1
View File
@@ -222,7 +222,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// ------------------------------------------------------------------------------------------------
// Read an ASCII STL file
void STLImporter::LoadASCIIFile(aiNode *root) {
std::vector<aiMesh *> meshes;
MeshArray meshes;
std::vector<aiNode *> nodes;
const char *sz = mBuffer;
const char *bufferEnd = mBuffer + mFileSize;
+1 -1
View File
@@ -58,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pragma warning(disable : 4127 4456 4245 4512 )
#endif // _MSC_VER
#if _MSC_VER > 1500 || (defined __GNUC__)
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
#else
# define step_unordered_map map
+1 -1
View File
@@ -63,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
//
#if _MSC_VER > 1500 || (defined __GNUC__)
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
# else
# define step_unordered_map map
+1 -1
View File
@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#if !defined(ASSIMP_BUILD_NO_VRML_IMPORTER)
#include "meshlabplugins/io_x3d/vrml/Parser.h"
#include "contrib/meshlab/autoclone/meshlab_repo-src/src/meshlabplugins/io_x3d/vrml/Parser.h"
#endif // #if !defined(ASSIMP_BUILD_NO_VRML_IMPORTER)
namespace Assimp {
+1 -1
View File
@@ -219,7 +219,7 @@ void XFileImporter::CreateMeshes(aiScene *pScene, aiNode *pNode, const std::vect
}
// create a mesh for each mesh-material combination in the source node
std::vector<aiMesh *> meshes;
MeshArray meshes;
for (unsigned int a = 0; a < pMeshes.size(); ++a) {
XFile::Mesh *sourceMesh = pMeshes[a];
if (nullptr == sourceMesh) {
+1 -1
View File
@@ -139,7 +139,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
ReadWorld(*worldNode, scope);
}
std::vector<aiMesh *> &meshes = scope.meshes_linear;
MeshArray &meshes = scope.meshes_linear;
std::vector<aiMaterial *> &materials = scope.materials_linear;
if (meshes.empty() || materials.empty()) {
ThrowException("failed to extract data from XGL file, no meshes loaded");
+1 -1
View File
@@ -83,7 +83,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
#if _MSC_VER > 1500 || (defined __GNUC__)
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
# else
# define gltf_unordered_map map
+1 -1
View File
@@ -192,7 +192,7 @@ static bool CheckValidFacesIndices(const aiFace *faces, unsigned nFaces, unsigne
}
void glTFImporter::ImportMeshes(Asset &r) {
std::vector<aiMesh *> meshes;
MeshArray meshes;
unsigned int k = 0;
meshOffsets.clear();
+4 -3
View File
@@ -64,7 +64,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <list>
#include <unordered_map>
#include <map>
#include <set>
#include <stdexcept>
#include <string>
@@ -95,7 +95,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# define ai_assert
#endif
#if _MSC_VER > 1500 || (defined __GNUC__)
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
#else
# define gltf_unordered_map map
@@ -1266,8 +1266,9 @@ private:
size_t mSceneLength;
size_t mBodyOffset;
size_t mBodyLength;
IdMap mUsedIds;
std::map<std::string, int, std::less<>> mUsedNamesMap;
Ref<Buffer> mBodyBuffer;
std::unordered_map<std::string, int> lastUsedID;
};
inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {
+29 -19
View File
@@ -438,6 +438,7 @@ unsigned int LazyDict<T>::Remove(const char *id) {
const unsigned int index = objIt->second;
mAsset.mUsedIds[id] = false;
mObjsById.erase(id);
mObjsByOIndex.erase(index);
delete mObjs[index];
@@ -471,6 +472,7 @@ unsigned int LazyDict<T>::Remove(const char *id) {
template <class T>
Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
typename Dict::iterator it = mObjsByOIndex.find(i);
if (it != mObjsByOIndex.end()) { // already created?
return Ref<T>(mObjs, it->second);
@@ -538,11 +540,16 @@ Ref<T> LazyDict<T>::Add(T *obj) {
mObjs.push_back(obj);
mObjsByOIndex[obj->oIndex] = idx;
mObjsById[obj->id] = idx;
mAsset.mUsedIds[obj->id] = true;
return Ref<T>(mObjs, idx);
}
template <class T>
Ref<T> LazyDict<T>::Create(const char *id) {
Asset::IdMap::iterator it = mAsset.mUsedIds.find(id);
if (it != mAsset.mUsedIds.end()) {
throw DeadlyImportError("GLTF: two objects with the same ID exist");
}
T *inst = new T();
unsigned int idx = unsigned(mObjs.size());
inst->id = id;
@@ -558,12 +565,11 @@ inline Buffer::Buffer() :
byteLength(0),
type(Type_arraybuffer),
EncodedRegion_Current(nullptr),
mIsSpecial(false) {
// empty
}
mIsSpecial(false) {}
inline Buffer::~Buffer() {
for (SEncodedRegion *reg : EncodedRegion_List) delete reg;
for (SEncodedRegion *reg : EncodedRegion_List)
delete reg;
}
inline const char *Buffer::TranslateId(Asset & /*r*/, const char *id) {
@@ -687,6 +693,7 @@ inline void Buffer::EncodedRegion_SetCurrent(const std::string &pID) {
}
inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count) {
if ((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) {
return false;
}
@@ -802,7 +809,8 @@ inline uint8_t *BufferView::GetPointerAndTailSize(size_t accOffset, size_t& outT
}
}
if (offset >= buffer->byteLength) {
if (offset >= buffer->byteLength)
{
outTailSize = 0;
return nullptr;
}
@@ -2198,27 +2206,29 @@ inline IOStream *Asset::OpenFile(const std::string &path, const char *mode, bool
inline std::string Asset::FindUniqueID(const std::string &str, const char *suffix) {
std::string id = str;
int n = 1;
if(!id.empty()) {
n = lastUsedID[id];
if(!n) {
lastUsedID[id] = n+1;
if (!id.empty()) {
if (mUsedIds.find(id) == mUsedIds.end()){
mUsedNamesMap[id] = 0;
return id;
}
id += "_";
}
if(suffix) {
id += suffix;
n = lastUsedID[id];
if(!n) {
lastUsedID[id] = n+1;
return id;
}
id += suffix;
Asset::IdMap::iterator it = mUsedIds.find(id);
if (it == mUsedIds.end()) {
mUsedNamesMap[id] = 0;
return id;
}
lastUsedID[id] = n+1;
return id + "_" + std::to_string(n-1);
auto key = id;
id += "_" + std::to_string(mUsedNamesMap[key]);
mUsedNamesMap[key] = mUsedNamesMap[key] + 1;
return id;
}
#if _MSC_VER
+1 -1
View File
@@ -69,7 +69,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# define ai_assert
#endif
#if _MSC_VER > 1500 || (defined __GNUC__)
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
#else
# define gltf_unordered_map map
+19 -12
View File
@@ -943,14 +943,17 @@ IF (ASSIMP_BUILD_VRML_IMPORTER)
message("****")
message("\n\n**** Cloning meshlab repo, git tag ${Meshlab_GIT_TAG}\n\n")
# Use CMAKE_CURRENT_SOURCE_DIR which provides assimp-local path (CMAKE_SOURCE_DIR is
# relative to top-level/main project)
set(Meshlab_BASE_ABSPATH "${CMAKE_CURRENT_SOURCE_DIR}/../contrib/meshlab")
# Note: Depending on user's OS, build environment etc it may be necessary to change line endings of
# "patches/meshlab.patch" file from CRLF to LF in order for patch operation to succeed
# Patch required to
# - replace QtXml w/pugixml
# - disable meshlab cmake scripts to prevent breaking assimp build
# - address compiler warnings to avoid breaking build for users who wisely treat warnings-as-errors
set(Meshlab_PATCHFILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../contrib/meshlab/patches/meshlab.patch")
set(Meshlab_PATCH_CMD git apply ${Meshlab_PATCHFILE_PATH})
set(Meshlab_PATCH_CMD git apply ${Meshlab_BASE_ABSPATH}/patches/meshlab.patch)
# Note: cloning entire meshlab repo is wasteful since we require literally only two source files.
# There is a technique using "git archive" e.g.
@@ -966,6 +969,9 @@ IF (ASSIMP_BUILD_VRML_IMPORTER)
# block (wait) as long as necessary until cloning is complete, so we immediately have full
# access to the cloned source files
include(FetchContent)
set(Meshlab_REPO_ABSPATH "${Meshlab_BASE_ABSPATH}/autoclone")
# Only want to clone once (on Android, using SOURCE_DIR will clone per-ABI (x86, x86_64 etc))
set(FETCHCONTENT_BASE_DIR ${Meshlab_REPO_ABSPATH})
set(FETCHCONTENT_QUIET on) # Turn off to troubleshoot repo clone problems
set(FETCHCONTENT_UPDATES_DISCONNECTED on) # Prevent other ABIs from re-cloning/re-patching etc
set(Meshlab_GIT_REPO "https://github.com/cnr-isti-vclab/meshlab")
@@ -978,17 +984,13 @@ IF (ASSIMP_BUILD_VRML_IMPORTER)
FetchContent_MakeAvailable(meshlab_repo)
message("**** Finished cloning meshlab repo")
message("****")
set(Meshlab_REPO_BASEPATH "${CMAKE_BINARY_DIR}/_deps/meshlab_repo-src/src")
set(Meshlab_SRC_ABSPATH "${Meshlab_REPO_BASEPATH}/meshlabplugins/io_x3d/vrml")
set(Meshlab_SRC_ABSPATH "${Meshlab_REPO_ABSPATH}/meshlab_repo-src/src/meshlabplugins/io_x3d/vrml")
set(Meshlab_SRCS
${Meshlab_SRC_ABSPATH}/Parser.cpp
${Meshlab_SRC_ABSPATH}/Scanner.cpp
)
INCLUDE_DIRECTORIES(
${Meshlab_SRC_ABSPATH}
# Add this to avoid include of generic-looking "Parser.h" (for sonarCloud)
${Meshlab_REPO_BASEPATH}
)
set(Meshlab_INCLUDE_DIRS "${Meshlab_SRC_ABSPATH}")
INCLUDE_DIRECTORIES(${Meshlab_INCLUDE_DIRS})
MESSAGE(STATUS "VRML enabled")
ELSE() # IF (ASSIMP_BUILD_VRML_IMPORTER)
set(Meshlab_SRCS "")
@@ -1001,6 +1003,10 @@ IF (ASSIMP_BUILD_USD_IMPORTER)
if (ASSIMP_BUILD_USD_VERBOSE_LOGS)
ADD_DEFINITIONS( -DASSIMP_USD_VERBOSE_LOGS)
endif ()
# Use CMAKE_CURRENT_SOURCE_DIR which provides assimp-local path (CMAKE_SOURCE_DIR is
# relative to top-level/main project)
set(Tinyusdz_BASE_ABSPATH "${CMAKE_CURRENT_SOURCE_DIR}/../contrib/tinyusdz")
set(Tinyusdz_REPO_ABSPATH "${Tinyusdz_BASE_ABSPATH}/autoclone")
# Note: ALWAYS specify a git commit hash (or tag) instead of a branch name; using a branch
# name can lead to non-deterministic (unpredictable) results since the code is potentially
@@ -1011,14 +1017,15 @@ IF (ASSIMP_BUILD_USD_IMPORTER)
message("\n\n**** Cloning tinyusdz repo, git tag ${TINYUSDZ_GIT_TAG}\n\n")
# Patch required to build arm32 on android
set(TINYUSDZ_PATCHFILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../contrib/tinyusdz/patches/tinyusdz.patch")
set(TINYUSDZ_PATCH_CMD git apply ${TINYUSDZ_PATCHFILE_PATH})
set(TINYUSDZ_PATCH_CMD git apply ${Tinyusdz_BASE_ABSPATH}/patches/tinyusdz.patch)
# Note: CMake's "FetchContent" (which executes at configure time) is much better for this use case
# than "ExternalProject" (which executes at build time); we just want to clone a repo and
# block (wait) as long as necessary until cloning is complete, so we immediately have full
# access to the cloned source files
include(FetchContent)
# Only want to clone once (on Android, using SOURCE_DIR will clone per-ABI (x86, x86_64 etc))
set(FETCHCONTENT_BASE_DIR ${Tinyusdz_REPO_ABSPATH})
set(FETCHCONTENT_QUIET on) # Turn off to troubleshoot repo clone problems
set(FETCHCONTENT_UPDATES_DISCONNECTED on) # Prevent other ABIs from re-cloning/re-patching etc
FetchContent_Declare(
@@ -1032,7 +1039,7 @@ IF (ASSIMP_BUILD_USD_IMPORTER)
message("**** Finished cloning tinyusdz repo")
message("****")
set(Tinyusdz_SRC_ABSPATH "${CMAKE_BINARY_DIR}/_deps/tinyusdz_repo-src/src")
set(Tinyusdz_SRC_ABSPATH "${Tinyusdz_REPO_ABSPATH}/tinyusdz_repo-src/src")
set(Tinyusdz_SRCS
${Tinyusdz_SRC_ABSPATH}/ascii-parser.cc
${Tinyusdz_SRC_ABSPATH}/ascii-parser-basetype.cc
+6 -8
View File
@@ -67,14 +67,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
namespace Assimp {
// underlying structure for aiPropertyStore
using PropertyMap = BatchLoader::PropertyMap ;
typedef BatchLoader::PropertyMap PropertyMap;
#if defined(__has_warning)
# if __has_warning("-Wordered-compare-function-pointers")
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wordered-compare-function-pointers"
#if __has_warning("-Wordered-compare-function-pointers")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wordered-compare-function-pointers"
#endif
#endif
@@ -112,7 +111,6 @@ void GetImporterInstanceList(std::vector<BaseImporter *> &out);
/** will delete all registered importers. */
void DeleteImporterInstanceList(std::vector<BaseImporter *> &out);
} // namespace Assimp
#ifndef ASSIMP_BUILD_SINGLETHREADED
@@ -129,7 +127,7 @@ public:
ai_assert(nullptr != s.callback);
}
~LogToCallbackRedirector() override {
~LogToCallbackRedirector() {
#ifndef ASSIMP_BUILD_SINGLETHREADED
std::lock_guard<std::mutex> lock(gLogStreamMutex);
#endif
@@ -148,7 +146,7 @@ public:
}
/** @copydoc LogStream::write */
void write(const char *message) override {
void write(const char *message) {
mStream.callback(message, mStream.user);
}
+4 -4
View File
@@ -68,11 +68,11 @@ public:
//! Represents data that is allocated on the heap, thus needs to be deleted
template <typename T>
struct THeapData final : Base {
struct THeapData : public Base {
explicit THeapData(T *in) :
data(in) {}
~THeapData() override {
~THeapData() {
delete data;
}
T *data;
@@ -80,11 +80,11 @@ public:
//! Represents static, by-value data not allocated on the heap
template <typename T>
struct TStaticData final : Base {
struct TStaticData : public Base {
explicit TStaticData(T in) :
data(in) {}
~TStaticData() override= default;
~TStaticData() = default;
T data;
};
+2 -2
View File
@@ -334,8 +334,8 @@ bool DefaultLogger::attachStream(LogStream *pStream, unsigned int severity) {
}
}
m_StreamArray.push_back(new LogStreamInfo(severity, pStream));
LogStreamInfo *pInfo = new LogStreamInfo(severity, pStream);
m_StreamArray.push_back(pInfo);
return true;
}
+1 -1
View File
@@ -53,7 +53,7 @@ namespace Assimp {
/**
* @brief Internal default implementation of the #ProgressHandler interface.
*/
class DefaultProgressHandler final : public ProgressHandler {
class DefaultProgressHandler : public ProgressHandler {
public:
/// @brief Ignores the update callback.
bool Update(float) override {
+1 -1
View File
@@ -733,7 +733,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
return nullptr;
}
}
#endif // ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
#endif // no validation
// Preprocess the scene and prepare it for post-processing
if (profiler) {
+13 -14
View File
@@ -678,8 +678,8 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
// ------------------------------------------------------------------------------------------------
// Build a list of unique bones
void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash> &asBones,
std::vector<aiMesh *>::const_iterator it,
std::vector<aiMesh *>::const_iterator end) {
MeshArray::const_iterator it,
MeshArray::const_iterator end) {
unsigned int iOffset = 0;
for (; it != end; ++it) {
for (unsigned int l = 0; l < (*it)->mNumBones; ++l) {
@@ -712,8 +712,7 @@ void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash> &asBones,
// ------------------------------------------------------------------------------------------------
// Merge a list of bones
void SceneCombiner::MergeBones(aiMesh *out, std::vector<aiMesh *>::const_iterator it,
std::vector<aiMesh *>::const_iterator end) {
void SceneCombiner::MergeBones(aiMesh *out, MeshArray::const_iterator it, MeshArray::const_iterator end) {
if (nullptr == out || out->mNumBones == 0) {
return;
}
@@ -771,8 +770,8 @@ void SceneCombiner::MergeBones(aiMesh *out, std::vector<aiMesh *>::const_iterato
// ------------------------------------------------------------------------------------------------
// Merge a list of meshes
void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
std::vector<aiMesh *>::const_iterator begin,
std::vector<aiMesh *>::const_iterator end) {
MeshArray::const_iterator begin,
MeshArray::const_iterator end) {
if (nullptr == _out) {
return;
}
@@ -788,7 +787,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
std::string name;
// Find out how much output storage we'll need
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
for (MeshArray::const_iterator it = begin; it != end; ++it) {
const char *meshName((*it)->mName.C_Str());
name += std::string(meshName);
if (it != end - 1) {
@@ -810,7 +809,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
if ((**begin).HasPositions()) {
pv2 = out->mVertices = new aiVector3D[out->mNumVertices];
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
for (MeshArray::const_iterator it = begin; it != end; ++it) {
if ((*it)->mVertices) {
::memcpy(pv2, (*it)->mVertices, (*it)->mNumVertices * sizeof(aiVector3D));
} else
@@ -822,7 +821,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
if ((**begin).HasNormals()) {
pv2 = out->mNormals = new aiVector3D[out->mNumVertices];
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
for (MeshArray::const_iterator it = begin; it != end; ++it) {
if ((*it)->mNormals) {
::memcpy(pv2, (*it)->mNormals, (*it)->mNumVertices * sizeof(aiVector3D));
} else {
@@ -837,7 +836,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
pv2 = out->mTangents = new aiVector3D[out->mNumVertices];
aiVector3D *pv2b = out->mBitangents = new aiVector3D[out->mNumVertices];
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
for (MeshArray::const_iterator it = begin; it != end; ++it) {
if ((*it)->mTangents) {
::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices * sizeof(aiVector3D));
::memcpy(pv2b, (*it)->mBitangents, (*it)->mNumVertices * sizeof(aiVector3D));
@@ -854,7 +853,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n];
pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices];
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
for (MeshArray::const_iterator it = begin; it != end; ++it) {
if ((*it)->mTextureCoords[n]) {
::memcpy(pv2, (*it)->mTextureCoords[n], (*it)->mNumVertices * sizeof(aiVector3D));
} else {
@@ -868,7 +867,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
n = 0;
while ((**begin).HasVertexColors(n)) {
aiColor4D *pVec2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
for (MeshArray::const_iterator it = begin; it != end; ++it) {
if ((*it)->mColors[n]) {
::memcpy(pVec2, (*it)->mColors[n], (*it)->mNumVertices * sizeof(aiColor4D));
} else {
@@ -887,7 +886,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
aiFace *pf2 = out->mFaces;
unsigned int ofs = 0;
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it) {
for (MeshArray::const_iterator it = begin; it != end; ++it) {
for (unsigned int m = 0; m < (*it)->mNumFaces; ++m, ++pf2) {
aiFace &face = (*it)->mFaces[m];
pf2->mNumIndices = face.mNumIndices;
@@ -910,7 +909,7 @@ void SceneCombiner::MergeMeshes(aiMesh **_out, unsigned int /*flags*/,
MergeBones(out, begin, end);
// delete all source meshes
for (std::vector<aiMesh *>::const_iterator it = begin; it != end; ++it)
for (MeshArray::const_iterator it = begin; it != end; ++it)
delete *it;
}
+3 -3
View File
@@ -158,8 +158,8 @@ void CatmullClarkSubdivider::Subdivide(
return;
}
std::vector<aiMesh *> inmeshes;
std::vector<aiMesh *> outmeshes;
MeshArray inmeshes;
MeshArray outmeshes;
std::vector<unsigned int> maptbl;
inmeshes.reserve(nmesh);
@@ -577,7 +577,7 @@ void CatmullClarkSubdivider::InternSubdivide(
// 7. Apply the next subdivision step.
// ---------------------------------------------------------------------
if (num != 1) {
std::vector<aiMesh *> tmp(nmesh);
MeshArray tmp(nmesh);
InternSubdivide(out, nmesh, &tmp.front(), num - 1);
for (size_t i = 0; i < nmesh; ++i) {
delete out[i];
+7 -13
View File
@@ -93,22 +93,17 @@ void ExportScenePbrt(const char *pFile, IOSystem *pIOSystem, const aiScene *pSce
const ExportProperties *) {
std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));
std::string texturesPath = path;
if (!texturesPath.empty()) {
texturesPath+=pIOSystem->getOsSeparator();
}
texturesPath+="textures";
// initialize the exporter
PbrtExporter exporter(pScene, pIOSystem, path, file, texturesPath);
PbrtExporter exporter(pScene, pIOSystem, path, file);
}
} // end of namespace Assimp
static void create_embedded_textures_folder(const aiScene *scene, IOSystem *pIOSystem, const std::string &texturesPath) {
static void create_embedded_textures_folder(const aiScene *scene, IOSystem *pIOSystem) {
if (scene->mNumTextures > 0) {
if (!pIOSystem->Exists(texturesPath)) {
if (!pIOSystem->CreateDirectory(texturesPath)) {
if (!pIOSystem->Exists("textures")) {
if (!pIOSystem->CreateDirectory("textures")) {
throw DeadlyExportError("Could not create textures/ directory.");
}
}
@@ -117,12 +112,11 @@ static void create_embedded_textures_folder(const aiScene *scene, IOSystem *pIOS
PbrtExporter::PbrtExporter(
const aiScene *pScene, IOSystem *pIOSystem,
const std::string &path, const std::string &file, const std::string &texturesPath) :
const std::string &path, const std::string &file) :
mScene(pScene),
mIOSystem(pIOSystem),
mPath(path),
mFile(file),
mTexturesPath(texturesPath),
mRootTransform(
// rotates the (already left-handed) CRS -90 degrees around the x axis in order to
// make +Z 'up' and +Y 'towards viewer', as in default in pbrt
@@ -140,7 +134,7 @@ PbrtExporter::PbrtExporter(
) * mRootTransform;
// Export embedded textures.
create_embedded_textures_folder(mScene, mIOSystem, mTexturesPath);
create_embedded_textures_folder(mScene, mIOSystem);
for (unsigned int i = 0; i < mScene->mNumTextures; ++i) {
aiTexture* tex = mScene->mTextures[i];
@@ -690,7 +684,7 @@ std::string PbrtExporter::CleanTextureFilename(const aiString &f, bool rewriteEx
}
// Expect all textures in textures
fn = mTexturesPath + mIOSystem->getOsSeparator() + fn;
fn = std::string("textures") + mIOSystem->getOsSeparator() + fn;
// Rewrite extension for unsupported file formats.
if (rewriteExtension) {
+1 -4
View File
@@ -74,7 +74,7 @@ class PbrtExporter {
public:
/// Constructor for a specific scene to export
PbrtExporter(const aiScene *pScene, IOSystem *pIOSystem,
const std::string &path, const std::string &file, const std::string &texturesPath);
const std::string &path, const std::string &file);
/// Destructor
virtual ~PbrtExporter() = default;
@@ -114,9 +114,6 @@ private:
/// Name of the file (without extension) where the scene will be exported
const std::string mFile;
/// Path of the textures directory (inlcuding seperator)
const std::string mTexturesPath;
// A private set to keep track of which textures have been declared
std::set<std::string> mTextureSet;
+5 -5
View File
@@ -65,22 +65,22 @@ namespace Assimp {
* You can contact RevoluPowered <gordon@gordonite.tech>
* For more info about this
*/
class ASSIMP_API ArmaturePopulate final : public BaseProcess {
class ASSIMP_API ArmaturePopulate : public BaseProcess {
public:
/// The default class constructor.
ArmaturePopulate() = default;
/// The class destructor.
~ArmaturePopulate() override = default;
virtual ~ArmaturePopulate() = default;
/// Overwritten, @see BaseProcess
bool IsActive( unsigned int pFlags ) const override;
virtual bool IsActive( unsigned int pFlags ) const;
/// Overwritten, @see BaseProcess
void SetupProperties( const Importer* pImp ) override;
virtual void SetupProperties( const Importer* pImp );
/// Overwritten, @see BaseProcess
void Execute( aiScene* pScene ) override;
virtual void Execute( aiScene* pScene );
static aiNode *GetArmatureRoot(aiNode *bone_node,
std::vector<aiBone *> &bone_list);
+1 -1
View File
@@ -58,7 +58,7 @@ namespace Assimp
* because the joining of vertices also considers tangents and bitangents for
* uniqueness.
*/
class ASSIMP_API_WINONLY CalcTangentsProcess final : public BaseProcess {
class ASSIMP_API_WINONLY CalcTangentsProcess : public BaseProcess {
public:
CalcTangentsProcess();
~CalcTangentsProcess() override = default;
@@ -58,7 +58,7 @@ namespace Assimp {
/** ComputeUVMappingProcess - converts special mappings, such as spherical,
* cylindrical or boxed to proper UV coordinates for rendering.
*/
class ComputeUVMappingProcess final : public BaseProcess {
class ComputeUVMappingProcess : public BaseProcess {
public:
ComputeUVMappingProcess() = default;
~ComputeUVMappingProcess() override = default;
+5 -5
View File
@@ -72,7 +72,7 @@ namespace Assimp {
*
* @note RH-LH and LH-RH is the same, so this class can be used for both
*/
class MakeLeftHandedProcess final : public BaseProcess {
class MakeLeftHandedProcess : public BaseProcess {
public:
MakeLeftHandedProcess() = default;
~MakeLeftHandedProcess() override = default;
@@ -147,7 +147,7 @@ public:
// ---------------------------------------------------------------------------
/** Postprocessing step to flip the UV coordinate system of the import data
*/
class FlipUVsProcess final : public BaseProcess
class FlipUVsProcess : public BaseProcess
{
friend class Importer;
@@ -156,13 +156,13 @@ public:
FlipUVsProcess();
/** Destructor, private as well */
~FlipUVsProcess() override;
~FlipUVsProcess();
// -------------------------------------------------------------------
bool IsActive( unsigned int pFlags) const override;
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
void Execute( aiScene* pScene) override;
void Execute( aiScene* pScene);
protected:
void ProcessMesh( aiMesh* pMesh);
+1 -1
View File
@@ -66,7 +66,7 @@ namespace Assimp {
* the bone are split from the mesh. The split off (new) mesh is boneless. At any
* point in time, bones without affect upon a given mesh are to be removed.
*/
class DeboneProcess final : public BaseProcess {
class DeboneProcess : public BaseProcess {
public:
DeboneProcess();
~DeboneProcess() override = default;
+1 -1
View File
@@ -52,7 +52,7 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** The DropFaceNormalsProcess computes face normals for all faces of all meshes
*/
class ASSIMP_API_WINONLY DropFaceNormalsProcess final : public BaseProcess {
class ASSIMP_API_WINONLY DropFaceNormalsProcess : public BaseProcess {
public:
DropFaceNormalsProcess() = default;
~DropFaceNormalsProcess() override = default;
+1 -1
View File
@@ -58,7 +58,7 @@ namespace Assimp {
* it will check if a file with the same name exists at the root folder
* of the imported model. And if so, it uses that.
*/
class ASSIMP_API EmbedTexturesProcess final : public BaseProcess {
class ASSIMP_API EmbedTexturesProcess : public BaseProcess {
public:
/// The default class constructor.
EmbedTexturesProcess() = default;
+12 -71
View File
@@ -51,9 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <numeric>
#include <memory>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
@@ -89,64 +86,6 @@ void GenFaceNormalsProcess::Execute(aiScene *pScene) {
}
}
namespace {
template<class XMesh>
void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) {
// replace vertex data with the unique data sets
pMesh->mNumVertices = static_cast<unsigned int>(uniqueVertices.size());
// ----------------------------------------------------------------------------
// NOTE - we're *not* calling Vertex::SortBack() because it would check for
// presence of every single vertex component once PER VERTEX. And our CPU
// dislikes branches, even if they're easily predictable.
// ----------------------------------------------------------------------------
// Position, if present (check made for aiAnimMesh)
if (pMesh->mVertices) {
std::unique_ptr<aiVector3D[]> oldVertices(pMesh->mVertices);
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mVertices[a] = oldVertices[uniqueVertices[a]];
}
}
// Tangents, if present
if (pMesh->mTangents) {
std::unique_ptr<aiVector3D[]> oldTangents(pMesh->mTangents);
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mTangents[a] = oldTangents[uniqueVertices[a]];
}
}
// Bitangents as well
if (pMesh->mBitangents) {
std::unique_ptr<aiVector3D[]> oldBitangents(pMesh->mBitangents);
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mBitangents[a] = oldBitangents[uniqueVertices[a]];
}
}
// Vertex colors
for (unsigned int a = 0; pMesh->HasVertexColors(a); a++) {
std::unique_ptr<aiColor4D[]> oldColors(pMesh->mColors[a]);
pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mColors[a][b] = oldColors[uniqueVertices[b]];
}
}
// Texture coords
for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++) {
std::unique_ptr<aiVector3D[]> oldTextureCoords(pMesh->mTextureCoords[a]);
pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mTextureCoords[a][b] = oldTextureCoords[uniqueVertices[b]];
}
}
}
} // namespace
// ------------------------------------------------------------------------------------------------
// Executes the post-processing step on the given imported data.
bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
@@ -173,21 +112,17 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
// mask to indicate if a vertex was already referenced and needs to be duplicated
std::vector<bool> alreadyReferenced;
alreadyReferenced.resize(pMesh->mNumVertices, false);
std::vector<int> duplicatedVertices;
duplicatedVertices.resize(pMesh->mNumVertices);
std::iota(std::begin(duplicatedVertices), std::end(duplicatedVertices), 0);
std::vector<aiVector3D> duplicatedVertices;
auto storeNormalSplitVertex = [&](unsigned int index, const aiVector3D& normal) {
if (!alreadyReferenced[index]) {
normals[index] = normal;
alreadyReferenced[index] = true;
} else {
duplicatedVertices.push_back(pMesh->mVertices[index]);
normals.push_back(normal);
duplicatedVertices.push_back(index);
index = static_cast<unsigned int>(duplicatedVertices.size() - 1);
index = pMesh->mNumVertices + static_cast<unsigned int>(duplicatedVertices.size() - 1);
}
return index;
};
@@ -219,10 +154,16 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
}
// store normals (and additional vertices) back into the mesh
if (pMesh->mNumVertices != std::size(duplicatedVertices)) {
updateXMeshVertices(pMesh, duplicatedVertices);
if (!duplicatedVertices.empty()) {
const aiVector3D * oldVertices = pMesh->mVertices;
auto oldNumVertices = pMesh->mNumVertices;
pMesh->mNumVertices += static_cast<unsigned int>(duplicatedVertices.size());
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mVertices, oldVertices, oldNumVertices * sizeof(aiVector3D));
memcpy(pMesh->mVertices + oldNumVertices, duplicatedVertices.data(), duplicatedVertices.size() * sizeof(aiVector3D));
delete[] oldVertices;
}
pMesh->mNormals = new aiVector3D[normals.size()];
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mNormals, normals.data(), normals.size() * sizeof(aiVector3D));
return true;

Some files were not shown because too many files have changed in this diff Show More