nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** @file Declares a helper class, "SceneCombiner" providing various nuclear@0: * utilities to merge scenes. nuclear@0: */ nuclear@0: #ifndef AI_SCENE_COMBINER_H_INC nuclear@0: #define AI_SCENE_COMBINER_H_INC nuclear@0: nuclear@0: #include "assimp/ai_assert.h" nuclear@0: nuclear@0: namespace Assimp { nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** \brief Helper data structure for SceneCombiner. nuclear@0: * nuclear@0: * Describes to which node a scene must be attached to. nuclear@0: */ nuclear@0: struct AttachmentInfo nuclear@0: { nuclear@0: AttachmentInfo() nuclear@0: : scene (NULL) nuclear@0: , attachToNode (NULL) nuclear@0: {} nuclear@0: nuclear@0: AttachmentInfo(aiScene* _scene, aiNode* _attachToNode) nuclear@0: : scene (_scene) nuclear@0: , attachToNode (_attachToNode) nuclear@0: {} nuclear@0: nuclear@0: aiScene* scene; nuclear@0: aiNode* attachToNode; nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: struct NodeAttachmentInfo nuclear@0: { nuclear@0: NodeAttachmentInfo() nuclear@0: : node (NULL) nuclear@0: , attachToNode (NULL) nuclear@0: , resolved (false) nuclear@0: , src_idx (SIZE_MAX) nuclear@0: {} nuclear@0: nuclear@0: NodeAttachmentInfo(aiNode* _scene, aiNode* _attachToNode,size_t idx) nuclear@0: : node (_scene) nuclear@0: , attachToNode (_attachToNode) nuclear@0: , resolved (false) nuclear@0: , src_idx (idx) nuclear@0: {} nuclear@0: nuclear@0: aiNode* node; nuclear@0: aiNode* attachToNode; nuclear@0: bool resolved; nuclear@0: size_t src_idx; nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES nuclear@0: * Generate unique names for all named scene items nuclear@0: */ nuclear@0: #define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES 0x1 nuclear@0: nuclear@0: /** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES nuclear@0: * Generate unique names for materials, too. nuclear@0: * This is not absolutely required to pass the validation. nuclear@0: */ nuclear@0: #define AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES 0x2 nuclear@0: nuclear@0: /** @def AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY nuclear@0: * Use deep copies of duplicate scenes nuclear@0: */ nuclear@0: #define AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY 0x4 nuclear@0: nuclear@0: /** @def AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS nuclear@0: * If attachment nodes are not found in the given master scene, nuclear@0: * search the other imported scenes for them in an any order. nuclear@0: */ nuclear@0: #define AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS 0x8 nuclear@0: nuclear@0: /** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY nuclear@0: * Can be combined with AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES. nuclear@0: * Unique names are generated, but only if this is absolutely nuclear@0: * required to avoid name conflicts. nuclear@0: */ nuclear@0: #define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10 nuclear@0: nuclear@0: nuclear@0: typedef std::pair BoneSrcIndex; nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** @brief Helper data structure for SceneCombiner::MergeBones. nuclear@0: */ nuclear@0: struct BoneWithHash : public std::pair { nuclear@0: std::vector pSrcBones; nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** @brief Utility for SceneCombiner nuclear@0: */ nuclear@0: struct SceneHelper nuclear@0: { nuclear@0: SceneHelper () nuclear@0: : scene (NULL) nuclear@0: , idlen (0) nuclear@0: { nuclear@0: id[0] = 0; nuclear@0: } nuclear@0: nuclear@0: SceneHelper (aiScene* _scene) nuclear@0: : scene (_scene) nuclear@0: , idlen (0) nuclear@0: { nuclear@0: id[0] = 0; nuclear@0: } nuclear@0: nuclear@0: AI_FORCE_INLINE aiScene* operator-> () const nuclear@0: { nuclear@0: return scene; nuclear@0: } nuclear@0: nuclear@0: // scene we're working on nuclear@0: aiScene* scene; nuclear@0: nuclear@0: // prefix to be added to all identifiers in the scene ... nuclear@0: char id [32]; nuclear@0: nuclear@0: // and its strlen() nuclear@0: unsigned int idlen; nuclear@0: nuclear@0: // hash table to quickly check whether a name is contained in the scene nuclear@0: std::set hashes; nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** \brief Static helper class providing various utilities to merge two nuclear@0: * scenes. It is intended as internal utility and NOT for use by nuclear@0: * applications. nuclear@0: * nuclear@0: * The class is currently being used by various postprocessing steps nuclear@0: * and loaders (ie. LWS). nuclear@0: */ nuclear@0: class SceneCombiner nuclear@0: { nuclear@0: // class cannot be instanced nuclear@0: SceneCombiner() {} nuclear@0: nuclear@0: public: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Merges two or more scenes. nuclear@0: * nuclear@0: * @param dest Receives a pointer to the destination scene. If the nuclear@0: * pointer doesn't point to NULL when the function is called, the nuclear@0: * existing scene is cleared and refilled. nuclear@0: * @param src Non-empty list of scenes to be merged. The function nuclear@0: * deletes the input scenes afterwards. There may be duplicate scenes. nuclear@0: * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above nuclear@0: */ nuclear@0: static void MergeScenes(aiScene** dest,std::vector& src, nuclear@0: unsigned int flags = 0); nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Merges two or more scenes and attaches all sceenes to a specific nuclear@0: * position in the node graph of the masteer scene. nuclear@0: * nuclear@0: * @param dest Receives a pointer to the destination scene. If the nuclear@0: * pointer doesn't point to NULL when the function is called, the nuclear@0: * existing scene is cleared and refilled. nuclear@0: * @param master Master scene. It will be deleted afterwards. All nuclear@0: * other scenes will be inserted in its node graph. nuclear@0: * @param src Non-empty list of scenes to be merged along with their nuclear@0: * corresponding attachment points in the master scene. The function nuclear@0: * deletes the input scenes afterwards. There may be duplicate scenes. nuclear@0: * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above nuclear@0: */ nuclear@0: static void MergeScenes(aiScene** dest, aiScene* master, nuclear@0: std::vector& src, nuclear@0: unsigned int flags = 0); nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Merges two or more meshes nuclear@0: * nuclear@0: * The meshes should have equal vertex formats. Only components nuclear@0: * that are provided by ALL meshes will be present in the output mesh. nuclear@0: * An exception is made for VColors - they are set to black. The nuclear@0: * meshes should have the same material indices, too. The output nuclear@0: * material index is always the material index of the first mesh. nuclear@0: * nuclear@0: * @param dest Destination mesh. Must be empty. nuclear@0: * @param flags Currently no parameters nuclear@0: * @param begin First mesh to be processed nuclear@0: * @param end Points to the mesh after the last mesh to be processed nuclear@0: */ nuclear@0: static void MergeMeshes(aiMesh** dest,unsigned int flags, nuclear@0: std::vector::const_iterator begin, nuclear@0: std::vector::const_iterator end); nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Merges two or more bones nuclear@0: * nuclear@0: * @param out Mesh to receive the output bone list nuclear@0: * @param flags Currently no parameters nuclear@0: * @param begin First mesh to be processed nuclear@0: * @param end Points to the mesh after the last mesh to be processed nuclear@0: */ nuclear@0: static void MergeBones(aiMesh* out,std::vector::const_iterator it, nuclear@0: std::vector::const_iterator end); nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Builds a list of uniquely named bones in a mesh list nuclear@0: * nuclear@0: * @param asBones Receives the output list nuclear@0: * @param it First mesh to be processed nuclear@0: * @param end Last mesh to be processed nuclear@0: */ nuclear@0: static void BuildUniqueBoneList(std::list& asBones, nuclear@0: std::vector::const_iterator it, nuclear@0: std::vector::const_iterator end); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Add a name prefix to all nodes in a scene. nuclear@0: * nuclear@0: * @param Current node. This function is called recursively. nuclear@0: * @param prefix Prefix to be added to all nodes nuclear@0: * @param len STring length nuclear@0: */ nuclear@0: static void AddNodePrefixes(aiNode* node, const char* prefix, nuclear@0: unsigned int len); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Add an offset to all mesh indices in a node graph nuclear@0: * nuclear@0: * @param Current node. This function is called recursively. nuclear@0: * @param offset Offset to be added to all mesh indices nuclear@0: */ nuclear@0: static void OffsetNodeMeshIndices (aiNode* node, unsigned int offset); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Attach a list of node graphs to well-defined nodes in a master nuclear@0: * graph. This is a helper for MergeScenes() nuclear@0: * nuclear@0: * @param master Master scene nuclear@0: * @param srcList List of source scenes along with their attachment nuclear@0: * points. If an attachment point is NULL (or does not exist in nuclear@0: * the master graph), a scene is attached to the root of the master nuclear@0: * graph (as an additional child node) nuclear@0: * @duplicates List of duplicates. If elem[n] == n the scene is not nuclear@0: * a duplicate. Otherwise elem[n] links scene n to its first occurence. nuclear@0: */ nuclear@0: static void AttachToGraph ( aiScene* master, nuclear@0: std::vector& srcList); nuclear@0: nuclear@0: static void AttachToGraph (aiNode* attach, nuclear@0: std::vector& srcList); nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Get a deep copy of a scene nuclear@0: * nuclear@0: * @param dest Receives a pointer to the destination scene nuclear@0: * @param src Source scene - remains unmodified. nuclear@0: */ nuclear@0: static void CopyScene(aiScene** dest,const aiScene* source,bool allocate = true); nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Get a flat copy of a scene nuclear@0: * nuclear@0: * Only the first hierarchy layer is copied. All pointer members of nuclear@0: * aiScene are shared by source and destination scene. If the nuclear@0: * pointer doesn't point to NULL when the function is called, the nuclear@0: * existing scene is cleared and refilled. nuclear@0: * @param dest Receives a pointer to the destination scene nuclear@0: * @param src Source scene - remains unmodified. nuclear@0: */ nuclear@0: static void CopySceneFlat(aiScene** dest,const aiScene* source); nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Get a deep copy of a mesh nuclear@0: * nuclear@0: * @param dest Receives a pointer to the destination mesh nuclear@0: * @param src Source mesh - remains unmodified. nuclear@0: */ nuclear@0: static void Copy (aiMesh** dest, const aiMesh* src); nuclear@0: nuclear@0: // similar to Copy(): nuclear@0: static void Copy (aiMaterial** dest, const aiMaterial* src); nuclear@0: static void Copy (aiTexture** dest, const aiTexture* src); nuclear@0: static void Copy (aiAnimation** dest, const aiAnimation* src); nuclear@0: static void Copy (aiCamera** dest, const aiCamera* src); nuclear@0: static void Copy (aiBone** dest, const aiBone* src); nuclear@0: static void Copy (aiLight** dest, const aiLight* src); nuclear@0: static void Copy (aiNodeAnim** dest, const aiNodeAnim* src); nuclear@0: nuclear@0: // recursive, of course nuclear@0: static void Copy (aiNode** dest, const aiNode* src); nuclear@0: nuclear@0: nuclear@0: private: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Same as AddNodePrefixes, but with an additional check nuclear@0: static void AddNodePrefixesChecked(aiNode* node, const char* prefix, nuclear@0: unsigned int len, nuclear@0: std::vector& input, nuclear@0: unsigned int cur); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Add node identifiers to a hashing set nuclear@0: static void AddNodeHashes(aiNode* node, std::set& hashes); nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Search for duplicate names nuclear@0: static bool FindNameMatch(const aiString& name, nuclear@0: std::vector& input, unsigned int cur); nuclear@0: }; nuclear@0: nuclear@0: } nuclear@0: nuclear@0: #endif // !! AI_SCENE_COMBINER_H_INC