diff options
Diffstat (limited to 'src/3rdparty/assimp/code/LWSLoader.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/LWSLoader.cpp | 935 |
1 files changed, 0 insertions, 935 deletions
diff --git a/src/3rdparty/assimp/code/LWSLoader.cpp b/src/3rdparty/assimp/code/LWSLoader.cpp deleted file mode 100644 index 2017cdb9d..000000000 --- a/src/3rdparty/assimp/code/LWSLoader.cpp +++ /dev/null @@ -1,935 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2017, 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. ---------------------------------------------------------------------------- -*/ - -/** @file LWSLoader.cpp - * @brief Implementation of the LWS importer class - */ - - -#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER - -#include "LWSLoader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" - -#include <assimp/SceneCombiner.h> -#include "GenericProperty.h" -#include "SkeletonMeshBuilder.h" -#include "ConvertToLHProcess.h" -#include "Importer.h" -#include <assimp/DefaultLogger.hpp> -#include <assimp/scene.h> -#include <assimp/IOSystem.hpp> -#include <assimp/importerdesc.h> -#include <memory> - -using namespace Assimp; - -static const aiImporterDesc desc = { - "LightWave Scene Importer", - "", - "", - "http://www.newtek.com/lightwave.html=", - aiImporterFlags_SupportTextFlavour, - 0, - 0, - 0, - 0, - "lws mot" -}; - -// ------------------------------------------------------------------------------------------------ -// Recursive parsing of LWS files -void LWS::Element::Parse (const char*& buffer) -{ - for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) { - - // begin of a new element with children - bool sub = false; - if (*buffer == '{') { - ++buffer; - SkipSpaces(&buffer); - sub = true; - } - else if (*buffer == '}') - return; - - children.push_back(Element()); - - // copy data line - read token per token - - const char* cur = buffer; - while (!IsSpaceOrNewLine(*buffer)) ++buffer; - children.back().tokens[0] = std::string(cur,(size_t) (buffer-cur)); - SkipSpaces(&buffer); - - if (children.back().tokens[0] == "Plugin") - { - DefaultLogger::get()->debug("LWS: Skipping over plugin-specific data"); - - // strange stuff inside Plugin/Endplugin blocks. Needn't - // follow LWS syntax, so we skip over it - for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) { - if (!::strncmp(buffer,"EndPlugin",9)) { - //SkipLine(&buffer); - break; - } - } - continue; - } - - cur = buffer; - while (!IsLineEnd(*buffer)) ++buffer; - children.back().tokens[1] = std::string(cur,(size_t) (buffer-cur)); - - // parse more elements recursively - if (sub) - children.back().Parse(buffer); - } -} - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -LWSImporter::LWSImporter() - : configSpeedFlag(), - io(), - first(), - last(), - fps(), - noSkeletonMesh() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -LWSImporter::~LWSImporter() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - if (extension == "lws" || extension == "mot") - return true; - - // if check for extension is not enough, check for the magic tokens LWSC and LWMO - if (!extension.length() || checkSig) { - uint32_t tokens[2]; - tokens[0] = AI_MAKE_MAGIC("LWSC"); - tokens[1] = AI_MAKE_MAGIC("LWMO"); - return CheckMagicToken(pIOHandler,pFile,tokens,2); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Get list of file extensions -const aiImporterDesc* LWSImporter::GetInfo () const -{ - return &desc; -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void LWSImporter::SetupProperties(const Importer* pImp) -{ - // AI_CONFIG_FAVOUR_SPEED - configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0)); - - // AI_CONFIG_IMPORT_LWS_ANIM_START - first = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_START, - 150392 /* magic hack */); - - // AI_CONFIG_IMPORT_LWS_ANIM_END - last = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_END, - 150392 /* magic hack */); - - if (last < first) { - std::swap(last,first); - } - - noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Read an envelope description -void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill ) -{ - if (dad.children.empty()) { - DefaultLogger::get()->error("LWS: Envelope descriptions must not be empty"); - return; - } - - // reserve enough storage - std::list< LWS::Element >::const_iterator it = dad.children.begin();; - fill.keys.reserve(strtoul10(it->tokens[1].c_str())); - - for (++it; it != dad.children.end(); ++it) { - const char* c = (*it).tokens[1].c_str(); - - if ((*it).tokens[0] == "Key") { - fill.keys.push_back(LWO::Key()); - LWO::Key& key = fill.keys.back(); - - float f; - SkipSpaces(&c); - c = fast_atoreal_move<float>(c,key.value); - SkipSpaces(&c); - c = fast_atoreal_move<float>(c,f); - - key.time = f; - - unsigned int span = strtoul10(c,&c), num = 0; - switch (span) { - - case 0: - key.inter = LWO::IT_TCB; - num = 5; - break; - case 1: - case 2: - key.inter = LWO::IT_HERM; - num = 5; - break; - case 3: - key.inter = LWO::IT_LINE; - num = 0; - break; - case 4: - key.inter = LWO::IT_STEP; - num = 0; - break; - case 5: - key.inter = LWO::IT_BEZ2; - num = 4; - break; - default: - DefaultLogger::get()->error("LWS: Unknown span type"); - } - for (unsigned int i = 0; i < num;++i) { - SkipSpaces(&c); - c = fast_atoreal_move<float>(c,key.params[i]); - } - } - else if ((*it).tokens[0] == "Behaviors") { - SkipSpaces(&c); - fill.pre = (LWO::PrePostBehaviour) strtoul10(c,&c); - SkipSpaces(&c); - fill.post = (LWO::PrePostBehaviour) strtoul10(c,&c); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Read animation channels in the old LightWave animation format -void LWSImporter::ReadEnvelope_Old( - std::list< LWS::Element >::const_iterator& it, - const std::list< LWS::Element >::const_iterator& end, - LWS::NodeDesc& nodes, - unsigned int /*version*/) -{ - unsigned int num,sub_num; - if (++it == end)goto unexpected_end; - - num = strtoul10((*it).tokens[0].c_str()); - for (unsigned int i = 0; i < num; ++i) { - - nodes.channels.push_back(LWO::Envelope()); - LWO::Envelope& envl = nodes.channels.back(); - - envl.index = i; - envl.type = (LWO::EnvelopeType)(i+1); - - if (++it == end)goto unexpected_end; - sub_num = strtoul10((*it).tokens[0].c_str()); - - for (unsigned int n = 0; n < sub_num;++n) { - - if (++it == end)goto unexpected_end; - - // parse value and time, skip the rest for the moment. - LWO::Key key; - const char* c = fast_atoreal_move<float>((*it).tokens[0].c_str(),key.value); - SkipSpaces(&c); - float f; - fast_atoreal_move<float>((*it).tokens[0].c_str(),f); - key.time = f; - - envl.keys.push_back(key); - } - } - return; - -unexpected_end: - DefaultLogger::get()->error("LWS: Encountered unexpected end of file while parsing object motion"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup a nice name for a node -void LWSImporter::SetupNodeName(aiNode* nd, LWS::NodeDesc& src) -{ - const unsigned int combined = src.number | ((unsigned int)src.type) << 28u; - - // the name depends on the type. We break LWS's strange naming convention - // and return human-readable, but still machine-parsable and unique, strings. - if (src.type == LWS::NodeDesc::OBJECT) { - - if (src.path.length()) { - std::string::size_type s = src.path.find_last_of("\\/"); - if (s == std::string::npos) - s = 0; - else ++s; - std::string::size_type t = src.path.substr(s).find_last_of("."); - - nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.path.substr(s).substr(0,t).c_str(),combined); - return; - } - } - nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.name,combined); -} - -// ------------------------------------------------------------------------------------------------ -// Recursively build the scenegraph -void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<AttachmentInfo>& attach, - BatchLoader& batch, - aiCamera**& camOut, - aiLight**& lightOut, - std::vector<aiNodeAnim*>& animOut) -{ - // Setup a very cryptic name for the node, we want the user to be happy - SetupNodeName(nd,src); - aiNode* ndAnim = nd; - - // If the node is an object - if (src.type == LWS::NodeDesc::OBJECT) { - - // If the object is from an external file, get it - aiScene* obj = NULL; - if (src.path.length() ) { - obj = batch.GetImport(src.id); - if (!obj) { - DefaultLogger::get()->error("LWS: Failed to read external file " + src.path); - } - else { - if (obj->mRootNode->mNumChildren == 1) { - - //If the pivot is not set for this layer, get it from the external object - if (!src.isPivotSet) { - src.pivotPos.x = +obj->mRootNode->mTransformation.a4; - src.pivotPos.y = +obj->mRootNode->mTransformation.b4; - src.pivotPos.z = -obj->mRootNode->mTransformation.c4; //The sign is the RH to LH back conversion - } - - //Remove first node from obj (the old pivot), reset transform of second node (the mesh node) - aiNode* newRootNode = obj->mRootNode->mChildren[0]; - obj->mRootNode->mChildren[0] = NULL; - delete obj->mRootNode; - - obj->mRootNode = newRootNode; - obj->mRootNode->mTransformation.a4 = 0.0; - obj->mRootNode->mTransformation.b4 = 0.0; - obj->mRootNode->mTransformation.c4 = 0.0; - } - } - } - - //Setup the pivot node (also the animation node), the one we received - nd->mName = std::string("Pivot:") + nd->mName.data; - ndAnim = nd; - - //Add the attachment node to it - nd->mNumChildren = 1; - nd->mChildren = new aiNode*[1]; - nd->mChildren[0] = new aiNode(); - nd->mChildren[0]->mParent = nd; - nd->mChildren[0]->mTransformation.a4 = -src.pivotPos.x; - nd->mChildren[0]->mTransformation.b4 = -src.pivotPos.y; - nd->mChildren[0]->mTransformation.c4 = -src.pivotPos.z; - SetupNodeName(nd->mChildren[0], src); - - //Update the attachment node - nd = nd->mChildren[0]; - - //Push attachment, if the object came from an external file - if (obj) { - attach.push_back(AttachmentInfo(obj,nd)); - } - } - - // If object is a light source - setup a corresponding ai structure - else if (src.type == LWS::NodeDesc::LIGHT) { - aiLight* lit = *lightOut++ = new aiLight(); - - // compute final light color - lit->mColorDiffuse = lit->mColorSpecular = src.lightColor*src.lightIntensity; - - // name to attach light to node -> unique due to LWs indexing system - lit->mName = nd->mName; - - // detemine light type and setup additional members - if (src.lightType == 2) { /* spot light */ - - lit->mType = aiLightSource_SPOT; - lit->mAngleInnerCone = (float)AI_DEG_TO_RAD( src.lightConeAngle ); - lit->mAngleOuterCone = lit->mAngleInnerCone+(float)AI_DEG_TO_RAD( src.lightEdgeAngle ); - - } - else if (src.lightType == 1) { /* directional light source */ - lit->mType = aiLightSource_DIRECTIONAL; - } - else lit->mType = aiLightSource_POINT; - - // fixme: no proper handling of light falloffs yet - if (src.lightFalloffType == 1) - lit->mAttenuationConstant = 1.f; - else if (src.lightFalloffType == 1) - lit->mAttenuationLinear = 1.f; - else - lit->mAttenuationQuadratic = 1.f; - } - - // If object is a camera - setup a corresponding ai structure - else if (src.type == LWS::NodeDesc::CAMERA) { - aiCamera* cam = *camOut++ = new aiCamera(); - - // name to attach cam to node -> unique due to LWs indexing system - cam->mName = nd->mName; - } - - // Get the node transformation from the LWO key - LWO::AnimResolver resolver(src.channels,fps); - resolver.ExtractBindPose(ndAnim->mTransformation); - - // .. and construct animation channels - aiNodeAnim* anim = NULL; - - if (first != last) { - resolver.SetAnimationRange(first,last); - resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO); - if (anim) { - anim->mNodeName = ndAnim->mName; - animOut.push_back(anim); - } - } - - // Add children - if (!src.children.empty()) { - nd->mChildren = new aiNode*[src.children.size()]; - for (std::list<LWS::NodeDesc*>::iterator it = src.children.begin(); it != src.children.end(); ++it) { - aiNode* ndd = nd->mChildren[nd->mNumChildren++] = new aiNode(); - ndd->mParent = nd; - - BuildGraph(ndd,**it,attach,batch,camOut,lightOut,animOut); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Determine the exact location of a LWO file -std::string LWSImporter::FindLWOFile(const std::string& in) -{ - // insert missing directory separator if necessary - std::string tmp; - if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/') - { - tmp = in[0] + (std::string(":\\") + in.substr(2)); - } - else tmp = in; - - if (io->Exists(tmp)) { - return in; - } - - // file is not accessible for us ... maybe it's packed by - // LightWave's 'Package Scene' command? - - // Relevant for us are the following two directories: - // <folder>\Objects\<hh>\<*>.lwo - // <folder>\Scenes\<hh>\<*>.lws - // where <hh> is optional. - - std::string test = std::string("..") + (io->getOsSeparator() + tmp); - if (io->Exists(test)) { - return test; - } - - test = std::string("..") + (io->getOsSeparator() + test); - if (io->Exists(test)) { - return test; - } - - - // return original path, maybe the IOsystem knows better - return tmp; -} - -// ------------------------------------------------------------------------------------------------ -// Read file into given scene data structure -void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler) -{ - io = pIOHandler; - std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open LWS file " + pFile + "."); - } - - // Allocate storage and copy the contents of the file to a memory buffer - std::vector< char > mBuffer; - TextFileToBuffer(file.get(),mBuffer); - - // Parse the file structure - LWS::Element root; const char* dummy = &mBuffer[0]; - root.Parse(dummy); - - // Construct a Batchimporter to read more files recursively - BatchLoader batch(pIOHandler); -// batch.SetBasePath(pFile); - - // Construct an array to receive the flat output graph - std::list<LWS::NodeDesc> nodes; - - unsigned int cur_light = 0, cur_camera = 0, cur_object = 0; - unsigned int num_light = 0, num_camera = 0, num_object = 0; - - // check magic identifier, 'LWSC' - bool motion_file = false; - std::list< LWS::Element >::const_iterator it = root.children.begin(); - - if ((*it).tokens[0] == "LWMO") - motion_file = true; - - if ((*it).tokens[0] != "LWSC" && !motion_file) - throw DeadlyImportError("LWS: Not a LightWave scene, magic tag LWSC not found"); - - // get file format version and print to log - ++it; - unsigned int version = strtoul10((*it).tokens[0].c_str()); - DefaultLogger::get()->info("LWS file format version is " + (*it).tokens[0]); - first = 0.; - last = 60.; - fps = 25.; /* seems to be a good default frame rate */ - - // Now read all elements in a very straghtforward manner - for (; it != root.children.end(); ++it) { - const char* c = (*it).tokens[1].c_str(); - - // 'FirstFrame': begin of animation slice - if ((*it).tokens[0] == "FirstFrame") { - if (150392. != first /* see SetupProperties() */) - first = strtoul10(c,&c)-1.; /* we're zero-based */ - } - - // 'LastFrame': end of animation slice - else if ((*it).tokens[0] == "LastFrame") { - if (150392. != last /* see SetupProperties() */) - last = strtoul10(c,&c)-1.; /* we're zero-based */ - } - - // 'FramesPerSecond': frames per second - else if ((*it).tokens[0] == "FramesPerSecond") { - fps = strtoul10(c,&c); - } - - // 'LoadObjectLayer': load a layer of a specific LWO file - else if ((*it).tokens[0] == "LoadObjectLayer") { - - // get layer index - const int layer = strtoul10(c,&c); - - // setup the layer to be loaded - BatchLoader::PropertyMap props; - SetGenericProperty(props.ints,AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,layer); - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::OBJECT; - if (version >= 4) { // handle LWSC 4 explicit ID - SkipSpaces(&c); - d.number = strtoul16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_object++; - - // and add the file to the import list - SkipSpaces(&c); - std::string path = FindLWOFile( c ); - d.path = path; - d.id = batch.AddLoadRequest(path,0,&props); - - nodes.push_back(d); - num_object++; - } - // 'LoadObject': load a LWO file into the scenegraph - else if ((*it).tokens[0] == "LoadObject") { - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::OBJECT; - - if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtoul16(c,&c) & AI_LWS_MASK; - SkipSpaces(&c); - } - else d.number = cur_object++; - std::string path = FindLWOFile( c ); - d.id = batch.AddLoadRequest(path,0,NULL); - - d.path = path; - nodes.push_back(d); - num_object++; - } - // 'AddNullObject': add a dummy node to the hierarchy - else if ((*it).tokens[0] == "AddNullObject") { - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::OBJECT; - if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtoul16(c,&c) & AI_LWS_MASK; - SkipSpaces(&c); - } - else d.number = cur_object++; - d.name = c; - nodes.push_back(d); - - num_object++; - } - // 'NumChannels': Number of envelope channels assigned to last layer - else if ((*it).tokens[0] == "NumChannels") { - // ignore for now - } - // 'Channel': preceedes any envelope description - else if ((*it).tokens[0] == "Channel") { - if (nodes.empty()) { - if (motion_file) { - - // LightWave motion file. Add dummy node - LWS::NodeDesc d; - d.type = LWS::NodeDesc::OBJECT; - d.name = c; - d.number = cur_object++; - nodes.push_back(d); - } - else DefaultLogger::get()->error("LWS: Unexpected keyword: \'Channel\'"); - } - - // important: index of channel - nodes.back().channels.push_back(LWO::Envelope()); - LWO::Envelope& env = nodes.back().channels.back(); - - env.index = strtoul10(c); - - // currently we can just interpret the standard channels 0...9 - // (hack) assume that index-i yields the binary channel type from LWO - env.type = (LWO::EnvelopeType)(env.index+1); - - } - // 'Envelope': a single animation channel - else if ((*it).tokens[0] == "Envelope") { - if (nodes.empty() || nodes.back().channels.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'Envelope\'"); - else { - ReadEnvelope((*it),nodes.back().channels.back()); - } - } - // 'ObjectMotion': animation information for older lightwave formats - else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" || - (*it).tokens[0] == "CameraMotion" || - (*it).tokens[0] == "LightMotion")) { - - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'<Light|Object|Camera>Motion\'"); - else { - ReadEnvelope_Old(it,root.children.end(),nodes.back(),version); - } - } - // 'Pre/PostBehavior': pre/post animation behaviour for LWSC 2 - else if (version == 2 && (*it).tokens[0] == "Pre/PostBehavior") { - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'Pre/PostBehavior'"); - else { - for (std::list<LWO::Envelope>::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) { - // two ints per envelope - LWO::Envelope& env = *it; - env.pre = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c); - env.post = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c); - } - } - } - // 'ParentItem': specifies the parent of the current element - else if ((*it).tokens[0] == "ParentItem") { - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentItem\'"); - - else nodes.back().parent = strtoul16(c,&c); - } - // 'ParentObject': deprecated one for older formats - else if (version < 3 && (*it).tokens[0] == "ParentObject") { - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentObject\'"); - - else { - nodes.back().parent = strtoul10(c,&c) | (1u << 28u); - } - } - // 'AddCamera': add a camera to the scenegraph - else if ((*it).tokens[0] == "AddCamera") { - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::CAMERA; - - if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtoul16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_camera++; - nodes.push_back(d); - - num_camera++; - } - // 'CameraName': set name of currently active camera - else if ((*it).tokens[0] == "CameraName") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'CameraName\'"); - - else nodes.back().name = c; - } - // 'AddLight': add a light to the scenegraph - else if ((*it).tokens[0] == "AddLight") { - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::LIGHT; - - if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtoul16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_light++; - nodes.push_back(d); - - num_light++; - } - // 'LightName': set name of currently active light - else if ((*it).tokens[0] == "LightName") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightName\'"); - - else nodes.back().name = c; - } - // 'LightIntensity': set intensity of currently active light - else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity" ) { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightIntensity\'"); - - else fast_atoreal_move<float>(c, nodes.back().lightIntensity ); - - } - // 'LightType': set type of currently active light - else if ((*it).tokens[0] == "LightType") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightType\'"); - - else nodes.back().lightType = strtoul10(c); - - } - // 'LightFalloffType': set falloff type of currently active light - else if ((*it).tokens[0] == "LightFalloffType") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightFalloffType\'"); - - else nodes.back().lightFalloffType = strtoul10(c); - - } - // 'LightConeAngle': set cone angle of currently active light - else if ((*it).tokens[0] == "LightConeAngle") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightConeAngle\'"); - - else nodes.back().lightConeAngle = fast_atof(c); - - } - // 'LightEdgeAngle': set area where we're smoothing from min to max intensity - else if ((*it).tokens[0] == "LightEdgeAngle") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightEdgeAngle\'"); - - else nodes.back().lightEdgeAngle = fast_atof(c); - - } - // 'LightColor': set color of currently active light - else if ((*it).tokens[0] == "LightColor") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightColor\'"); - - else { - c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.r ); - SkipSpaces(&c); - c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.g ); - SkipSpaces(&c); - c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.b ); - } - } - - // 'PivotPosition': position of local transformation origin - else if ((*it).tokens[0] == "PivotPosition" || (*it).tokens[0] == "PivotPoint") { - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'PivotPosition\'"); - else { - c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.x ); - SkipSpaces(&c); - c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.y ); - SkipSpaces(&c); - c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.z ); - // Mark pivotPos as set - nodes.back().isPivotSet = true; - } - } - } - - // resolve parenting - for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) { - - // check whether there is another node which calls us a parent - for (std::list<LWS::NodeDesc>::iterator dit = nodes.begin(); dit != nodes.end(); ++dit) { - if (dit != it && *it == (*dit).parent) { - if ((*dit).parent_resolved) { - // fixme: it's still possible to produce an overflow due to cross references .. - DefaultLogger::get()->error("LWS: Found cross reference in scenegraph"); - continue; - } - - (*it).children.push_back(&*dit); - (*dit).parent_resolved = &*it; - } - } - } - - // find out how many nodes have no parent yet - unsigned int no_parent = 0; - for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) { - if (!(*it).parent_resolved) - ++ no_parent; - } - if (!no_parent) - throw DeadlyImportError("LWS: Unable to find scene root node"); - - - // Load all subsequent files - batch.LoadAll(); - - // and build the final output graph by attaching the loaded external - // files to ourselves. first build a master graph - aiScene* master = new aiScene(); - aiNode* nd = master->mRootNode = new aiNode(); - - // allocate storage for cameras&lights - if (num_camera) { - master->mCameras = new aiCamera*[master->mNumCameras = num_camera]; - } - aiCamera** cams = master->mCameras; - if (num_light) { - master->mLights = new aiLight*[master->mNumLights = num_light]; - } - aiLight** lights = master->mLights; - - std::vector<AttachmentInfo> attach; - std::vector<aiNodeAnim*> anims; - - nd->mName.Set("<LWSRoot>"); - nd->mChildren = new aiNode*[no_parent]; - for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) { - if (!(*it).parent_resolved) { - aiNode* ro = nd->mChildren[ nd->mNumChildren++ ] = new aiNode(); - ro->mParent = nd; - - // ... and build the scene graph. If we encounter object nodes, - // add then to our attachment table. - BuildGraph(ro,*it, attach, batch, cams, lights, anims); - } - } - - // create a master animation channel for us - if (anims.size()) { - master->mAnimations = new aiAnimation*[master->mNumAnimations = 1]; - aiAnimation* anim = master->mAnimations[0] = new aiAnimation(); - anim->mName.Set("LWSMasterAnim"); - - // LWS uses seconds as time units, but we convert to frames - anim->mTicksPerSecond = fps; - anim->mDuration = last-(first-1); /* fixme ... zero or one-based?*/ - - anim->mChannels = new aiNodeAnim*[anim->mNumChannels = static_cast<unsigned int>(anims.size())]; - std::copy(anims.begin(),anims.end(),anim->mChannels); - } - - // convert the master scene to RH - MakeLeftHandedProcess monster_cheat; - monster_cheat.Execute(master); - - // .. ccw - FlipWindingOrderProcess flipper; - flipper.Execute(master); - - // OK ... finally build the output graph - SceneCombiner::MergeScenes(&pScene,master,attach, - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? ( - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0)); - - // Check flags - if (!pScene->mNumMeshes || !pScene->mNumMaterials) { - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - - if (pScene->mNumAnimations && !noSkeletonMesh) { - // construct skeleton mesh - SkeletonMeshBuilder builder(pScene); - } - } - -} - -#endif // !! ASSIMP_BUILD_NO_LWS_IMPORTER |