[*] Merge with fresh master.

pull/972/head
Alexandr Arutjunov 2016-09-20 16:02:41 +03:00
commit f11545d2c0
12 changed files with 1130 additions and 58 deletions

View File

@ -404,7 +404,7 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD
} }
// acknowledge that the scene might come out incomplete // acknowledge that the scene might come out incomplete
// by Assimps definition of `complete`: blender scenes // by Assimp's definition of `complete`: blender scenes
// can consist of thousands of cameras or lights with // can consist of thousands of cameras or lights with
// not a single mesh between them. // not a single mesh between them.
if (!out->mNumMeshes) { if (!out->mNumMeshes) {
@ -790,7 +790,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp
) )
{ {
// TODO: Resolve various problems with BMesh triangluation before re-enabling. // TODO: Resolve various problems with BMesh triangulation before re-enabling.
// See issues #400, #373, #318 #315 and #132. // See issues #400, #373, #318 #315 and #132.
#if defined(TODO_FIX_BMESH_CONVERSION) #if defined(TODO_FIX_BMESH_CONVERSION)
BlenderBMeshConverter BMeshConverter( mesh ); BlenderBMeshConverter BMeshConverter( mesh );
@ -852,7 +852,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
//out->mNumVertices = 0 //out->mNumVertices = 0
out->mFaces = new aiFace[it.second](); out->mFaces = new aiFace[it.second]();
// all submeshes created from this mesh are named equally. this allows // all sub-meshes created from this mesh are named equally. this allows
// curious users to recover the original adjacency. // curious users to recover the original adjacency.
out->mName = aiString(mesh->id.name+2); out->mName = aiString(mesh->id.name+2);
// skip over the name prefix 'ME' // skip over the name prefix 'ME'
@ -1304,5 +1304,4 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
return node.dismiss(); return node.dismiss();
} }
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
#endif

View File

