Merge branch 'master' into ios-build-script

* master: (34 commits)
  Update INSTALL for iOS build
  Improve the contribution guide
  usage of dynamic_cast instead of static_cast
  prevent zero sized array allocations
  reworked to ElemBase *
  use of malloc and free (given to shared ptr) for correct mem management
  rereworked suggested by clang
  travis changes according clang 5.0
  again travis hit me
  changes according travis compiles
  changes according travis build
  changed to coding convention
  issue_1973 added support for CustomData(Layer) to support multiple (texture) UV mappings added unittest with sample model
  Update script.iss
  replace typo by comment statement.
  Update script.iss
  Update script.iss
  Update script.iss
  Update script.iss
  Update script.iss
  ...
pull/2045/head
Doron Adler 2018-06-14 14:55:02 +03:00
commit 1d5b1b12e2
25 changed files with 808 additions and 89 deletions

View File

@ -1,11 +1,10 @@
#How to contribute # How to contribute
If you want to contribute you can follow these setps:
- Fist create your own clone of assimp
- When you want to fix a bug or add a new feature create a branch on your own fork ( just follow https://help.github.com/articles/creating-a-pull-request-from-a-fork/ )
- Push it to the repo and open a pull request
- A pull request will start our CI-service, which checks if the build works for linux and windows.
It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fails: fix it and the tests will be reastarted automatically
- At the end we will perform a code review and merge your branch to the master branch.
If you want to contribute, follow these steps:
- First, create your own clone of assimp.
- When you want to fix a bug or add a new feature, create a branch on your own fork following [these instructions](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
- Push it to your fork of the repository and open a pull request.
- A pull request will start our continuous integration service, which checks if the build works for Linux and Windows.
It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fail, fix it and the tests will be restarted automatically.
- At the end, we will perform a code review and merge your branch to the master branch.

View File

@ -42,3 +42,6 @@ For Windows:
1. Open a command prompt 1. Open a command prompt
2. cmake CMakeLists.txt 2. cmake CMakeLists.txt
2. Open your default IDE and build it 2. Open your default IDE and build it
For iOS:
Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS

View File

@ -32,6 +32,9 @@ install:
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017 - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
- if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64 - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
- cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%"
- set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe
cache: cache:
- code\assimp.dir\%CONFIGURATION% - code\assimp.dir\%CONFIGURATION%
@ -50,6 +53,7 @@ build:
project: Assimp.sln project: Assimp.sln
after_build: after_build:
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss
- 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\* - 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\*
test_script: test_script:

View File

@ -0,0 +1,185 @@
#include "BlenderCustomData.h"
#include "BlenderDNA.h"
#include <array>
#include <functional>
namespace Assimp {
namespace Blender {
/**
* @brief read/convert of Structure array to memory
*/
template<typename T>
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
for (size_t i = 0; i < cnt; ++i) {
T read;
s.Convert(read, db);
*p = read;
p++;
}
return true;
}
/**
* @brief pointer to function read memory for n CustomData types
*/
typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
typedef ElemBase * (*PCreate)(const size_t cnt);
typedef void(*PDestroy)(ElemBase *);
#define IMPL_STRUCT_READ(ty) \
bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
return read<ty>(db.dna[#ty], dynamic_cast<ty *>(v), cnt, db); \
}
#define IMPL_STRUCT_CREATE(ty) \
ElemBase *create##ty(const size_t cnt) { \
return new ty[cnt]; \
}
#define IMPL_STRUCT_DESTROY(ty) \
void destroy##ty(ElemBase *pE) { \
ty *p = dynamic_cast<ty *>(pE); \
delete[]p; \
}
/**
* @brief helper macro to define Structure functions
*/
#define IMPL_STRUCT(ty) \
IMPL_STRUCT_READ(ty) \
IMPL_STRUCT_CREATE(ty) \
IMPL_STRUCT_DESTROY(ty)
// supported structures for CustomData
IMPL_STRUCT(MVert)
IMPL_STRUCT(MEdge)
IMPL_STRUCT(MFace)
IMPL_STRUCT(MTFace)
IMPL_STRUCT(MTexPoly)
IMPL_STRUCT(MLoopUV)
IMPL_STRUCT(MLoopCol)
IMPL_STRUCT(MPoly)
IMPL_STRUCT(MLoop)
/**
* @brief describes the size of data and the read function to be used for single CustomerData.type
*/
struct CustomDataTypeDescription {
PRead Read; ///< function to read one CustomData type element
PCreate Create; ///< function to allocate n type elements
PDestroy Destroy;
CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy)
: Read(read)
, Create(create)
, Destroy(destroy)
{}
};
/**
* @brief helper macro to define Structure type specific CustomDataTypeDescription
* @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
*/
#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
CustomDataTypeDescription{&read##ty, &create##ty, &destroy##ty}
/**
* @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type
*/
#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
CustomDataTypeDescription{nullptr, nullptr, nullptr}
/**
* @brief descriptors for data pointed to from CustomDataLayer.data
* @note some of the CustomData uses already well defined Structures
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
* use a special readfunction for that cases
*/
std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
}};
bool isValidCustomDataType(const int cdtype) {
return cdtype >= 0 && cdtype < CD_NUMTYPES;
}
bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
if (!isValidCustomDataType(cdtype)) {
throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index"));
}
const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
// allocate cnt elements and parse them from file
out.reset(cdtd.Create(cnt), cdtd.Destroy);
return cdtd.Read(out.get(), cnt, db);
}
return false;
}
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
if (it->get()->type == cdtype && name == it->get()->name) {
return *it;
}
}
return nullptr;
}
const ElemBase * getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name)
{
const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
if (pLayer && pLayer->data) {
return pLayer->data.get();
}
return nullptr;
}
}
}

