/usr/share/doc/libassimp-doc/apiref/extend.html is in libassimp-doc 3.2~dfsg-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.9.1"/>
<title>Assimp: Extending the Library</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td style="padding-left: 0.5em;">
<div id="projectname">Assimp
 <span id="projectnumber">v3.1.1 (June 2014)</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.9.1 -->
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main Page</span></a></li>
<li class="current"><a href="pages.html"><span>Related Pages</span></a></li>
<li><a href="namespaces.html"><span>Namespaces</span></a></li>
<li><a href="annotated.html"><span>Classes</span></a></li>
<li><a href="files.html"><span>Files</span></a></li>
</ul>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">Extending the Library </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h1><a class="anchor" id="General"></a>
Overview</h1>
<p>Or - how to write your own loaders. It's easy. You just need to implement the <a class="el" href="class_assimp_1_1_base_importer.html" title="FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface for all importer worker classe...">Assimp::BaseImporter</a> class, which defines a few abstract methods, register your loader, test it carefully and provide test models for it.</p>
<p>OK, that sounds too easy :-). The whole procedure for a new loader merely looks like this:</p>
<ul>
<li>
Create a header (<code><em>FormatName</em>Importer.h</code>) and a unit (<code><em>FormatName</em>Importer.cpp</code>) in the <code><root>/code/</code> directory </li>
<li>
Add them to the following workspaces: vc8 and vc9 (the files are in the workspaces directory), CMAKE (code/CMakeLists.txt, create a new source group for your importer and put them also to ADD_LIBRARY( assimp SHARED)) </li>
<li>
Include <em>AssimpPCH.h</em> - this is the PCH file, and it includes already most Assimp-internal stuff. </li>
<li>
<p class="startli">Open Importer.cpp and include your header just below the <em>(include_new_importers_here)</em> line, guarded by a #define </p><div class="fragment"><div class="line"><span class="preprocessor">#if (!defined assimp_BUILD_NO_FormatName_IMPORTER)</span></div>
<div class="line"> ...</div>
<div class="line">#endif</div>
</div><!-- fragment --><p> Wrap the same guard around your .cpp!</p>
<p class="endli"></p>
</li>
<li>
Now advance to the <em>(register_new_importers_here)</em> line in the Importer.cpp and register your importer there - just like all the others do. </li>
<li>
Setup a suitable test environment (i.e. use AssimpView or your own application), make sure to enable the <a class="el" href="postprocess_8h.html#a64795260b95f5a4b3f3dc1be4f52e410ae420ce22fbbac9d0fd21fd92f2b630fa">aiProcess_ValidateDataStructure</a> flag and enable verbose logging. That is, simply call before you import anything: <div class="fragment"><div class="line">DefaultLogger::create(<span class="stringliteral">"AssimpLog.txt"</span>,Logger::VERBOSE)</div>
</div><!-- fragment --> </li>
<li>
Implement the <a class="el" href="class_assimp_1_1_base_importer.html#a13588d3396ba5b7ed1f1cb46e0945cfd" title="Returns whether the class can handle the format of the given file. ">Assimp::BaseImporter::CanRead()</a>, <a class="el" href="class_assimp_1_1_base_importer.html#ac67d9f5ceb26353d27d6be06cccad398" title="Imports the given file into the given scene structure. ">Assimp::BaseImporter::InternReadFile()</a> and <a class="el" href="class_assimp_1_1_base_importer.html#a7a658f1192a37e336ba98fe701918b31" title="Called by #Importer::GetExtensionList for each loaded importer. ">Assimp::BaseImporter::GetExtensionList()</a>. Just copy'n'paste the template from Appendix A and adapt it for your needs. </li>
<li>
For error handling, throw a dynamic allocated ImportErrorException (see Appendix A) for critical errors, and log errors, warnings, infos and debuginfos with DefaultLogger::get()->[error, warn, debug, info]. </li>
<li>
Make sure that your loader compiles against all build configurations on all supported platforms. This includes <em>-noboost</em>! To avoid problems, see the boost section on this page for a list of all 'allowed' boost classes (again, this grew historically when we had to accept that boost is not THAT widely spread that one could rely on it being available everywhere). </li>
<li>
Provide some <em>free</em> test models in <code><root>/test/models/<FormatName>/</code> and credit their authors. Test files for a file format shouldn't be too large (<em>~500 KiB in total</em>), and not too repetive. Try to cover all format features with test data. </li>
<li>
Done! Please, share your loader that everyone can profit from it! </li>
</ul>
<h1><a class="anchor" id="properties"></a>
Properties</h1>
<p>You can use properties to chance the behavior of you importer. In order to do so, you have to overide BaseImporter::SetupProperties, and specify you custom properties in <a class="el" href="config_8h.html" title="Defines constants for configurable properties for the library. ">config.h</a>. Just have a look to the other AI_CONFIG_IMPORT_* defines and you will understand, how it works.</p>
<p>The properties can be set with Importer::SetProperty***() and can be accessed in your SetupProperties function with Importer::GetProperty***(). You can store the properties as a member variable of your importer, they are thread safe.</p>
<h1><a class="anchor" id="tnote"></a>
Notes for text importers</h1>
<ul>
<li>
Try to make your parser as flexible as possible. Don't rely on particular layout, whitespace/tab style, except if the file format has a strict definition, in which case you should always warn about spec violations. But the general rule of thumb is <em>be strict in what you write and tolerant in what you accept</em>. </li>
<li>
Call <a class="el" href="class_assimp_1_1_base_importer.html#afc318aa0eb85b73f501156a50f3eb703" title="An utility for all text file loaders. ">Assimp::BaseImporter::ConvertToUTF8()</a> before you parse anything to convert foreign encodings to UTF-8. That's not necessary for XML importers, which must use the provided IrrXML for reading. </li>
</ul>
<h1><a class="anchor" id="bnote"></a>
Notes for binary importers</h1>
<ul>
<li>
Take care of endianess issues! <a class="el" href="namespace_assimp.html" title="Assimp's CPP-API and all internal APIs. ">Assimp</a> importers mostly support big-endian platforms, which define the <code>AI_BUILD_BIG_ENDIAN</code> constant. See the next section for a list of utilities to simplify this task. </li>
<li>
Don't trust the input data! Check all offsets! </li>
</ul>
<h1><a class="anchor" id="util"></a>
Utilities</h1>
<p>Mixed stuff for internal use by loaders, mostly documented (most of them are already included by <em>AssimpPCH.h</em>): </p><ul>
<li>
<b>ByteSwapper</b> (<em>ByteSwapper.h</em>) - manual byte swapping stuff for binary loaders. </li>
<li>
<b>StreamReader</b> (<em>StreamReader.h</em>) - safe, endianess-correct, binary reading. </li>
<li>
<b>IrrXML</b> (<em>irrXMLWrapper.h</em>) - for XML-parsing (SAX. </li>
<li>
<b>CommentRemover</b> (<em>RemoveComments.h</em>) - remove single-line and multi-line comments from a text file. </li>
<li>
fast_atof, strtoul10, strtoul16, SkipSpaceAndLineEnd, SkipToNextToken .. large family of low-level parsing functions, mostly declared in <em>fast_atof.h</em>, <em>StringComparison.h</em> and <em>ParsingUtils.h</em> (a collection that grew historically, so don't expect perfect organization). </li>
<li>
<b>ComputeNormalsWithSmoothingsGroups()</b> (<em>SmoothingGroups.h</em>) - Computes normal vectors from plain old smoothing groups. </li>
<li>
<b>SkeletonMeshBuilder</b> (<em>SkeletonMeshBuilder.h</em>) - generate a dummy mesh from a given (animation) skeleton. </li>
<li>
<b>StandardShapes</b> (<em>StandardShapes.h</em>) - generate meshes for standard solids, such as platonic primitives, cylinders or spheres. </li>
<li>
<b>BatchLoader</b> (<em><a class="el" href="_base_importer_8h.html">BaseImporter.h</a></em>) - manage imports from external files. Useful for file formats which spread their data across multiple files. </li>
<li>
<b>SceneCombiner</b> (<em>SceneCombiner.h</em>) - exhaustive toolset to merge multiple scenes. Useful for file formats which spread their data across multiple files. </li>
</ul>
<h1><a class="anchor" id="mat"></a>
Filling materials</h1>
<p>The required definitions zo set/remove/query keys in <a class="el" href="structai_material.html" title="Data structure for a material. ">aiMaterial</a> structures are declared in <em>MaterialSystem.h</em>, in a <a class="el" href="structai_material.html" title="Data structure for a material. ">aiMaterial</a> derivate called <a class="el" href="structai_material.html" title="Data structure for a material. ">aiMaterial</a>. The header is included by AssimpPCH.h, so you don't need to bother.</p>
<div class="fragment"><div class="line"><a class="code" href="structai_material.html">aiMaterial</a>* mat = <span class="keyword">new</span> <a class="code" href="structai_material.html">aiMaterial</a>();</div>
<div class="line"></div>
<div class="line"><span class="keyword">const</span> <span class="keywordtype">float</span> spec = 16.f;</div>
<div class="line">mat-><a class="code" href="structai_material.html#a0432dbdfd97ffe71838daf967a6b087e">AddProperty</a>(&spec, 1, <a class="code" href="material_8h.html#aeb1edba2c1e099a0a7055a82cabc9e87">AI_MATKEY_SHININESS</a>);</div>
<div class="line"></div>
<div class="line"><span class="comment">//set the name of the material:</span></div>
<div class="line">NewMaterial->AddProperty(&<a class="code" href="structai_string.html">aiString</a>(MaterialName.c_str()), <a class="code" href="material_8h.html#a204a0a39264125e160bd8fb2117f06e9">AI_MATKEY_NAME</a>);<span class="comment">//MaterialName is a std::string</span></div>
<div class="line"></div>
<div class="line"><span class="comment">//set the first diffuse texture</span></div>
<div class="line">NewMaterial->AddProperty(&<a class="code" href="structai_string.html">aiString</a>(Texturename.c_str()), <a class="code" href="material_8h.html#a18c395e1dd733f94d36353956a12776f">AI_MATKEY_TEXTURE</a>(<a class="code" href="material_8h.html#a7dd415ff703a2cc53d1c22ddbbd7dde0a3027af56603d5babd7e2efcf5ed1debd">aiTextureType_DIFFUSE</a>, 0));<span class="comment">//again, Texturename is a std::string</span></div>
</div><!-- fragment --><h1><a class="anchor" id="boost"></a>
Boost</h1>
<p>The boost whitelist: </p><ul>
<li>
<em>boost.scoped_ptr</em> </li>
<li>
<em>boost.scoped_array</em> </li>
<li>
<em>boost.format</em> </li>
<li>
<em>boost.random</em> </li>
<li>
<em>boost.common_factor</em> </li>
<li>
<em>boost.foreach</em> </li>
<li>
<em>boost.tuple</em> </li>
</ul>
<p>(if you happen to need something else, i.e. boost::thread, make this an optional feature. <code>assimp_BUILD_BOOST_WORKAROUND</code> is defined for <em>-noboost</em> builds)</p>
<h1><a class="anchor" id="appa"></a>
Appendix A - Template for BaseImporter's abstract methods</h1>
<div class="fragment"><div class="line"><span class="comment">// -------------------------------------------------------------------------------</span></div>
<div class="line"><span class="comment">// Returns whether the class can handle the format of the given file.</span></div>
<div class="line"><span class="keywordtype">bool</span> xxxxImporter::CanRead( <span class="keyword">const</span> std::string& pFile, IOSystem* pIOHandler,</div>
<div class="line"> <span class="keywordtype">bool</span> checkSig)<span class="keyword"> const</span></div>
<div class="line"><span class="keyword"></span>{</div>
<div class="line"> <span class="keyword">const</span> std::string extension = GetExtension(pFile);</div>
<div class="line"> <span class="keywordflow">if</span>(extension == <span class="stringliteral">"xxxx"</span>) {</div>
<div class="line"> <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">if</span> (!extension.length() || checkSig) {</div>
<div class="line"> <span class="comment">// no extension given, or we're called a second time because no</span></div>
<div class="line"> <span class="comment">// suitable loader was found yet. This means, we're trying to open</span></div>
<div class="line"> <span class="comment">// the file and look for and hints to identify the file format.</span></div>
<div class="line"> <span class="comment">// #Assimp::BaseImporter provides some utilities:</span></div>
<div class="line"> <span class="comment">//</span></div>
<div class="line"> <span class="comment">// #Assimp::BaseImporter::SearchFileHeaderForToken - for text files.</span></div>
<div class="line"> <span class="comment">// It reads the first lines of the file and does a substring check</span></div>
<div class="line"> <span class="comment">// against a given list of 'magic' strings.</span></div>
<div class="line"> <span class="comment">//</span></div>
<div class="line"> <span class="comment">// #Assimp::BaseImporter::CheckMagicToken - for binary files. It goes</span></div>
<div class="line"> <span class="comment">// to a particular offset in the file and and compares the next words</span></div>
<div class="line"> <span class="comment">// against a given list of 'magic' tokens.</span></div>
<div class="line"></div>
<div class="line"> <span class="comment">// These checks MUST be done (even if !checkSig) if the file extension</span></div>
<div class="line"> <span class="comment">// is not exclusive to your format. For example, .xml is very common</span></div>
<div class="line"> <span class="comment">// and (co)used by many formats.</span></div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
<div class="line">}</div>
<div class="line"></div>
<div class="line"><span class="comment">// -------------------------------------------------------------------------------</span></div>
<div class="line"><span class="comment">// Get list of file extensions handled by this loader</span></div>
<div class="line"><span class="keywordtype">void</span> xxxxImporter::GetExtensionList(std::set<std::string>& extensions)</div>
<div class="line">{</div>
<div class="line"> extensions.insert(<span class="stringliteral">"xxx"</span>);</div>
<div class="line">}</div>
<div class="line"></div>
<div class="line"><span class="comment">// -------------------------------------------------------------------------------</span></div>
<div class="line"><span class="keywordtype">void</span> xxxxImporter::InternReadFile( <span class="keyword">const</span> std::string& pFile,</div>
<div class="line"> <a class="code" href="structai_scene.html">aiScene</a>* pScene, IOSystem* pIOHandler)</div>
<div class="line">{</div>
<div class="line"> boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, <span class="stringliteral">"rb"</span>));</div>
<div class="line"></div>
<div class="line"> <span class="comment">// Check whether we can read from the file</span></div>
<div class="line"> <span class="keywordflow">if</span>( file.get() == NULL) {</div>
<div class="line"> <span class="keywordflow">throw</span> DeadlyImportError( <span class="stringliteral">"Failed to open xxxx file "</span> + pFile + <span class="stringliteral">"."</span>);</div>
<div class="line"> }</div>
<div class="line"></div>
<div class="line"> <span class="comment">// Your task: fill pScene</span></div>
<div class="line"> <span class="comment">// Throw a ImportErrorException with a meaningful (!) error message if</span></div>
<div class="line"> <span class="comment">// something goes wrong.</span></div>
<div class="line">}</div>
</div><!-- fragment --> </div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Tue Dec 15 2015 23:19:13 for Assimp by  <a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.9.1
</small></address>
</body>
</html>
|