@ -275,9 +275,6 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
orig_object.id.name,"`"); orig_object.id.name,"`");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin) bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
{ {
@ -323,4 +320,4 @@ void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data
orig_object.id.name,"`"); orig_object.id.name,"`");
} }
#endif #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -806,4 +806,4 @@ void DNA::RegisterConverters() {
} }
#endif #endif ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -64,7 +64,7 @@ namespace Blender {
// * C++ style comments only // * C++ style comments only
// //
// * Structures may include the primitive types char, int, short, // * Structures may include the primitive types char, int, short,
// float, double. Signedness specifiers are not allowed on // float, double. Signed specifiers are not allowed on
// integers. Enum types are allowed, but they must have been // integers. Enum types are allowed, but they must have been
// defined in this header. // defined in this header.
// //
@ -85,9 +85,9 @@ namespace Blender {
// provided they are neither pointers nor arrays. // provided they are neither pointers nor arrays.
// //
// * One of WARN, FAIL can be appended to the declaration ( // * One of WARN, FAIL can be appended to the declaration (
// prior to the semiolon to specifiy the error handling policy if // prior to the semicolon to specify the error handling policy if
// this field is missing in the input DNA). If none of those // this field is missing in the input DNA). If none of those
// is specified the default policy is to subtitute a default // is specified the default policy is to substitute a default
// value for the field. // value for the field.
// //
@ -102,16 +102,16 @@ struct Image;
#define AI_BLEND_MESH_MAX_VERTS 2000000000L #define AI_BLEND_MESH_MAX_VERTS 2000000000L
static const size_t MaxNameLen = 1024;
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ID : ElemBase { struct ID : ElemBase {
char name[ MaxNameLen ] WARN;
char name[1024] WARN;
short flag; short flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ListBase : ElemBase { struct ListBase : ElemBase {
std::shared_ptr<ElemBase> first; std::shared_ptr<ElemBase> first;
std::shared_ptr<ElemBase> last; std::shared_ptr<ElemBase> last;
}; };
@ -126,7 +126,6 @@ struct PackedFile : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct GroupObject : ElemBase { struct GroupObject : ElemBase {
std::shared_ptr<GroupObject> prev,next FAIL; std::shared_ptr<GroupObject> prev,next FAIL;
std::shared_ptr<Object> ob; std::shared_ptr<Object> ob;
}; };
@ -142,7 +141,6 @@ struct Group : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct World : ElemBase { struct World : ElemBase {
ID id FAIL; ID id FAIL;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -217,7 +215,6 @@ struct TFace : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MTFace : ElemBase { struct MTFace : ElemBase {
float uv[4][2] FAIL; float uv[4][2] FAIL;
char flag; char flag;
short mode; short mode;
@ -235,7 +232,6 @@ struct MDeformWeight : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MDeformVert : ElemBase { struct MDeformVert : ElemBase {
vector<MDeformWeight> dw WARN; vector<MDeformWeight> dw WARN;
int totweight; int totweight;
}; };
@ -264,7 +260,6 @@ struct Material : ElemBase {
float darkness; float darkness;
float refrac; float refrac;
float amb; float amb;
float ang; float ang;
float spectra; float spectra;

View File

@ -290,6 +290,13 @@ size_t idx_srcdata_ind;// Index of begin of coordinates indices array in buffer.
bool comp_allow;// Point that data of current mesh can be compressed. bool comp_allow;// Point that data of current mesh can be compressed.
// Variables needed for compression. END. // Variables needed for compression. END.
std::string bufferId = mAsset->FindUniqueID("", "buffer");
Ref<Buffer> b = mAsset->GetBodyBuffer();
if (!b) {
b = mAsset->buffers.Create(bufferId);
}
for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) { for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) {
const aiMesh* aim = mScene->mMeshes[idx_mesh]; const aiMesh* aim = mScene->mMeshes[idx_mesh];
@ -325,13 +332,6 @@ bool comp_allow;// Point that data of current mesh can be compressed.
p.material = mAsset->materials.Get(aim->mMaterialIndex); p.material = mAsset->materials.Get(aim->mMaterialIndex);
std::string bufferId = mAsset->FindUniqueID(meshId, "buffer");
Ref<Buffer> b = mAsset->GetBodyBuffer();
if (!b) {
b = mAsset->buffers.Create(bufferId);
}
/******************* Vertices ********************/ /******************* Vertices ********************/
// If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored. // If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored.
if(comp_allow) idx_srcdata_begin = b->byteLength; if(comp_allow) idx_srcdata_begin = b->byteLength;
@ -347,6 +347,13 @@ bool comp_allow;// Point that data of current mesh can be compressed.
/************** Texture coordinates **************/ /************** Texture coordinates **************/
for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
// Flip UV y coords
if (aim -> mNumUVComponents[i] > 1) {
for (unsigned int j = 0; j < aim->mNumVertices; ++j) {
aim->mTextureCoords[i][j].y = 1 - aim->mTextureCoords[i][j].y;
}
}
if (aim->mNumUVComponents[i] > 0) { if (aim->mNumUVComponents[i] > 0) {
AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3; AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3;

View File

@ -0,0 +1,656 @@
<HTML>
<HEAD>
<META name="description"
content="Violet UML Editor cross format document" />
<META name="keywords" content="Violet, UML" />
<META charset="UTF-8" />
<SCRIPT type="text/javascript">
function switchVisibility() {
var obj = document.getElementById("content");
obj.style.display = (obj.style.display == "block") ? "none" : "block";
}
</SCRIPT>
</HEAD>
<BODY>
This file was generated with Violet UML Editor 2.1.0.
&nbsp;&nbsp;(&nbsp;<A href=# onclick="switchVisibility()">View Source</A>&nbsp;/&nbsp;<A href="http://sourceforge.net/projects/violet/files/violetumleditor/" target="_blank">Download Violet</A>&nbsp;)
<BR />
<BR />
<SCRIPT id="content" type="text/xml"><![CDATA[<ClassDiagramGraph id="1">
<nodes id="2">
<ClassNode id="3">
<children id="4"/>
<location class="Point2D.Double" id="5" x="270.0" y="200.0"/>
<id id="6" value="8ccad607-14e2-4eec-836e-b25f61cfa2ea"/>
<revision>1</revision>
<backgroundColor id="7">
<red>255</red>
<green>255</green>
<blue>255</blue>
<alpha>255</alpha>
</backgroundColor>
<borderColor id="8">
<red>0</red>
<green>0</green>
<blue>0</blue>
<alpha>255</alpha>
</borderColor>
<textColor reference="8"/>
<name id="9" justification="1" size="3" underlined="false">
<text>Assimpo::Exporter</text>
</name>
<attributes id="10" justification="0" size="4" underlined="false">
<text>aiScene* mScene;
IOSystem* mIOHandler;
struct ExportFormatEntry {
aiExportFormatDesc mDescription;
fpExportFunc mExportFunction;
};
</text>
</attributes>
<methods id="11" justification="0" size="4" underlined="false">
<text>const aiExportDataBlob* ExportToBlob( const aiScene* pScene, ... );
const aiExportDataBlob* ExportToBlob( const aiScene* pScene, ...);
aiReturn Export( const aiScene* pScene, ... );
aiReturn Export( const aiScene* pScene, ...);
</text>
</methods>
</ClassNode>
<ClassNode id="12">
<children id="13"/>
<location class="Point2D.Double" id="14" x="760.0" y="120.0"/>
<id id="15" value="c2ac589d-2d10-4a82-b77f-df3c3232086a"/>
<revision>1</revision>
<backgroundColor id="16">
<red>255</red>
<green>255</green>
<blue>255</blue>
<alpha>255</alpha>
</backgroundColor>
<borderColor id="17">
<red>0</red>
<green>0</green>
<blue>0</blue>
<alpha>255</alpha>
</borderColor>
<textColor reference="17"/>
<name id="18" justification="1" size="3" underlined="false">
<text>IOSystem</text>
</name>
<attributes id="19" justification="0" size="4" underlined="false">
<text></text>
</attributes>
<methods id="20" justification="0" size="4" underlined="false">
<text>bool Exists( const std::string&amp; pFile) const;
bool Exists( const char* pFile) const;
virtual char getOsSeparator() const;
virtual IOStream* Open(const char* pFile,
const char* pMode = &quot;rb&quot;);
IOStream* Open(const std::string&amp; pFile, const std::string&amp; pMode = std::string(&quot;rb&quot;));
void Close( IOStream* pFile);
</text>
</methods>
</ClassNode>
<ClassNode id="21">
<children id="22"/>
<location class="Point2D.Double" id="23" x="760.0" y="450.0"/>
<id id="24" value="543d8402-9358-46ed-abd8-77935414c423"/>
<revision>1</revision>
<backgroundColor reference="7"/>
<borderColor reference="8"/>
<textColor reference="8"/>
<name id="25" justification="1" size="3" underlined="false">
<text>ObjExporter</text>
</name>
<attributes id="26" justification="0" size="4" underlined="false">
<text>File contains function pointer:
ExportSceneObj</text>
</attributes>
<methods id="27" justification="0" size="4" underlined="false">
<text></text>
</methods>
</ClassNode>
</nodes>
<edges id="28">
<NoteEdge id="29">
<start class="ClassNode" reference="3"/>
<end class="ClassNode" reference="12"/>
<startLocation class="Point2D.Double" id="30" x="130.0" y="70.0"/>
<endLocation class="Point2D.Double" id="31" x="120.0" y="70.0"/>
<transitionPoints id="32"/>
<id id="33" value="32e48b3f-86c7-427a-9d3b-9fa3af2a79f7"/>
<revision>1</revision>
</NoteEdge>
<NoteEdge id="34">
<start class="ClassNode" reference="12"/>
<end class="ClassNode" reference="12"/>
<startLocation class="Point2D.Double" id="35" x="20.0" y="70.0"/>
<endLocation class="Point2D.Double" reference="35"/>
<transitionPoints id="36"/>
<id id="37" value="8b7d1b44-5b84-4bdc-b723-096126d300a4"/>
<revision>1</revision>
</NoteEdge>
<NoteEdge id="38">
<start class="ClassNode" reference="3"/>
<end class="ClassNode" reference="3"/>
<startLocation class="Point2D.Double" id="39" x="190.0" y="80.0"/>
<endLocation class="Point2D.Double" reference="39"/>
<transitionPoints id="40"/>
<id id="41" value="ac092bcb-c3bb-4ac7-bc77-879556396f91"/>
<revision>1</revision>
</NoteEdge>
<NoteEdge id="42">
<start class="ClassNode" reference="12"/>
<end class="ClassNode" reference="12"/>
<startLocation class="Point2D.Double" id="43" x="370.0" y="80.0"/>
<endLocation class="Point2D.Double" reference="43"/>
<transitionPoints id="44"/>
<id id="45" value="3d0ad2f3-6f05-491d-b8c8-961212d7a0c9"/>
<revision>1</revision>
</NoteEdge>
<NoteEdge id="46">
<start class="ClassNode" reference="3"/>
<end class="ClassNode" reference="3"/>
<startLocation class="Point2D.Double" id="47" x="50.0" y="40.0"/>
<endLocation class="Point2D.Double" reference="47"/>
<transitionPoints id="48"/>
<id id="49" value="e8d16ba4-8036-4f77-81ad-aee4e11adbfe"/>
<revision>1</revision>
</NoteEdge>
<NoteEdge id="50">
<start class="ClassNode" reference="3"/>
<end class="ClassNode" reference="21"/>
<startLocation class="Point2D.Double" id="51" x="300.0" y="250.0"/>
<endLocation class="Point2D.Double" id="52" x="20.0" y="40.0"/>
<transitionPoints id="53"/>
<id id="54" value="c9fa9dbf-f219-4363-9f26-aeea21492a1f"/>
<revision>1</revision>
</NoteEdge>
<NoteEdge id="55">
<start class="ClassNode" reference="21"/>
<end class="ClassNode" reference="21"/>
<startLocation class="Point2D.Double" id="56" x="60.0" y="90.0"/>
<endLocation class="Point2D.Double" reference="56"/>
<transitionPoints id="57"/>
<id id="58" value="a1addbce-8d05-4a56-9289-d885dedc75c2"/>
<revision>1</revision>
</NoteEdge>
<NoteEdge id="59">
<start class="ClassNode" reference="21"/>
<end class="ClassNode" reference="21"/>
<startLocation class="Point2D.Double" id="60" x="60.0" y="70.0"/>
<endLocation class="Point2D.Double" reference="60"/>
<transitionPoints id="61"/>
<id id="62" value="2155dc70-7a87-4d23-a8f3-7798f7931872"/>
<revision>1</revision>
</NoteEdge>
<NoteEdge id="63">
<start class="ClassNode" reference="21"/>
<end class="ClassNode" reference="21"/>
<startLocation class="Point2D.Double" id="64" x="80.0" y="60.0"/>
<endLocation class="Point2D.Double" id="65" x="140.0" y="40.0"/>
<transitionPoints id="66"/>
<id id="67" value="5473f8fb-4b83-475c-bb59-6c60b45f5948"/>
<revision>1</revision>
</NoteEdge>
</edges>
</ClassDiagramGraph>]]></SCRIPT>
<BR />
<BR />
<IMG alt="embedded diagram image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA88AAAHHCAIAAAAOJf3QAABkOklEQVR42uydf0hcx964CyIie2Ur
LCIiRaRixYpXLCISgohgxUoavAFfCaGEIF+xYqUtliDekIY0vFKkSBDfN6SSG2xIkCAiQYQ0pMGK
LYhXJIhIgwlpsGIRCSKL7PeDw5339PyYPavrqvF5/pDx7JyZz5lZd58zzpl5KwIAAEeQtwAA4LDy
l49rvrEAAI6obdMIAACH//OZD2sAAGwbAACwbQAAwLYBALBtAADAtgEAjvPn87//A7YNAIBtAwAA
tg0AANg2AAC2DQAA2DYAALaNbQMAYNsAAIBtAwAAtg0AgG0DAAC2DQAA2DYAALYNAADYNgAAYNsA
ANg2AABg2wAAgG0DAGDbAACAbQMAALYNAIBtAwDA0bXtt3ZQ6enp6aqqqtQdqqur5+bm1PHV1dXm
5ua0tLTk5GT52dDQsLCw4L+KycnJyspKOgsAsG0AADi+tv306VOR7NLS0pUdysrKRKzn5+flpfr6
eskzMzMj6YcPH0o6Ly9vd0IPAIBtAwDAcbTtc+fOSWJiYkIdV1YtByWdnJws6Z6eHuuJxcXFcnBx
cVHSS0tLkpYj09PTFRUVkl/EvbKycnl5OSUl5a3/IDm3t7c7OjoCO0giHA7rGG7dulVeXi6Kf+XK
levXr6enp2dlZY2OjtLLAIBtAwDAkbftYDAoCbFhdVwS8qu4r6RFglU28eknT56oDBcvXpQjvb29
kpafku7u7s7JyZHE2trazMyMJMrKyiJ/Hdvu6uqS9O3bt+/evatO0Rk6OzuVtQuff/75wsKCJLKz
s+llAMC2AQDgyNt2UlKSrTT5NTk5WRLLy8sFBQV6iPrUqVOvXr169OiRpNWE7KqqKknPzc2JnSsp
v3Hjxubmpq0KISsrS9JbW1vK5sXOdQaVX6U3NjZUWqKilwEA2wYAgCNv20qUxYPVcUnose3IzlD3
d999984776j8J06cUKeIDb948UJ+5ubmypE7d+6oMXIhFArdvXvXZtvK6TVKpq0ZvNIAANg2AAAc
YdtW87YfPHigjo+Pj8uvZ8+etWYOh8N9fX16zLuxsVENdau5HzrPyMjIJ598omXdKs2ZmZnW+Spm
w8a2AQDbBgCAN8S25+fnRY6Liopevnz56tUrSQQCAbUmiaQlz9jYmKSfPHki6ZqaGkkPDQ3pUeqp
qanIf2Z4//rrr1KIJPLz8yP/GTVXE0U6OzslffPmzbm5OUmcPHkS2wYAbBsAAN582xZmZ2erq6tT
dqiqqpJf1fHl5eXGxkY1b0R+nj9/fmVlRY6vra2pmSF6QUCR7IaGhtTU1OTk5BMnTihZHx4elgKV
WIfDYbUmiRypra2V/Ng2AGDbAADwxtr2rtne3l5fX8/NzZUY9EIlAACAbQMAYNtxIBgMpqSk5Ofn
3759m44AAMC2AQCwbQAAwLYBAADbBgDAtgEAANsGAABsGwAA2wYAAGwbAACwbQAAbBsAALBtAADA
tgEAsG0AAMC2AQAA2wYAwLYBAADbBgAAbBsAANsGAABsGwAAsG0AAGwbAACwbQAAwLYBALBtAADA
tgEAIB6f5gAAcDjBtgEA3gTbphEAAA7n5zO2DQCAbQMAALYNAADYNgAAtg0AANg2AABg2wAA2DYA
AGDbAACAbQMAYNsAAIBtAwAAtg0AgG0DAAC2DQAA2DYAALYNAADYNgAAYNsAANg2AABg2wAAgG0D
AGDbAACAbQMAALYNAIBtAwAAtg0AANg2AAC2DQAA2DYAAGDbAADYNgAAYNsAAIBtAwBg2wAAgG0D
AAC2DQBwXD7NAQDgcIJtAwC8CbZNIwAAHM7PZ2wbAADbBgAAbBsAALBtAABsGwAAsG0AAMC2AQCw
bQAAwLYBAADbBgDAtgEAANsGAABsGwAA2wYAAGwbAACwbQAAbBsAALBtAADAtgEAsG0AAMC2AQAA
2wYAwLYBAADbBgAAbBsAANsGAABsGwAAsG0AAGwbAACwbQAAwLYBALDtg2R7e/uoxBCXUA/D9fJ+
AMC2AQAg/ra9R+12nv6Wg13ofnFxsbneu3fvNjU17WsTRY3BkC3WVo1LIYqJiYns7OxQKDQyMuK/
E5395ecdIl0wPDycgLerz74AwLYBAOBY2HYcw3MlHA7n5eWtrq4mpol2kS3WRojjvxpEtaenp2dm
ZrKysuJSu+FV6YKCggLpjoS9XQGOo20DACQYPojjbtuLi4vFxcVVVVUrKyvqoCSqq6uTk5PloJZa
14M+bbumpmZycjKyM/J65swZa7axsTEpMykpqaio6NGjR9avFtdXhYGBgc8//9xWxdLSUmFhYTAY
vH//vjngnp6enJwcOf7gwQM/MWjM2aQ6qSg1NfX27duGEWJzISq83Nxc27nOmOWKKisrQ6HQ9evX
rXGmpKRsb2+/evVKtNu130dHRwOBgJyru9t8w6ATa2trtbW1EoP0pqTVwY6ODumOhPUFnwBwTG2b
RgGAxDsixNG2W1paxM/Ehpubm9VBSQwODkri1q1bFy5cMBz0aduzs7Pl5eVSS2lp6YsXL6zZRK2k
QEmMj48ry4z6qjifNm+NSLx4p1Sks3kF3NnZKZGI3knhfmLQmLNJMw4NDUnJ7e3thjequRBJqEJs
B50xt7W19fb2ykFJWKtramrq7u6W2ycp37XfpSnkLGkZCTgm25b8qu9GRkbkGtVB6Yi6urrE9wUA
tg0AgG0fGdvWY43p6ek6oYRva2srGAwaDvqft3327Nn6+vpLly7ZThRXE0EUtbJOSDC/GggEJAZb
vWlpabYpDV4B62w+Y9CYs2VkZKjq1tfXDW9UcyGS0E8EWg86Y87MzFSNsLa2pg8uLy8XFRVlZ2cv
Li569fvLly+dbeIcy3fadigU0q9K7Soh5UjLJ74vALBtAABs+8jYtj6oxxd3d9DcR9PT03LW5uam
LZu4vppjIIo2MzPj59WkpCQ/742oAfuMQWPOpquIRJvrbCjE7LtRqzt58uTw8PDDhw9Pnz797Nmz
zs7OWNvEULtVyq1dYI0kYX0BgG0DACTiMwjiYttzc3ORnUXW9OBlMBhUI5HhcFiPXLoe9G/b7e3t
FRUV165dc80mJd+8eVM/2Gd+VWr3M7YdNeCYYoiaLTMzUwWwsbER9cvRqxD/tp2RkaEawVqdSKq6
5N7e3nfeeUeqcPbO+vp6ZGeMWUqIybb1mLQVn2Pb+9QXANg2AAC2fQRsu6qqShKPHz/Wk3HPnz8/
Ojoa+essW9eDPm17YWGhtLRUzKyoqMg2b7ugoGBsbEwStsm7IpFer9bX1+uH6jQNDQ2Dg4Pz8/N6
sm/UgH3GoDFnk9ZTzwt++eWXhi9HcyH+bVuqE6WO7DynqEea5X7mu+++k8TQ0FBqampZWZl+nFGf
rh4wlbaSE2Oy7ZaWluXlZUncuXOnvLxcHRwfH5fuSHxfAGDbAADY9pGx7cXFxcLCwtraWjXqGfnP
8hqiONXV1dY1SZwHfc7bFiF78uSJkrNTp05ZT5yampLaxRelZKVZStdSUlK8XhWpbW1ttdW7tLSU
n58fCoW0iEcN2GcMGnM2tWRHZmamiKZhTRJzIf5tW6qTqwsGg319fSLWuhHkrkZKlp/T09NXr17V
Sq1Pl9aTuqQXdHf7tG1pw5qaGilcbpmePn2qDkpHuK5Jsk99gXUAtg0AgG0fMds+ioTD4dzcXPW0
H9y5c6eysvJA+l26QDoiAetta/S4OAC2DQCAbWPb+0gC9pI85LS0tKSlpaWkpJw4cUJN8PCDbbR+
j5w7dy4xe0lquru7+eMFbBsAANvGtgEAANsGAGwb2wYAAGwbAADbxrYBALBtAABsG9sGAABsGwCw
bVrycH96693Lj3kMRwIaCgDbBgBsGzxte48f4z7X245V94uLi831JmBNkqgx7KX1AoGA/xZ2Nqaf
7pP2ScyCIX4aCgCwbQDAtrHtuNl2HMNzJRwO5+Xl6U1S9ruJ4mvbtbW17e3toVBIftbU1OyxCsOr
0j4FBQUJWAwbEwA4GNt+9uyZvhGfn5/fRTUJ+Ov1OQCzFyYnJ/1vOgAA2PaB2Pbi4mJxcXFVVdXK
yoo6KInq6urk5GQ5aN1L0nnQp22LVsrnoSQmJibOnDljzTY2NiZlJiUlFRUVPXr0yPrh7PpqZGcv
SbX9uJWlpaXCwsJgMHj//n1zwD09PTk5OXJc73RojsFQhWS4e/duenq6tbSpqamSkhI5kpGRcevW
LWu9ubm5Gxsbra2tmZmZLS0tthsGyTM6OhoIBOSLQ/eFz40e1U6WUqk0td6tvaOjw3Wjx31qKLQb
IKG2PTQ0pP8CBwcHD+3F7PdHQ2JuGwCwbdiLbYv2bW9viw03Nzerg5JQH90ii3r3PteDPm17dna2
vLxcaiktLX3x4oU1m9ibUtLx8XGRUVshrq+KVmrz1ojEX79+XSrS2bwC7uzslEjEIKVwPzEYqnAt
raCg4OHDh5IYHh4WqdU55ZtRci4vL1dUVMhPaZBnz57Zmk7ilDwStnRKTLYt+VXDjoyMtLe3q4PS
SnV1dYlvKABIhG2fP39eXqqvr5efZ8+eVQenp6flI0b+VlNTU+XGXe195XrQeqMsyN+2fCqlpaVd
uXJFPiPS09OzsrJGR0d1hrt378onmuR59eqVquvzzz+X/IFAQD4sbOLrTGjm5+fllr2kpCSy89hH
cXGx/CoHY62lpqZGvlFSUlKsN/1SYEdHR2AHSaj/7lnz8/YCwLYPxLb1cKZ8uuqEevRta2tL+6Lr
Qf/ztuW7QL4ULl26ZDtRdLCpqUnszTrnwfyqfIpKDLZ65dPYNmvCK2CdzWcMhipcS/Nq56hPE0oe
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
F4lyXafVvJiVfjUSbZ9g57YMkb9O/zMsrqUxZ3Ndq8pJ1IW8DJ0etTq5xRoeHn748OHp06efPXum
tsWIqU3MN3jOfvFzc0VHxNQRIrWvXr1SDxy7Vm39V4BrkH66aRdtchga1uuKvD6RrIW43vAb8mDb
AIBtH3fb3sWKUq7fba5rKPlfoMmPbZsXiVpfX1c3BiIZhpBca5QrNYxt65Vq5bir39si91pcy4ZX
Nte1qrzwKsS/i0hzqWu3Vqen7Mtd1jvvvCNVOJvR2eA+bdu1X5zQEXvsiDNnzpw/f76hocHW+M42
dL1SQzf52WzkkDes9U/e8PkwNzenYrCO9FuHIRjbBgBsG6Krzy5WlNKrRVm/C1zXUPK/QJMf2zYv
EqWeeRIF7+joMITkWmN9fb1+pkrsRAqZn5/XU0VFWdS8R9t0YWc55sW1NOZsrmtVOTEX4t9FpDox
ucjOY156wK+iouK7776TxNDQkHSi3DXZnpNzbXD/87ad/eKEjthjR/T19Ykj9vT0WGtxbUPXK/XZ
Tbtok8PQsNY/eYNtV1VVSeLx48euDxiMj49LOc40tg0A2Da2bf9SiXVFKb1alLUQ1zWU/C/QFPH3
IL9hkSj5/paoTp06pYb6IrEs6yTntra2qvTS0lJ+fr5oiv4yVksoSDlyv2FdCsNZjnlxLY05m3mt
Kp91+XcRqU6uTvWRXgdNGqG0tFRKlp/T09NXr17VJmdocJ+2HbVf6Ii4dMSvv/4qCbVipnVNEmcb
ul6pazf55PA3rPVP3mDbi4uLEoNEq9vWipSg1yGxphO0JsledvpJ8C5BB7Ip0e4qZWMqwLax7Tja
NtdlJRwO5+bm6tuJ48mdO3cqKysP6o3EEluHpCOOScPu/U9ezpUS1JQYa3ovb+bYbHsv24w5z/U5
PWiP1e1fFf4rjWOr3rhxY++z9QGwbaz0qGAbs9wF+7eX5CGnpaUlLS1NGvDEiRNq5kBiGtwGS2wd
ko44Pg27xz/5c+fO6f0jrem9vJljs+29fJqbn0Hevy+eRH4D7a7SmDLLuyrWtegBsG1sGwAADsk3
3Vt72enHmrbtFOU6xOv63VBTUzM5OSmJiYkJtbWP63ZKhn2nJCpbqM5azKdHou2IFnHbRy1qpRG3
zZBcW1WaTq08Lz9tI9+xLtYDgG1j2wAAcBhtexc7/VjTzp2ifI5tyynl5eVScmlpqTJO1+2UvPad
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
2hoOh9PS0nYto1KmWUbNY9u7s+1DfoHO/P6DAcC2AQAADsa2P//8c0kMDg52dHQYFG1hYaG0tFQc
saioSE9rdp57/vz50dHRiGMmsS4nOTlZTfNwrUU92CcGKQWaZbShoUHqnZ+fd523vQvbPvwX6Cw5
ajDYNmDbAAAAB2zbAwMDKSkpp06dUuO4EY9pzfX19U+ePJHE+Pi4ZPY6d2VlpaqqSrywurraukqG
rlokUk7xEkH1YF9aWtqNGzfMMrq0tJSfnx8KhZxLGfqx7aN4gc6SowZzGNZbBGwbAADg2Nm2q4wm
8tyj0u5vzLXokW8AbBsAACBxtq3GShN/7pHgTbrA7u5u/pAA2wYAAEi0bQMAYNsAAMAXH7YNANg2
AAAAtg0A2DYAAAC2DQCAbQMAAGDbAIBtAwAAJMS2k5OTb926RYsAALYNAAAQf9ve2NgoKSmhRQAA
2wYAAIi/bUd2hrf1UZoGALBtAACAeNp2UlISLQIA2DYAAMC+2HZ5efmTJ09oFADAtgEAAOJv27/+
+mtaWhqNAgDYNgAAQPxtu7i4mLFtAMC2AQAA9sW2eTgSALBtAACAfbdttBsAsG0AAIB42vbq6mpq
aqpKX7hwgaYBAGwbAAAgbradkpJy/fp1le7u7qZpAADbBgAAiJttAwBg2wAAANg2AGDbAAAA2DYA
ALYNAADYNq0AANg2AAAAtg0A2DYAAAC2DQCAbQMAAGDbAIBtAwAAYNsAgG0DAABg2wAA2DYAAAC2
DQDYNgAAALYNANg2AAAAtg0AgG0DAABg2wCAbQMAACTOtgEAEgm2DQAAx8u2aQUASOSHDrYNAADY
NgAAtg0AAIBtAwC2DQAAgG0DAGDbAACAbQMAYNsAAADYNgBg2wAAANg2AAC2DQAA2DYAALYNAACA
bQMAtg0AAIBtAwBg2wAAgG0DAGDbAAAA2DYAYNsAAADYNgAAtg0AAIBtAwC2DQAAgG0DALYNAACA
bQMAYNsAAADYNgBg2wAAANg2AGDbAAAA2DYAALYNAACAbQMAtg0AAHDEbXt7e/vwXOeugzlUV/Fm
9xEXi20DAABg2zFQXFzsM4L/C+Wv7Ecw1vKTk5MfPHiwl6uwFlVSUjI9PW27KPMl2wgEAoYq9q9Z
3nIjMZd89+7dpqamxLzXY31DLi8v19TUpKSkSL+0trZubGzsX2yuXe9KIqOKFenK4eFhbBsAACBB
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
e/asdlk9/BwMBqPa9traWkZGRk5OTnp6eiAQePnypc65vr6uygmFQhHLWLU6aB2rdrXtzMxM64wX
ZwbAtgGwbQAAOHS2PT8/n5aWVlRUJGb86tUrSYglW9ck+fLLL4eGhiTR3Nwc1bbb2trkoOTv7++3
TfVub2+/c+eOJFpaWuRgd3e3muGt5m1fvXrVWaYad1dLr3R2dkr65s2bc3Nzkjh58iS2jW0DYNsA
AHDYbVuYnZ2trq5O2aGqqkp+1UUJ9+/fD4VCZWVlKysrEcesDytq+RHJqU4vKSmRX2dmZtSrfX19
qampUr56ojEcDovHqzVGurq6rDXqwIaHhyUkJdaSX61JIkdqa2uto+Z0OrYNgG0DAMDhtW3/qFkf
eXl5sYaEE2PbAIBtAwBg21GoqqpKS0sbGxuL6Sw1ak7XYNsAgG0DAGDbgG0DALYNAADYNmDbANg2
AABg24BtAwC2DQCAbQO2DQDYNgAAYNuAbQNg2wAAgG0Dtg0A2DYAALYN2DYAYNsAAIBtA7YNgG0D
AAC2Ddg2AGDbAADYNmDbAIBtAwAAtg3YNgC2DQAA2DZg2wCAbQMAYNuAbQMAtg0AALEbFYAX2DYA
tg0AAHu1bRoBvN4b2DYAtg0AANg2YNsA2DYAAGDbgG0DALYNAIBtA2DbANg2AABg24BtA2DbAACA
bQO2DQDYNgAAtg2AbQNg2wAAgG0Dtg2AbQMAALYN2DYAYNsAANg2ALYNgG0DAAC2Ddg2ALYNAADY
NmDbAIBtAwBgVDQCYNsA2DYAAGDbgG0DYNsAAIBtA7YNANg2AABg24BtA2DbAABwLGx7e3v7MDfU
oQovMcFg2wDYNgAAxM223/orzlf3O5Li4uJ9uisYGxtLSUlpbW2NS3iJuT8x12JuK2wbANsGAIDD
aNv7JLtx8cu9kJyc/ODBg0Mb3qENBtsGwLYBAGB/bdv56traWm1trfhrTU2NpG35l5aWCgsLg8Hg
/fv31ZGVlZXq6mrJX1VVtbq6qkvr6enJycnRHmwdU///7d1RZJX/H8DxPzPHzGTMZLr46SZzzExk
usjMmMkkMzJdJWOSmS4iXSRJdNFFkkhmMt0kmUkiSZJuZv8kMyOTLiaRTGZm/48evh7nnJ3f+Wmt
+v1fr4uf757zPd/nec7Zj3ePZ+e8evWqq6srHmptbZ2amio/kpLnbn6/eh0/1tXVdXR0PHv2rOQU
0sr5c6y+YMmJVFykxlMrOZiZmZnGxsaenp54evV1anmtKr4d2VP27t37g12utkFtA7DTtT02Nvbh
w4cYPHz4cHx8vGT+8PDwjRs35ufns9QLo6Ojk5OTMYhuPnnyZFrt7NmzGxsbkY9RiiW7aG9vf/r0
aQzu378fvVt+JOXPjUHW5Y8fP067rn6O1RcsP5HyRWo/tfxOY2Y8Gk+MV7L6OrW8VhXfjnh0enr6
x+/tVtugtgHYztouuWm7YmK2tLSkR3fv3l2yWlNT0/r6en5Lc3Nzln1ra2v5dE7T/mnuV3zu4cOH
R0ZGIrVL9l5jbZcvWH4i5YvUfmr5RT5+/FjylK3WqeW1qvh2xKPb8meUahvUNgDbWds1xm5SV1e3
1fyKW8ovzVbcxadPny5dunTs2LH29vbqf6+Zf0p2M0ZU8tzc3D+t7VpejepHUv3Uan81yjdWP7yK
b8d23dWttkFtA7DTtZ0uvlZUfkk45mfXWWN7PFpLQR44cODy5cszMzPv37+vsbYzsaM7d+60tbX9
7Vmsra1VX7CWa9u1n1p+y5cvX7IDaG1trWWd6q9VxbdDbYPaBuBPre2xsbHl5eUY3Lt3r7u7u2T+
0NDQ5OTk27dv0+3OJ06ciG7e3OKm5Py4vr7+69evMWhoaFhYWIgeHR8fr7G229vbZ2dnY7DV3dJp
FzEh0nZiYqL6guUnkg4vzan91PJbzpw5E4NYPI6hlnWqv1YV3w61DWobgD+1tj99+tTf3x+119HR
8e7du5L5S0tL+/bta2lpSR/HsbKy0tvbG/P7+vrKP3CjJHALhcLm9z/4i3retWvX9evXa6ztV69e
FYvFurq62FGW3RXPImvxpqam27dvV1+w/ETS4eU/k6TGU8tvuXXrVqxz5MiR7CL3365T/bWq+HZU
Pwa1DWobgF9Q23i11TaobQDU9h8suyCttgG1DaC28buhtkFtA6C2UdugtgFQ26htQG0DqG1Q26C2
AfhzantbvkgctQ1qG4A/tbb/U2Yb99LZ2ZkNlpeX+/v7C4VCY2PjqVOnsq9o+UkePXrU0dFRX18f
e3/69Gn1f2C4xq+2QW0D8HNrewf20t3dffPmzY2NjbW1tfPnz58+ffon7XFubm7Pnj3Pnz+PcaR2
W1vb/Py8sFbboLYB+I1qu7+//+XLlzF48uTJ8PBwNm1mZqaxsbGnp2dlZSWbFoO+vr76+vre3t78
tyFevXp17969+YvlMSd/V0lTU1M2WFpaKhaLu3btevDgQbbl8+fPAwMDMT+OIcb5Nf/666/sO9ir
zDx27Njdu3fTju7cuTMyMpIWWVxc7OzsjKNNpyDB1TaobQB2urbn5+e7u7ujj/fv3//hw4ds2smT
J2PL5OTk2NhYNm10dDR+jMHU1FQ8mhacnp7O2jotfvTo0XPnzsX2km99j5S/ceNG7C7qPNsSi2d7
fPjw4fj4eFrz7NmzsWb2HexVZka4f/v2La2/urqayj4WiafEIvEPiThyta22QW0DsBO1XfG+7ePH
jw8ODl64cCFN+/jxYwzW1taiaLONzc3NWVXnN8bMdBk7rfb58+fI8UOHDtXV1bW3t6e7OyKF19fX
8wfW0tKSxrt3707rpGlpza1mlpxpqvN4KF2AjyNX22ob1DYAO1HbFSe8fv06OjVdJ85Py/dr9Y3l
i0eXX7t2rVgsbjUh3/2R5lXWrDgzoj92kSbH8eevbVc/WtQ2qG0Adqi2x8fHDx48eOXKlTTty5cv
WS63tramtM0uY6+vr1eM2jSOR/P3bRcKhbS95Np2ukZe8Wjz44ozR0ZGpqam0o+Tk5P5+7bfvHmz
+f1zCdN1cbWttkFtA7DTtb2wsLB///4I646OjnTf9pkzZ7J+nZiYyKadOHFiZmZms+y+7bROfX19
9mF/p0+fvnjxYvR6lG4UfF9fXzZhaGgoFnz79m3+vu3l5eUY3Lt3r7u7u0ptV5wZPd3W1vbixYsY
x39jPDc3l57Y29sbg+fPn+fvCPfLoLZBbQPwE2u7/L7twcHBLFgfP3585MiRbNqtW7cKhUL8mF3k
3vz+mSTRr5HUUc/5zyRJe4mYzi5jr66uRnA3NjbGj4cPH85uAd/8/pkk+/bta2lpSZ80Euv09/fH
mhH66U8qK9Z2xZnh2bNnnZ2dsb2rqyvG+ScuLi4Wi8WBgYF0CmpbbYPaBuAn1vZPmv/7W19fn52d
TTdwo7ZBbQPwy2o73Wn9r3H37t2GhoZ0TR21DWobgF9W26htQG0DoLZR26C2AVDbqG1AbQOobdQ2
oLYBUNuobVDbAKht1DagtgHUNmrbqwFqGwC1jdoGtQ2A2kZtA2obQG2jttU2qG0A1DZqG9Q2AGob
tQ2obQC1DWob1DYAahu1DWobALWN2gbUNsD/YVHBVtQ2qG0AfrS2vQhs9buhtkFtA6C2UdugtgFQ
26htQG0DqG1Q26C2AVDbqG1Q2wCobdQ2oLYB1DaobVDbAKht1DaobQDUNmobUNsAahvUNqhtANQ2
ahvUNgBqG7UNqG0AReVFQG2D2gZAbaO2QW0DoLZR24DaBkBto7ZBbQOgtlHboLYBUNuobUBtA6C2
UdugtgHYiaKCrahtUNsAbJv/whb83wFqGwC1jdoGtQ2A2kZtA2obAAB+E/8DOiU+nN21u+YAAAAA
SUVORK5C" />
</BODY>
</HTML>

View File

@ -0,0 +1,107 @@
<HTML>
<HEAD>
<META name="description"
content="Violet UML Editor cross format document" />
<META name="keywords" content="Violet, UML" />
<META charset="UTF-8" />
<SCRIPT type="text/javascript">
function switchVisibility() {
var obj = document.getElementById("content");
obj.style.display = (obj.style.display == "block") ? "none" : "block";
}
</SCRIPT>
</HEAD>
<BODY>
This file was generated with Violet UML Editor 2.1.0.
&nbsp;&nbsp;(&nbsp;<A href=# onclick="switchVisibility()">View Source</A>&nbsp;/&nbsp;<A href="http://sourceforge.net/projects/violet/files/violetumleditor/" target="_blank">Download Violet</A>&nbsp;)
<BR />
<BR />
<SCRIPT id="content" type="text/xml"><![CDATA[<ObjectDiagramGraph id="1">
<nodes id="2">
<ObjectNode id="3">
<children id="4"/>
<location class="Point2D.Double" id="5" x="410.0" y="40.0"/>
<id id="6" value="72a7fa39-c47c-4be4-8616-28e53dd941c9"/>
<revision>1</revision>
<backgroundColor id="7">
<red>255</red>
<green>255</green>
<blue>255</blue>
<alpha>255</alpha>
</backgroundColor>
<borderColor id="8">
<red>0</red>
<green>0</green>
<blue>0</blue>
<alpha>255</alpha>
</borderColor>
<textColor reference="8"/>
<name id="9" justification="1" size="3" underlined="true">
<text>Importer</text>
</name>
</ObjectNode>
<ObjectNode id="10">
<children id="11"/>
<location class="Point2D.Double" id="12" x="410.0" y="140.0"/>
<id id="13" value="84358792-4b76-43e5-8e54-e861f8d058cf"/>
<revision>1</revision>
<backgroundColor reference="7"/>
<borderColor reference="8"/>
<textColor reference="8"/>
<name id="14" justification="1" size="3" underlined="true">
<text>Raw data format</text>
</name>
</ObjectNode>
<ObjectNode id="15">
<children id="16"/>
<location class="Point2D.Double" id="17" x="410.0" y="240.0"/>
<id id="18" value="00422f37-250b-4969-91a6-48bcd052e792"/>
<revision>1</revision>
<backgroundColor reference="7"/>
<borderColor reference="8"/>
<textColor reference="8"/>
<name id="19" justification="1" size="3" underlined="true">
<text>Postproce</text>
</name>
</ObjectNode>
</nodes>
<edges id="20"/>
</ObjectDiagramGraph>]]></SCRIPT>
<BR />
<BR />
<IMG alt="embedded diagram image" src="data:image/png;base64,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" />
</BODY>
</HTML>

View File

@ -67,7 +67,8 @@ class IOStream;
* to the importer library. If you implement this interface, you also want to * to the importer library. If you implement this interface, you also want to
* supply a custom implementation for IOStream. * supply a custom implementation for IOStream.
* *
* @see Importer::SetIOHandler() */ * @see Importer::SetIOHandler()
*/
class ASSIMP_API IOSystem class ASSIMP_API IOSystem
#ifndef SWIG #ifndef SWIG
: public Intern::AllocateFromAssimpHeap : public Intern::AllocateFromAssimpHeap

View File

@ -255,7 +255,6 @@ struct aiNodeAnim
* scaling and one position key. */ * scaling and one position key. */
C_STRUCT aiQuatKey* mRotationKeys; C_STRUCT aiQuatKey* mRotationKeys;
/** The number of scaling keys */ /** The number of scaling keys */
unsigned int mNumScalingKeys; unsigned int mNumScalingKeys;
@ -266,7 +265,6 @@ struct aiNodeAnim
* position and one rotation key.*/ * position and one rotation key.*/
C_STRUCT aiVectorKey* mScalingKeys; C_STRUCT aiVectorKey* mScalingKeys;
/** Defines how the animation behaves before the first /** Defines how the animation behaves before the first
* key is encountered. * key is encountered.
* *

View File

@ -60,9 +60,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
extern "C" { extern "C" {
#endif #endif
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** A node in the imported hierarchy. /**
* A node in the imported hierarchy.
* *
* Each node has name, a parent node (except for the root node), * Each node has name, a parent node (except for the root node),
* a transformation relative to its parent and possibly several child nodes. * a transformation relative to its parent and possibly several child nodes.
@ -278,7 +278,6 @@ struct aiNode
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct aiScene struct aiScene
{ {
/** Any combination of the AI_SCENE_FLAGS_XXX flags. By default /** Any combination of the AI_SCENE_FLAGS_XXX flags. By default
* this value is 0, no flags are set. Most applications will * this value is 0, no flags are set. Most applications will
* want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE * want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE
@ -286,7 +285,6 @@ struct aiScene
*/ */
unsigned int mFlags; unsigned int mFlags;
/** The root node of the hierarchy. /** The root node of the hierarchy.
* *
* There will always be at least the root node if the import * There will always be at least the root node if the import
@ -296,8 +294,6 @@ struct aiScene
*/ */
C_STRUCT aiNode* mRootNode; C_STRUCT aiNode* mRootNode;
/** The number of meshes in the scene. */ /** The number of meshes in the scene. */
unsigned int mNumMeshes; unsigned int mNumMeshes;
@ -310,8 +306,6 @@ struct aiScene
*/ */
C_STRUCT aiMesh** mMeshes; C_STRUCT aiMesh** mMeshes;
/** The number of materials in the scene. */ /** The number of materials in the scene. */
unsigned int mNumMaterials; unsigned int mNumMaterials;
@ -324,8 +318,6 @@ struct aiScene
*/ */
C_STRUCT aiMaterial** mMaterials; C_STRUCT aiMaterial** mMaterials;
/** The number of animations in the scene. */ /** The number of animations in the scene. */
unsigned int mNumAnimations; unsigned int mNumAnimations;
@ -336,8 +328,6 @@ struct aiScene
*/ */
C_STRUCT aiAnimation** mAnimations; C_STRUCT aiAnimation** mAnimations;
/** The number of textures embedded into the file */ /** The number of textures embedded into the file */
unsigned int mNumTextures; unsigned int mNumTextures;
@ -349,7 +339,6 @@ struct aiScene
*/ */
C_STRUCT aiTexture** mTextures; C_STRUCT aiTexture** mTextures;
/** The number of light sources in the scene. Light sources /** The number of light sources in the scene. Light sources
* are fully optional, in most cases this attribute will be 0 * are fully optional, in most cases this attribute will be 0
*/ */
@ -362,7 +351,6 @@ struct aiScene
*/ */
C_STRUCT aiLight** mLights; C_STRUCT aiLight** mLights;
/** The number of cameras in the scene. Cameras /** The number of cameras in the scene. Cameras
* are fully optional, in most cases this attribute will be 0 * are fully optional, in most cases this attribute will be 0
*/ */
@ -387,33 +375,38 @@ struct aiScene
//! Check whether the scene contains meshes //! Check whether the scene contains meshes
//! Unless no special scene flags are set this will always be true. //! Unless no special scene flags are set this will always be true.
inline bool HasMeshes() const inline bool HasMeshes() const {
{ return mMeshes != NULL && mNumMeshes > 0; } return mMeshes != NULL && mNumMeshes > 0;
}
//! Check whether the scene contains materials //! Check whether the scene contains materials
//! Unless no special scene flags are set this will always be true. //! Unless no special scene flags are set this will always be true.
inline bool HasMaterials() const inline bool HasMaterials() const {
{ return mMaterials != NULL && mNumMaterials > 0; } return mMaterials != NULL && mNumMaterials > 0;
}
//! Check whether the scene contains lights //! Check whether the scene contains lights
inline bool HasLights() const inline bool HasLights() const {
{ return mLights != NULL && mNumLights > 0; } return mLights != NULL && mNumLights > 0;
}
//! Check whether the scene contains textures //! Check whether the scene contains textures
inline bool HasTextures() const inline bool HasTextures() const {
{ return mTextures != NULL && mNumTextures > 0; } return mTextures != NULL && mNumTextures > 0;
}
//! Check whether the scene contains cameras //! Check whether the scene contains cameras
inline bool HasCameras() const inline bool HasCameras() const {
{ return mCameras != NULL && mNumCameras > 0; } return mCameras != NULL && mNumCameras > 0;
}
//! Check whether the scene contains animations //! Check whether the scene contains animations
inline bool HasAnimations() const inline bool HasAnimations() const {
{ return mAnimations != NULL && mNumAnimations > 0; } return mAnimations != NULL && mNumAnimations > 0;
}
#endif // __cplusplus #endif // __cplusplus
/** Internal data, do not touch */ /** Internal data, do not touch */
#ifdef __cplusplus #ifdef __cplusplus
void* mPrivate; void* mPrivate;

View File

@ -0,0 +1,254 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#include "ModelDiffer.h"
#include <assimp/scene.h>
#include <sstream>
using namespace Assimp;
ModelDiffer::ModelDiffer() {
// empty
}
ModelDiffer::~ModelDiffer() {
// empty
}
bool ModelDiffer::isEqual( aiScene *expected, aiScene *toCompare ) {
if ( expected == toCompare ) {
return true;
}
if ( nullptr == expected ) {
return false;
}
if ( nullptr == toCompare ) {
return false;
}
if ( expected->mNumMeshes != toCompare->mNumMeshes ) {
std::stringstream stream;
stream << "Number of meshes not equal ( expected: " << expected->mNumMeshes << ", found : " << toCompare->mNumMeshes << " )\n";
addDiff( stream.str() );
}
for ( unsigned int i = 0; i < expected->mNumMeshes; i++ ) {
aiMesh *expMesh( expected->mMeshes[ i ] );
aiMesh *toCompMesh( toCompare->mMeshes[ i ] );
compareMesh( expMesh, toCompMesh );
}
}
void ModelDiffer::showReport() {
if ( m_diffs.empty() ) {
return;
}
for ( std::vector<std::string>::iterator it = m_diffs.begin(); it != m_diffs.end(); it++ ) {
std::cout << *it << "\n";
}
std::cout << std::endl;
}
void ModelDiffer::reset() {
m_diffs.resize( 0 );
}
void ModelDiffer::addDiff( const std::string &diff ) {
if ( diff.empty() ) {
return;
}
m_diffs.push_back( diff );
}
static std::string dumpVector3( const aiVector3D &toDump ) {
std::stringstream stream;
stream << "( " << toDump.x << ", " << toDump.y << ", " << toDump.z << ")";
return stream.str();
}
static std::string dumpColor4D( const aiColor4D &toDump ) {
std::stringstream stream;
stream << "( " << toDump.r << ", " << toDump.g << ", " << toDump.b << ", " << toDump.a << ")";
return stream.str();
}
bool ModelDiffer::compareMesh( aiMesh *expected, aiMesh *toCompare ) {
if ( expected == toCompare ) {
return true;
}
if ( nullptr == expected || nullptr == toCompare ) {
return false;
}
if ( expected->mName != toCompare->mName ) {
std::stringstream stream;
stream << "Mesh name not equal ( expected: " << expected->mName.C_Str() << ", found : " << toCompare->mName.C_Str() << " )\n";
addDiff( stream.str() );
}
if ( expected->mNumVertices != toCompare->mNumVertices ) {
std::stringstream stream;
stream << "Number of vertices not equal ( expected: " << expected->mNumVertices << ", found : " << toCompare->mNumVertices << " )\n";
addDiff( stream.str() );
return false;
}
// positions
if ( expected->HasPositions() != toCompare->HasPositions() ) {
addDiff( "Expected are vertices, toCompare does not have any." );
return false;
}
bool vertEqual( true );
for ( unsigned int i = 0; i < expected->mNumVertices; i++ ) {
aiVector3D &expVert( expected->mVertices[ i ] );
aiVector3D &toCompVert( toCompare->mVertices[ i ] );
if ( expVert != toCompVert ) {
std::stringstream stream;
stream << "Vertex not equal ( expected: " << dumpVector3( expVert ) << ", found: " << dumpVector3( toCompVert ) << "\n";
addDiff( stream.str() );
vertEqual = false;
}
}
if ( !vertEqual ) {
return false;
}
// normals
if ( expected->HasNormals() != toCompare->HasNormals() ) {
addDiff( "Expected are normals, toCompare does not have any." );
return false;
}
bool normalEqual( true );
for ( unsigned int i = 0; i < expected->mNumVertices; i++ ) {
aiVector3D &expNormal( expected->mNormals[ i ] );
aiVector3D &toCompNormal( toCompare->mNormals[ i ] );
if ( expNormal != toCompNormal ) {
std::stringstream stream;
stream << "Normal not equal ( expected: " << dumpVector3( expNormal ) << ", found: " << dumpVector3( toCompNormal ) << "\n";
addDiff( stream.str() );
normalEqual = false;
}
}
if ( !normalEqual ) {
return false;
}
// vertex colors
bool vertColEqual( true );
for ( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++ ) {
if ( expected->HasVertexColors(a) != toCompare->HasVertexColors(a) ) {
addDiff( "Expected are normals, toCompare does not have any." );
return false;
}
for ( unsigned int i = 0; i < expected->mNumVertices; i++ ) {
aiColor4D &expColor4D( expected->mColors[ a ][ i ] );
aiColor4D &toCompColor4D( toCompare->mColors[ a ][ i ] );
if ( expColor4D != toCompColor4D ) {
std::stringstream stream;
stream << "Color4D not equal ( expected: " << dumpColor4D( expColor4D ) << ", found: " << dumpColor4D( toCompColor4D ) << "\n";
addDiff( stream.str() );
vertColEqual = false;
}
}
if ( !vertColEqual ) {
return false;
}
}
// texture coords
bool texCoordsEqual( true );
for ( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++ ) {
if ( expected->HasTextureCoords( a ) != toCompare->HasTextureCoords( a ) ) {
addDiff( "Expected are texture coords, toCompare does not have any." );
return false;
}
for ( unsigned int i = 0; i < expected->mNumVertices; i++ ) {
aiVector3D &expTexCoord( expected->mTextureCoords[ a ][ i ] );
aiVector3D &toCompTexCoord( toCompare->mTextureCoords[ a ][ i ] );
if ( expTexCoord != toCompTexCoord ) {
std::stringstream stream;
stream << "Texture coords not equal ( expected: " << dumpVector3( expTexCoord ) << ", found: " << dumpVector3( toCompTexCoord ) << "\n";
addDiff( stream.str() );
vertColEqual = false;
}
}
if ( !vertColEqual ) {
return false;
}
}
// tangents and bi-tangents
if ( expected->HasTangentsAndBitangents() != toCompare->HasTangentsAndBitangents() ) {
addDiff( "Expected are tangents and bi-tangents, toCompare does not have any." );
return false;
}
bool tangentsEqual( true );
for ( unsigned int i = 0; i < expected->mNumVertices; i++ ) {
aiVector3D &expTangents( expected->mTangents[ i ] );
aiVector3D &toCompTangents( toCompare->mTangents[ i ] );
if ( expTangents != toCompTangents ) {
std::stringstream stream;
stream << "Tangents not equal ( expected: " << dumpVector3( expTangents ) << ", found: " << dumpVector3( toCompTangents ) << "\n";
addDiff( stream.str() );
tangentsEqual = false;
}
aiVector3D &expBiTangents( expected->mBitangents[ i ] );
aiVector3D &toCompBiTangents( toCompare->mBitangents[ i ] );
if ( expBiTangents != toCompBiTangents ) {
std::stringstream stream;
stream << "Tangents not equal ( expected: " << dumpVector3( expBiTangents ) << ", found: " << dumpVector3( toCompBiTangents ) << "\n";
addDiff( stream.str() );
tangentsEqual = false;
}
}
if ( !tangentsEqual ) {
return false;
}
return true;
}

View File

@ -0,0 +1,65 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#pragma once
#include "UnitTestPCH.h"
#include <fast_atof.h>
#include <vector>
#include <string>
struct aiScene;
struct aiMesh;
class ModelDiffer {
public:
ModelDiffer();
~ModelDiffer();
bool isEqual( aiScene *expected, aiScene *toCompare );
void showReport();
void reset();
private:
void addDiff( const std::string &diff );
bool compareMesh( aiMesh *expected, aiMesh *toCompare );
private:
std::vector<std::string> m_diffs;
};