View File

@ -0,0 +1,89 @@
#pragma once
#include "BlenderDNA.h"
#include "BlenderScene.h"
#include <memory>
namespace Assimp {
namespace Blender {
/* CustomData.type from Blender (2.79b) */
enum CustomDataType {
CD_AUTO_FROM_NAME = -1,
CD_MVERT = 0,
#ifdef DNA_DEPRECATED
CD_MSTICKY = 1, /* DEPRECATED */
#endif
CD_MDEFORMVERT = 2,
CD_MEDGE = 3,
CD_MFACE = 4,
CD_MTFACE = 5,
CD_MCOL = 6,
CD_ORIGINDEX = 7,
CD_NORMAL = 8,
/* CD_POLYINDEX = 9, */
CD_PROP_FLT = 10,
CD_PROP_INT = 11,
CD_PROP_STR = 12,
CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
CD_ORCO = 14,
CD_MTEXPOLY = 15,
CD_MLOOPUV = 16,
CD_MLOOPCOL = 17,
CD_TANGENT = 18,
CD_MDISPS = 19,
CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */
/* CD_ID_MCOL = 21, */
CD_TEXTURE_MLOOPCOL = 22,
CD_CLOTH_ORCO = 23,
CD_RECAST = 24,
/* BMESH ONLY START */
CD_MPOLY = 25,
CD_MLOOP = 26,
CD_SHAPE_KEYINDEX = 27,
CD_SHAPEKEY = 28,
CD_BWEIGHT = 29,
CD_CREASE = 30,
CD_ORIGSPACE_MLOOP = 31,
CD_PREVIEW_MLOOPCOL = 32,
CD_BM_ELEM_PYPTR = 33,
/* BMESH ONLY END */
CD_PAINT_MASK = 34,
CD_GRID_PAINT_MASK = 35,
CD_MVERT_SKIN = 36,
CD_FREESTYLE_EDGE = 37,
CD_FREESTYLE_FACE = 38,
CD_MLOOPTANGENT = 39,
CD_TESSLOOPNORMAL = 40,
CD_CUSTOMLOOPNORMAL = 41,
CD_NUMTYPES = 42
};
/**
* @brief check if given cdtype is valid (ie >= 0 and < CD_NUMTYPES)
* @param[in] cdtype to check
* @return true when valid
*/
bool isValidCustomDataType(const int cdtype);
/**
* @brief returns CustomDataLayer ptr for given cdtype and name
* @param[in] customdata CustomData to search for wanted layer
* @param[in] cdtype to search for
* @param[in] name to search for
* @return CustomDataLayer * or nullptr if not found
*/
std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
/**
* @brief returns CustomDataLayer data ptr for given cdtype and name
* @param[in] customdata CustomData to search for wanted layer
* @param[in] cdtype to search for
* @param[in] name to search for
* @return * to struct data or nullptr if not found
*/
const ElemBase * getCustomDataLayerData(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
}
}

View File

@ -309,6 +309,28 @@ public:
void ReadField(T& out, const char* name, void ReadField(T& out, const char* name,
const FileDatabase& db) const; const FileDatabase& db) const;
// --------------------------------------------------------
/**
* @brief field parsing for dynamic vectors
* @param[in] out vector of struct to be filled
* @param[in] name of field
* @param[in] db to access the file, dna, ...
* @return true when read was successful
*/
template <int error_policy, template <typename> class TOUT, typename T>
bool ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const;
/**
* @brief parses raw customdata
* @param[in] out shared_ptr to be filled
* @param[in] cdtype customdata type to read
* @param[in] name of field ptr
* @param[in] db to access the file, dna, ...
* @return true when read was successful
*/
template <int error_policy>
bool ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const;
private: private:
// -------------------------------------------------------- // --------------------------------------------------------
@ -803,6 +825,17 @@ private:
FileDatabase& db; FileDatabase& db;
}; };
/**
* @brief read CustomData's data to ptr to mem
* @param[out] out memory ptr to set
* @param[in] cdtype to read
* @param[in] cnt cnt of elements to read
* @param[in] db to read elements from
* @return true when ok
*/
bool readCustomData(std::shared_ptr<ElemBase> &out, int cdtype, size_t cnt, const FileDatabase &db);
} // end Blend } // end Blend
} // end Assimp } // end Assimp

View File

