/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "motion/quaternion_channel.h" #include "metafile/nml.h" #include "alloc/ialloc.h" #include "log/log.h" using namespace GS; using NML::Tag; //------------------------------------------------------------------------------ bool QuaternionChannel::FromMetaTag(Tag &tag) { if (tag.name != "QChannel") __ERR__(__LOG_E__ << "Could not parse motion quaternion channel, incorrect root tag (" << tag.name << ").\n", false) Clear(); // Parse root tags. NMLTagForeach(pt, tag) { if (pt->name == "BinaryKeys") { Tag *count_tag = pt->GetTag("Count"), *data_tag = pt->GetTag("Data"); if (count_tag && data_tag) { float *data = (float *)data_tag->GetValue().GetBinaryBuffer(), *p_data = data; if (data) { int count = count_tag->GetInteger(); for (int n = 0; n < count; ++n) { QuaternionKey *key = new QuaternionKey; key->t = Time::fromSec(*p_data++); key->q.x = *p_data++; key->q.y = *p_data++; key->q.z = *p_data++; key->q.w = *p_data++; keys.Add(key); } } } } else if (pt->name == "Keys") { NMLTagForeach(st, *pt) if (st->name == "Key") { const char *p = st->GetString(); if (!p) __LOG_W__ << "Invalid key tag while parsing quaternion channel.\n"; else { //------------------------------------------------------------------------------------------- #define SEEK_CHAR(v) \ p = String::strfindchar(p, (v)); \ if (!p[0]) \ __ERR__(__LOG_W__ << "Mangled keyframe tag while parsing quaternion channel.\n", false) \ p++; \ //------------------------------------------------------------------------------------------- QuaternionKey *key = new QuaternionKey; key->t = Time::fromSec(String::atof(p, NULL, false)); SEEK_CHAR(':'); key->q.x = String::atof(p, NULL, false); SEEK_CHAR(','); key->q.y = String::atof(p, NULL, false); SEEK_CHAR(','); key->q.z = String::atof(p, NULL, false); SEEK_CHAR(','); key->q.w = String::atof(p, NULL, false); keys.Add(key); } } } else __LOG_W__ << "Unknown tag '" << pt->name << "' in .\n"; } return true; } Tag *QuaternionChannel::AsMetaTag() { Tag *root = new Tag("QChannel"); if (!root) __ERR__(__LOG_E__ << "Could not create quaternion channel root tag to serialize.\n", NULL) if (keys.GetCount()) if (Tag *kf_tag = root->AddChild("BinaryKeys")) { kf_tag->AddChild("Count", (int)keys.GetCount()); // Legacy support. float *kf_array = new float[5 * keys.GetCount()], *p_kf = kf_array; for (uint n = 0; n < keys.GetCount(); n++) { *p_kf++ = keys[n]->t.toSec(); *p_kf++ = keys[n]->q.x; *p_kf++ = keys[n]->q.y; *p_kf++ = keys[n]->q.z; *p_kf++ = keys[n]->q.w; } kf_tag->AddChild("Data", (uchar *)kf_array, 5 * 4 * keys.GetCount()); _safe_delete_array(kf_array); } return root; } //------------------------------------------------------------------------------