Files
Webcam/include/engine/motion/quaternion_channel_nml.cpp

122 lines
3.3 KiB
C++

/* -----------------------------------------------------------------------------
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 <QChannel>.\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;
}
//------------------------------------------------------------------------------