@ -307,6 +307,108 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
} }
//--------------------------------------------------------------------------------
// field parsing for raw untyped data (like CustomDataLayer.data)
template <int error_policy>
bool Structure::ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const {
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
Pointer ptrval;
const Field* f;
try {
f = &(*this)[name];
// sanity check, should never happen if the genblenddna script is right
if (!(f->flags & FieldFlag_Pointer)) {
throw Error((Formatter::format(), "Field `", name, "` of structure `",
this->name, "` ought to be a pointer"));
}
db.reader->IncPtr(f->offset);
Convert(ptrval, db);
// actually it is meaningless on which Structure the Convert is called
// because the `Pointer` argument triggers a special implementation.
}
catch (const Error& e) {
_defaultInitializer<error_policy>()(out, e.what());
out.reset();
}
bool readOk = true;
if (ptrval.val) {
// get block for ptr
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
// read block->num instances of given type to out
readOk = readCustomData(out, cdtype, block->num, db);
}
// and recover the previous stream position
db.reader->SetCurrentPos(old);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
++db.stats().fields_read;
#endif
return readOk;
}
//--------------------------------------------------------------------------------
template <int error_policy, template <typename> class TOUT, typename T>
bool Structure::ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const {
out.clear();
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
Pointer ptrval;
const Field* f;
try {
f = &(*this)[name];
// sanity check, should never happen if the genblenddna script is right
if (!(f->flags & FieldFlag_Pointer)) {
throw Error((Formatter::format(), "Field `", name, "` of structure `",
this->name, "` ought to be a pointer"));
}
db.reader->IncPtr(f->offset);
Convert(ptrval, db);
// actually it is meaningless on which Structure the Convert is called
// because the `Pointer` argument triggers a special implementation.
}
catch (const Error& e) {
_defaultInitializer<error_policy>()(out, e.what());
out.clear();
return false;
}
if (ptrval.val) {
// find the file block the pointer is pointing to
const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
// I really ought to improve StreamReader to work with 64 bit indices exclusively.
const Structure& s = db.dna[f->type];
for (size_t i = 0; i < block->num; ++i) {
TOUT<T> p(new T);
s.Convert(*p, db);
out.push_back(p);
}
}
db.reader->SetCurrentPos(old);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
++db.stats().fields_read;
#endif
return false;
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <template <typename> class TOUT, typename T> template <template <typename> class TOUT, typename T>
bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db, bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,

View File

@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderIntermediate.h" #include "BlenderIntermediate.h"
#include "BlenderModifier.h" #include "BlenderModifier.h"
#include "BlenderBMesh.h" #include "BlenderBMesh.h"
#include "BlenderCustomData.h"
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
@ -1021,6 +1022,32 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
} }
} }
// TODO should we create the TextureUVMapping map in Convert<Material> to prevent redundant processing?
// create texture <-> uvname mapping for all materials
// key is texture number, value is data *
typedef std::map<uint32_t, const MLoopUV *> TextureUVMapping;
// key is material number, value is the TextureUVMapping for the material
typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
MaterialTextureUVMappings matTexUvMappings;
const uint32_t maxMat = static_cast<const uint32_t>(mesh->mat.size());
for (uint32_t m = 0; m < maxMat; ++m) {
// get material by index
const std::shared_ptr<Material> pMat = mesh->mat[m];
TextureUVMapping texuv;
const uint32_t maxTex = sizeof(pMat->mtex) / sizeof(pMat->mtex[0]);
for (uint32_t t = 0; t < maxTex; ++t) {
if (pMat->mtex[t] && pMat->mtex[t]->uvname[0]) {
// get the CustomData layer for given uvname and correct type
const ElemBase *pLoop = getCustomDataLayerData(mesh->ldata, CD_MLOOPUV, pMat->mtex[t]->uvname);
if (pLoop) {
texuv.insert(std::make_pair(t, dynamic_cast<const MLoopUV *>(pLoop)));
}
}
}
matTexUvMappings.insert(std::make_pair(m, texuv));
}
// collect texture coordinates, they're stored in a separate per-face buffer // collect texture coordinates, they're stored in a separate per-face buffer
if (mesh->mtface || mesh->mloopuv) { if (mesh->mtface || mesh->mloopuv) {
if (mesh->totface > static_cast<int> ( mesh->mtface.size())) { if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
@ -1028,8 +1055,17 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
} }
for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) { for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
ai_assert((*it)->mNumVertices && (*it)->mNumFaces); ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
if (itMatTexUvMapping == matTexUvMappings.end()) {
// default behaviour like before
(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices]; (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
}
else {
// create texture coords for every mapped tex
for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) {
(*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices];
}
}
(*it)->mNumFaces = (*it)->mNumVertices = 0; (*it)->mNumFaces = (*it)->mNumVertices = 0;
} }
@ -1051,13 +1087,34 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ]; aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
const aiFace& f = out->mFaces[out->mNumFaces++]; const aiFace& f = out->mFaces[out->mNumFaces++];
const auto itMatTexUvMapping = matTexUvMappings.find(v.mat_nr);
if (itMatTexUvMapping == matTexUvMappings.end()) {
// old behavior
aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices]; aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) { for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) {
const MLoopUV& uv = mesh->mloopuv[v.loopstart + j]; const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
vo->x = uv.uv[0]; vo->x = uv.uv[0];
vo->y = uv.uv[1]; vo->y = uv.uv[1];
} }
}
else {
// create textureCoords for every mapped tex
for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) {
const MLoopUV *tm = itMatTexUvMapping->second[m];
aiVector3D* vo = &out->mTextureCoords[m][out->mNumVertices];
uint32_t j = 0;
for (; j < f.mNumIndices; ++j, ++vo) {
const MLoopUV& uv = tm[v.loopstart + j];
vo->x = uv.uv[0];
vo->y = uv.uv[1];
}
// only update written mNumVertices in last loop
// TODO why must the numVertices be incremented here?
if (m == itMatTexUvMapping->second.size() - 1) {
out->mNumVertices += j;
}
}
}
} }
} }

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderScene.h" #include "BlenderScene.h"
#include "BlenderSceneGen.h" #include "BlenderSceneGen.h"
#include "BlenderDNA.h" #include "BlenderDNA.h"
#include "BlenderCustomData.h"
using namespace Assimp; using namespace Assimp;
using namespace Assimp::Blender; using namespace Assimp::Blender;
@ -481,6 +482,12 @@ template <> void Structure :: Convert<Mesh> (
ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db); ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
ReadField<ErrorPolicy_Igno>(dest.vdata, "vdata", db);
ReadField<ErrorPolicy_Igno>(dest.edata, "edata", db);
ReadField<ErrorPolicy_Igno>(dest.fdata, "fdata", db);
ReadField<ErrorPolicy_Igno>(dest.pdata, "pdata", db);
ReadField<ErrorPolicy_Warn>(dest.ldata, "ldata", db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
@ -786,6 +793,42 @@ template <> void Structure :: Convert<Image> (
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//--------------------------------------------------------------------------------
template <> void Structure::Convert<CustomData>(
CustomData& dest,
const FileDatabase& db
) const
{
ReadFieldArray<ErrorPolicy_Warn>(dest.typemap, "typemap", db);
ReadField<ErrorPolicy_Igno>(dest.pad_i1, "pad_i1", db);
ReadField<ErrorPolicy_Warn>(dest.totlayer, "totlayer", db);
ReadField<ErrorPolicy_Warn>(dest.maxlayer, "maxlayer", db);
ReadField<ErrorPolicy_Warn>(dest.totsize, "totsize", db);
ReadFieldPtrVector<ErrorPolicy_Warn>(dest.layers, "*layers", db);
db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
template <> void Structure::Convert<CustomDataLayer>(
CustomDataLayer& dest,
const FileDatabase& db
) const
{
ReadField<ErrorPolicy_Fail>(dest.type, "type", db);
ReadField<ErrorPolicy_Fail>(dest.offset, "offset", db);
ReadField<ErrorPolicy_Fail>(dest.flag, "flag", db);
ReadField<ErrorPolicy_Fail>(dest.active, "active", db);
ReadField<ErrorPolicy_Fail>(dest.active_rnd, "active_rnd", db);
ReadField<ErrorPolicy_Fail>(dest.active_clone, "active_clone", db);
ReadField<ErrorPolicy_Fail>(dest.active_mask, "active_mask", db);
ReadField<ErrorPolicy_Fail>(dest.uid, "uid", db);
ReadFieldArray<ErrorPolicy_Warn>(dest.name, "name", db);
ReadCustomDataPtr<ErrorPolicy_Fail>(dest.data, dest.type, "*data", db);
db.reader->IncPtr(size);
}
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
void DNA::RegisterConverters() { void DNA::RegisterConverters() {
@ -822,6 +865,8 @@ void DNA::RegisterConverters() {
converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> ); converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> ); converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> ); converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
converters["CustomData"] = DNA::FactoryPair(&Structure::Allocate<CustomData>, &Structure::Convert<CustomData>);
converters["CustomDataLayer"] = DNA::FactoryPair(&Structure::Allocate<CustomDataLayer>, &Structure::Convert<CustomDataLayer>);
} }
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -157,10 +157,16 @@ struct World : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MVert : ElemBase { struct MVert : ElemBase {
float co[3] FAIL; float co[3] FAIL;
float no[3] FAIL; float no[3] FAIL; // readed as short and divided through / 32767.f
char flag; char flag;
int mat_nr WARN; int mat_nr WARN;
int bweight; int bweight;
MVert() : ElemBase()
, flag(0)
, mat_nr(0)
, bweight(0)
{}
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -369,6 +375,73 @@ struct Material : ElemBase {
std::shared_ptr<MTex> mtex[18]; std::shared_ptr<MTex> mtex[18];
}; };
/*
CustomDataLayer 104
int type 0 4
int offset 4 4
int flag 8 4
int active 12 4
int active_rnd 16 4
int active_clone 20 4
int active_mask 24 4
int uid 28 4
char name 32 64
void *data 96 8
*/
struct CustomDataLayer : ElemBase {
int type;
int offset;
int flag;
int active;
int active_rnd;
int active_clone;
int active_mask;
int uid;
char name[64];
std::shared_ptr<ElemBase> data; // must be converted to real type according type member
CustomDataLayer()
: ElemBase()
, type(0)
, offset(0)
, flag(0)
, active(0)
, active_rnd(0)
, active_clone(0)
, active_mask(0)
, uid(0)
, data(nullptr)
{
memset(name, 0, sizeof name);
}
};
/*
CustomData 208
CustomDataLayer *layers 0 8
int typemap 8 168
int pad_i1 176 4
int totlayer 180 4
int maxlayer 184 4
int totsize 188 4
BLI_mempool *pool 192 8
CustomDataExternal *external 200 8
*/
struct CustomData : ElemBase {
vector<std::shared_ptr<struct CustomDataLayer> > layers;
int typemap[42]; // CD_NUMTYPES
int pad_i1;
int totlayer;
int maxlayer;
int totsize;
/*
std::shared_ptr<BLI_mempool> pool;
std::shared_ptr<CustomDataExternal> external;
*/
};
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Mesh : ElemBase { struct Mesh : ElemBase {
ID id FAIL; ID id FAIL;
@ -398,6 +471,12 @@ struct Mesh : ElemBase {
vector<MCol> mcol; vector<MCol> mcol;
vector< std::shared_ptr<Material> > mat FAIL; vector< std::shared_ptr<Material> > mat FAIL;
struct CustomData vdata;
struct CustomData edata;
struct CustomData fdata;
struct CustomData pdata;
struct CustomData ldata;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------

View File

@ -248,6 +248,17 @@ template <> void Structure :: Convert<Image> (
) const ) const
; ;
template <> void Structure::Convert<CustomData>(
CustomData& dest,
const FileDatabase& db
) const
;
template <> void Structure::Convert<CustomDataLayer>(
CustomDataLayer& dest,
const FileDatabase& db
) const
;
} }
} }

View File

@ -469,6 +469,8 @@ ADD_ASSIMP_IMPORTER( BLEND
BlenderBMesh.cpp BlenderBMesh.cpp
BlenderTessellator.h BlenderTessellator.h
BlenderTessellator.cpp BlenderTessellator.cpp
BlenderCustomData.h
BlenderCustomData.cpp
) )
ADD_ASSIMP_IMPORTER( IFC ADD_ASSIMP_IMPORTER( IFC

View File

@ -985,6 +985,10 @@ int64_t to_ktime(double ticks, const aiAnimation* anim) {
return (static_cast<int64_t>(ticks) / static_cast<int64_t>(anim->mTicksPerSecond)) * FBX::SECOND; return (static_cast<int64_t>(ticks) / static_cast<int64_t>(anim->mTicksPerSecond)) * FBX::SECOND;
} }
int64_t to_ktime(double time) {
return (static_cast<int64_t>(time * FBX::SECOND));
}
void FBXExporter::WriteObjects () void FBXExporter::WriteObjects ()
{ {
if (!binary) { if (!binary) {
@ -2089,7 +2093,7 @@ void FBXExporter::WriteObjects ()
// position/translation // position/translation
for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) { for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) {
const aiVectorKey& k = na->mPositionKeys[ki]; const aiVectorKey& k = na->mPositionKeys[ki];
times.push_back(to_ktime(k.mTime, anim)); times.push_back(to_ktime(k.mTime));
xval.push_back(k.mValue.x); xval.push_back(k.mValue.x);
yval.push_back(k.mValue.y); yval.push_back(k.mValue.y);
zval.push_back(k.mValue.z); zval.push_back(k.mValue.z);
@ -2103,7 +2107,7 @@ void FBXExporter::WriteObjects ()
times.clear(); xval.clear(); yval.clear(); zval.clear(); times.clear(); xval.clear(); yval.clear(); zval.clear();
for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) { for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) {
const aiQuatKey& k = na->mRotationKeys[ki]; const aiQuatKey& k = na->mRotationKeys[ki];
times.push_back(to_ktime(k.mTime, anim)); times.push_back(to_ktime(k.mTime));
// TODO: aiQuaternion method to convert to Euler... // TODO: aiQuaternion method to convert to Euler...
aiMatrix4x4 m(k.mValue.GetMatrix()); aiMatrix4x4 m(k.mValue.GetMatrix());
aiVector3D qs, qr, qt; aiVector3D qs, qr, qt;
@ -2121,7 +2125,7 @@ void FBXExporter::WriteObjects ()
times.clear(); xval.clear(); yval.clear(); zval.clear(); times.clear(); xval.clear(); yval.clear(); zval.clear();
for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) { for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) {
const aiVectorKey& k = na->mScalingKeys[ki]; const aiVectorKey& k = na->mScalingKeys[ki];
times.push_back(to_ktime(k.mTime, anim)); times.push_back(to_ktime(k.mTime));
xval.push_back(k.mValue.x); xval.push_back(k.mValue.x);
yval.push_back(k.mValue.y); yval.push_back(k.mValue.y);
zval.push_back(k.mValue.z); zval.push_back(k.mValue.z);

View File

@ -73,6 +73,7 @@ GenFaceNormalsProcess::~GenFaceNormalsProcess()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const { bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const {
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
return (pFlags & aiProcess_GenNormals) != 0; return (pFlags & aiProcess_GenNormals) != 0;
} }
@ -105,7 +106,8 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene) {
bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
{ {
if (NULL != pMesh->mNormals) { if (NULL != pMesh->mNormals) {
return false; if (force_) delete[] pMesh->mNormals;
else return false;
} }
// If the mesh consists of lines and/or points but not of // If the mesh consists of lines and/or points but not of
@ -134,7 +136,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize(); const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
for (unsigned int i = 0;i < face.mNumIndices;++i) { for (unsigned int i = 0;i < face.mNumIndices;++i) {
pMesh->mNormals[face.mIndices[i]] = vNor; pMesh->mNormals[face.mIndices[i]] = vNor;

View File

@ -78,7 +78,8 @@ public:
private: private:
bool GenMeshFaceNormals (aiMesh* pcMesh); bool GenMeshFaceNormals(aiMesh* pcMesh);
mutable bool force_ = false;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -72,6 +72,7 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() {
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
{ {
force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
return (pFlags & aiProcess_GenSmoothNormals) != 0; return (pFlags & aiProcess_GenSmoothNormals) != 0;
} }
@ -113,8 +114,10 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex) bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
{ {
if (NULL != pMesh->mNormals) if (NULL != pMesh->mNormals) {
return false; if (force_) delete[] pMesh->mNormals;
else return false;
}
// If the mesh consists of lines and/or points but not of // If the mesh consists of lines and/or points but not of
// triangles or higher-order polygons the normal vectors // triangles or higher-order polygons the normal vectors

View File

@ -107,6 +107,7 @@ private:
/** Configuration option: maximum smoothing angle, in radians*/ /** Configuration option: maximum smoothing angle, in radians*/
ai_real configMaxAngle; ai_real configMaxAngle;
mutable bool force_ = false;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -76,41 +76,36 @@ using namespace std;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Default constructor // Default constructor
ObjFileImporter::ObjFileImporter() : ObjFileImporter::ObjFileImporter()
m_Buffer(), : m_Buffer()
m_pRootObject( NULL ), , m_pRootObject( nullptr )
m_strAbsPath( "" ) , m_strAbsPath( "" ) {
{
DefaultIOSystem io; DefaultIOSystem io;
m_strAbsPath = io.getOsSeparator(); m_strAbsPath = io.getOsSeparator();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor. // Destructor.
ObjFileImporter::~ObjFileImporter() ObjFileImporter::~ObjFileImporter() {
{
delete m_pRootObject; delete m_pRootObject;
m_pRootObject = NULL; m_pRootObject = nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns true, if file is an obj file. // Returns true, if file is an obj file.
bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const {
{ if(!checkSig) {
if(!checkSig) //Check File Extension //Check File Extension
{
return SimpleExtensionCheck(pFile,"obj"); return SimpleExtensionCheck(pFile,"obj");
} } else {
else //Check file Header // Check file Header
{
static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " }; static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 ); return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiImporterDesc* ObjFileImporter::GetInfo () const const aiImporterDesc* ObjFileImporter::GetInfo () const {
{
return &desc; return &desc;
} }

View File

@ -362,14 +362,23 @@ void STLImporter::LoadASCIIFile( aiNode *root ) {
pMesh->mNumFaces = 0; pMesh->mNumFaces = 0;
throw DeadlyImportError("Normal buffer size does not match position buffer size"); throw DeadlyImportError("Normal buffer size does not match position buffer size");
} }
// only process positionbuffer when filled, else exception when accessing with index operator
// see line 353: only warning is triggered
// see line 373(now): access to empty positionbuffer with index operator forced exception
if (!positionBuffer.empty()) {
pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3); pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3);
pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size()); pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size());
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mVertices, positionBuffer.data(), pMesh->mNumVertices * sizeof(aiVector3D)); memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
positionBuffer.clear(); positionBuffer.clear();
}
// also only process normalBuffer when filled, else exception when accessing with index operator
if (!normalBuffer.empty()) {
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mNormals, normalBuffer.data(), pMesh->mNumVertices * sizeof(aiVector3D)); memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
normalBuffer.clear(); normalBuffer.clear();
}
// now copy faces // now copy faces
addFacesToMesh(pMesh); addFacesToMesh(pMesh);

View File

@ -559,6 +559,9 @@ enum aiPostProcessSteps
// aiProcess_GenEntityMeshes = 0x100000, // aiProcess_GenEntityMeshes = 0x100000,
// aiProcess_OptimizeAnimations = 0x200000 // aiProcess_OptimizeAnimations = 0x200000
// aiProcess_FixTexturePaths = 0x200000 // aiProcess_FixTexturePaths = 0x200000
aiProcess_ForceGenNormals = 0x20000000,
}; };

View File

@ -2,7 +2,7 @@
[Setup] [Setup]
AppName=Open Asset Import Library - SDK AppName=Open Asset Import Library - SDK
AppVerName=Open Asset Import Library - SDK (v3.3.1) AppVerName=Open Asset Import Library - SDK (v4.1.0)
DefaultDirName={pf}\Assimp DefaultDirName={pf}\Assimp
DefaultGroupName=Assimp DefaultGroupName=Assimp
UninstallDisplayIcon={app}\bin\x86\assimp.exe UninstallDisplayIcon={app}\bin\x86\assimp.exe
@ -12,9 +12,9 @@ SetupIconFile=..\..\tools\shared\assimp_tools_icon.ico
WizardImageFile=compiler:WizModernImage-IS.BMP WizardImageFile=compiler:WizModernImage-IS.BMP
WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP
LicenseFile=License.rtf LicenseFile=License.rtf
OutputBaseFileName=assimp-sdk-3.3.1-setup OutputBaseFileName=assimp-sdk-4.1.0-setup
VersionInfoVersion=3.3.1.0 VersionInfoVersion=4.1.0.0
VersionInfoTextVersion=3.3.1 VersionInfoTextVersion=4.1.0
VersionInfoCompany=Assimp Development Team VersionInfoCompany=Assimp Development Team
ArchitecturesInstallIn64BitMode=x64 ArchitecturesInstallIn64BitMode=x64
@ -30,20 +30,19 @@ Name: "help"; Description: "Help Files"; Types: full compact
Name: "samples"; Description: "Samples"; Types: full Name: "samples"; Description: "Samples"; Types: full
Name: "test"; Description: "Test Models (BSD-licensed)"; Types: full Name: "test"; Description: "Test Models (BSD-licensed)"; Types: full
Name: "test_nonbsd"; Description: "Test Models (other (free) licenses)"; Types: full Name: "test_nonbsd"; Description: "Test Models (other (free) licenses)"; Types: full
Name: "pyassimp"; Description: "Python Bindings"; Types: full ;Name: "pyassimp"; Description: "Python Bindings"; Types: full
Name: "dassimp"; Description: "D Bindings"; Types: full ;Name: "dassimp"; Description: "D Bindings"; Types: full
Name: "assimp_net"; Description: "C#/.NET Bindings"; Types: full ;Name: "assimp_net"; Description: "C#/.NET Bindings"; Types: full
[Run] [Run]
Filename: "{app}\stub\vc_redist.x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2015 redistributable package (32 Bit)"; Check: not IsWin64 ;Filename: "{app}\stub\vc_redist.x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (32 Bit)"; Check: not IsWin64
Filename: "{app}\stub\vc_redist.x64.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2015 redistributable package (64 Bit)"; Check: IsWin64 Filename: "{app}\stub\vc_redist.x64.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (64 Bit)"; Check: IsWin64
[Files] [Files]
Source: "readme_installer.txt"; DestDir: "{app}"; Flags: isreadme Source: "readme_installer.txt"; DestDir: "{app}"; Flags: isreadme
; Installer stub ; Installer stub
Source: "vc_redist.x86.exe"; DestDir: "{app}\stub\"; Check: not IsWin64 ;Source: "vc_redist.x86.exe"; DestDir: "{app}\stub\"; Check: not IsWin64
Source: "vc_redist.x64.exe"; DestDir: "{app}\stub\"; Check: IsWin64 Source: "vc_redist.x64.exe"; DestDir: "{app}\stub\"; Check: IsWin64
; Common stuff ; Common stuff
@ -55,27 +54,27 @@ Source: "WEB"; DestDir: "{app}"
Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs
; x86 binaries ; x86 binaries
Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" ;Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86"
Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools
Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "C:\Windows\SysWOW64\D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools
Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "C:\Windows\SysWOW64\D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools
Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools
; x64 binaries ; x64 binaries
Source: "..\..\bin\release\x64\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" Source: "..\..\bin\release\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64"
Source: "..\..\bin\release\x64\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools Source: "..\..\bin\release\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools
Source: "D3DCompiler_42_x64.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools Source: "C:\Windows\SysWOW64\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools
Source: "D3DX9_42_x64.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools Source: "C:\Windows\SysWOW64\D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools
Source: "..\..\bin\release\x64\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools Source: "..\..\bin\release\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools
; Documentation ; Documentation
Source: "..\..\doc\AssimpDoc_Html\AssimpDoc.chm"; DestDir: "{app}\doc"; Components: help ;Source: "..\..\doc\AssimpDoc_Html\AssimpDoc.chm"; DestDir: "{app}\doc"; Components: help
Source: "..\..\doc\AssimpCmdDoc_Html\AssimpCmdDoc.chm"; DestDir: "{app}\doc"; Components: help ;Source: "..\..\doc\AssimpCmdDoc_Html\AssimpCmdDoc.chm"; DestDir: "{app}\doc"; Components: help
Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help ;Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help
; Import libraries ; Import libraries
Source: "..\..\lib\release\x86\assimp.lib"; DestDir: "{app}\lib\x86" ;Source: "..\..\lib\release\x86\assimp.lib"; DestDir: "{app}\lib\x86"
Source: "..\..\lib\release\x64\assimp.lib"; DestDir: "{app}\lib\x64" Source: "..\..\lib\release\assimp-vc140-mt.lib"; DestDir: "{app}\lib\x64"
; Samples ; Samples
Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Components: samples Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Components: samples
@ -84,7 +83,7 @@ Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Comp
Source: "..\..\include\*"; DestDir: "{app}\include"; Flags: recursesubdirs Source: "..\..\include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
; dAssimp ; dAssimp
Source: "..\..\port\dAssimp\*"; DestDir: "{app}\port\D"; Flags: recursesubdirs; Components: dassimp ;Source: "..\..\port\dAssimp\*"; DestDir: "{app}\port\D"; Flags: recursesubdirs; Components: dassimp
; Assimp.NET ; Assimp.NET
;Source: "..\..\port\Assimp.NET\*"; DestDir: "{app}\port\C#"; Flags: recursesubdirs; Components: assimp_net ;Source: "..\..\port\Assimp.NET\*"; DestDir: "{app}\port\C#"; Flags: recursesubdirs; Components: assimp_net
@ -97,15 +96,6 @@ Source: "..\..\port\dAssimp\*"; DestDir: "{app}\port\D"; Flags: recursesubdirs;
;Source: "..\..\test\regression\*"; DestDir: "{app}\test\regression"; Flags: recursesubdirs; Components: test ;Source: "..\..\test\regression\*"; DestDir: "{app}\test\regression"; Flags: recursesubdirs; Components: test
;Source: "..\..\test\models-nonbsd\*"; DestDir: "{app}\test\models-nonbsd"; Flags: recursesubdirs; Components: test_nonbsd ;Source: "..\..\test\models-nonbsd\*"; DestDir: "{app}\test\models-nonbsd"; Flags: recursesubdirs; Components: test_nonbsd
; Source Code & Workspaces
;Source: "..\..\code\*"; Excludes: "*.o"; DestDir: "{app}\code"; Flags: recursesubdirs; Components: wsource
;Source: "..\..\workspaces\vc8\*.sln"; DestDir: "{app}\workspaces\vc8"; Components: wsource and vc8
;Source: "..\..\workspaces\vc8\*.vcproj"; DestDir: "{app}\workspaces\vc8"; Components: wsource and vc8
;Source: "..\..\workspaces\vc9\*.sln"; DestDir: "{app}\workspaces\vc9"; Components: wsource and vc9
;Source: "..\..\workspaces\vc9\*.vcproj"; DestDir: "{app}\workspaces\vc9"; Components: wsource and vc9
; Source: "Readme.txt"; DestDir: "{app}"; Flags: isreadme
[Icons] [Icons]
Name: "{group}\Assimp Manual"; Filename: "{app}\doc\AssimpDoc.chm" ; Components: help Name: "{group}\Assimp Manual"; Filename: "{app}\doc\AssimpDoc.chm" ; Components: help
Name: "{group}\Assimp Command Line Manual"; Filename: "{app}\doc\AssimpCmdDoc.chm"; Components: help Name: "{group}\Assimp Command Line Manual"; Filename: "{app}\doc\AssimpCmdDoc.chm"; Components: help

View File

@ -125,3 +125,30 @@ TEST_F(BlendImportMaterials, testImportMaterial)
ASSERT_PROPERTY_EQ(61, "mirror.glossSamples", mirrorGlossSamples); ASSERT_PROPERTY_EQ(61, "mirror.glossSamples", mirrorGlossSamples);
ASSERT_PROPERTY_FLOAT_EQ(0.87f, "mirror.glossAnisotropic", mirrorGlossAnisotropic); ASSERT_PROPERTY_FLOAT_EQ(0.87f, "mirror.glossAnisotropic", mirrorGlossAnisotropic);
} }
TEST_F(BlendImportMaterials, testImportMaterialwith2texturesAnd2TexCoordMappings)
{
const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/BLEND/plane_2_textures_2_texcoords_279.blend", aiProcess_ValidateDataStructure);
ASSERT_TRUE(pTest != NULL);
// material has 2 diffuse textures
ASSERT_TRUE(pTest->HasMaterials());
EXPECT_EQ(1, pTest->mNumMaterials);
const aiMaterial *pMat = pTest->mMaterials[0];
ASSERT_TRUE(nullptr != pMat);
ASSERT_EQ(2, pMat->GetTextureCount(aiTextureType_DIFFUSE));
aiString aPath;
aiTextureMapping tm = aiTextureMapping::aiTextureMapping_OTHER;
aiReturn result = pMat->GetTexture(aiTextureType_DIFFUSE, 0, &aPath, &tm);
ASSERT_EQ(aiReturn_SUCCESS, result);
result = pMat->GetTexture(aiTextureType_DIFFUSE, 1, &aPath, &tm);
ASSERT_EQ(aiReturn_SUCCESS, result);
// mesh has 2 texturecoord sets
ASSERT_TRUE(pTest->HasMeshes());
EXPECT_EQ(1, pTest->mNumMeshes);
const aiMesh *pMesh = pTest->mMeshes[0];
ASSERT_TRUE(nullptr != pMesh);
ASSERT_TRUE(pMesh->HasTextureCoords(0));
ASSERT_TRUE(pMesh->HasTextureCoords(1));
}

View File

@ -0,0 +1,57 @@
@echo off
set "initialdir=%cd%"
goto:main
:exitsucc
cd /d "%initialdir%"
set initialdir=
set MSBUILD_15="C:\Program Files (x86)\Microsoft Visual Studio\2018\Professional\MSBuild\15.0\Bin\msbuild.exe"
set MSBUILD_14="C:\Program Files (x86)\MSBuild\14.0\Bin\msbuild.exe"
if not "%VS150%"=="" set MSBUILD_15="%VS150%\MSBuild\15.0\Bin\msbuild.exe"
if /i %VS_VERSION%==2017 (
set MS_BUILD_EXE=%MSBUILD_15%
set PLATFORM_VER=v141
) else (
set MS_BUILD_EXE=%MSBUILD_14%
set PLATFORM_VER=v140
)
set MSBUILD=%MS_BUILD_EXE%
exit /b 0
:main
if not defined PLATFORM set "PLATFORM=x64"
::my work here is done?
set PATH_VSWHERE=C:\Program Files (x86)\Microsoft Visual Studio\Installer\
REM set PATH_STUDIO="C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\"
for /f "usebackq tokens=*" %%i in (`"%PATH_VSWHERE%vswhere" -latest -products * -requires Microsoft.Component.MSBuild -property installationPath`) do (
set InstallDir=%%i
)
IF EXIST "%InstallDir%\VC\Auxiliary\Build\vcvarsall.bat" set VS150=%InstallDir%\
set "CMAKE_GENERATOR=Visual Studio 15 2017 Win64"
if not "%VS150%"=="" call "%VS150%\VC\Auxiliary\Build\vcvarsall.bat" %PLATFORM% && echo found VS 2o17 && set PLATFORM_VER=v141 && set VS_VERSION=2017 && goto:exitsucc
set "CMAKE_GENERATOR=Visual Studio 14 2015 Win64"
if defined VS140COMNTOOLS call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" %PLATFORM% && echo found VS 2o15 && set PLATFORM_VER=v140 && set VS_VERSION=2015 && goto:exitsucc
if defined VS130COMNTOOLS echo call ghostbusters... found lost VS version
set "CMAKE_GENERATOR=Visual Studio 12 2013 Win64"
if defined VS120COMNTOOLS call "%VS120COMNTOOLS%..\..\VC\vcvarsall.bat" %PLATFORM% && echo found VS 2o13 && set PLATFORM_VER=v120 && set VS_VERSION=2013 && goto:exitsucc
set "CMAKE_GENERATOR=Visual Studio 11 2012 Win64"
if defined VS110COMNTOOLS call "%VS110COMNTOOLS%..\..\VC\vcvarsall.bat" %PLATFORM% && echo found VS 2o12 && set PLATFORM_VER=v110 && set VS_VERSION=2012 && goto:exitsucc
set "CMAKE_GENERATOR=Visual Studio 10 2010 Win64"
if defined VS100COMNTOOLS call "%VS100COMNTOOLS%..\..\VC\vcvarsall.bat" %PLATFORM% && echo found VS 2o1o && set PLATFORM_VER=v100 && set VS_VERSION=2010 && goto:exitsucc
goto:exitsucc

View File

@ -0,0 +1,18 @@
rem @echo off
setlocal
call build_env_win32.bat
set BUILD_CONFIG=release
set PLATFORM_CONFIG=x64
set MAX_CPU_CONFIG=4
set CONFIG_PARAMETER=/p:Configuration="%BUILD_CONFIG%"
set PLATFORM_PARAMETER=/p:Platform="%PLATFORM_CONFIG%"
set CPU_PARAMETER=/maxcpucount:%MAX_CPU_CONFIG%
set PLATFORM_TOOLSET=/p:PlatformToolset=%PLATFORM_VER%
pushd ..\..\
cmake CMakeLists.txt -G "Visual Studio 15 2017 Win64"
%MSBUILD% assimp.sln %CONFIG_PARAMETER% %PLATFORM_PARAMETER% %CPU_PARAMETER% %PLATFORM_TOOLSET%
popd
endlocal