Files
bullet3/Extras/FCollada/FCDocument/FCDGeometrySource.cpp
2006-05-25 19:18:29 +00:00

148 lines
5.5 KiB
C++

/*
Copyright (C) 2005-2006 Feeling Software Inc.
MIT License: http://www.opensource.org/licenses/mit-license.php
*/
#include "StdAfx.h"
#include "FCDocument/FCDocument.h"
#include "FCDocument/FCDAnimated.h"
#include "FCDocument/FCDGeometrySource.h"
#include "FUtils/FUDaeParser.h"
#include "FUtils/FUDaeWriter.h"
#include "FUtils/FUDaeEnum.h"
using namespace FUDaeParser;
using namespace FUDaeWriter;
FCDGeometrySource::FCDGeometrySource(FCDocument* document) : FCDObjectWithId(document, "GeometrySource")
{
sourceNode = NULL;
sourceStride = 0;
sourceType = FUDaeGeometryInput::UNKNOWN;
}
FCDGeometrySource::~FCDGeometrySource()
{
animatedValues.clear();
}
void FCDGeometrySource::SetSourceData(const FloatList& _sourceData, uint32 _sourceStride, size_t offset, size_t count)
{
// Remove all the data currently held by the source.
sourceData.clear();
sourceStride = _sourceStride;
// Check the given bounds
size_t beg = min(offset, _sourceData.size()), end;
if (count == 0) end = _sourceData.size();
else end = min(count + offset, _sourceData.size());
sourceData.insert(sourceData.begin(), _sourceData.begin() + beg, _sourceData.begin() + end);
}
void FCDGeometrySource::SetSourceType(FUDaeGeometryInput::Semantic type)
{
sourceType = type;
animatedValues.clear();
// Most types should remain un-animated
if (sourceType != FUDaeGeometryInput::POSITION && sourceType != FUDaeGeometryInput::COLOR) return;
// Look for an animation on this source's objects
Int32List animatedIndices;
GetDocument()->FindAnimationChannelsArrayIndices(sourceNode, animatedIndices);
for (Int32List::iterator itA = animatedIndices.begin(); itA != animatedIndices.end(); ++itA)
{
// Check for repeated animated indices
Int32List::iterator itB = animatedIndices.begin();
for (; itB != itA && (*itA) != (*itB); ++itB) {}
if (itB != itA) continue;
FCDAnimated* animated = NULL;
if (sourceType == FUDaeGeometryInput::POSITION)
{
animated = FCDAnimatedPoint3::Create(GetDocument(), sourceNode, (FMVector3*)&(sourceData[(*itA) * sourceStride]), *itA);
}
else
{
animated = FCDAnimatedColor::Create(GetDocument(), sourceNode, (FMVector3*)&(sourceData[(*itA) * sourceStride]), *itA);
}
// Keep track of these animated values
if (animated != NULL) animatedValues.push_back(animated);
}
}
// Clone this data source
FCDGeometrySource* FCDGeometrySource::Clone() const
{
FCDGeometrySource* clone = new FCDGeometrySource(GetDocument());
FCDObjectWithId::Clone(clone);
clone->name = name;
clone->sourceData = sourceData;
clone->sourceNode = sourceNode;
clone->sourceStride = sourceStride;
clone->SetSourceType(sourceType);
return clone;
}
// Read in the <source> node of the COLLADA document
FUStatus FCDGeometrySource::LoadFromXML(xmlNode* _sourceNode)
{
FUStatus status;
sourceNode = _sourceNode;
// Read in the name and id of the source
name = TO_FSTRING(ReadNodeName(sourceNode));
string id = ReadNodeId(sourceNode);
if (id.empty())
{
status.Warning(FS("Geometry source with no 'id' is unusable."), sourceNode->line);
}
SetDaeId(id);
if (!id.empty() && GetDaeId() != id)
{
return status.Fail(FS("Geometry source has duplicate 'id': ") + TO_FSTRING(id), sourceNode->line);
}
// Read in the source data
sourceStride = ReadSource(sourceNode, sourceData);
if (sourceStride == 0)
{
status.Warning(FS("Geometry has source with no data."), sourceNode->line);
}
return status;
}
// Write out the <source> node to the COLLADA xml tree
xmlNode* FCDGeometrySource::WriteToXML(xmlNode* parentNode) const
{
xmlNode* sourceNode = NULL;
// Export the source directly, using the correct parameters and the length factor
switch (sourceType)
{
case FUDaeGeometryInput::POSITION: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, FUDaeAccessor::XYZW, GetDocument()->GetLengthUnitConversion()); break;
case FUDaeGeometryInput::NORMAL: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, FUDaeAccessor::XYZW); break;
case FUDaeGeometryInput::GEOTANGENT: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, FUDaeAccessor::XYZW); break;
case FUDaeGeometryInput::GEOBINORMAL: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, FUDaeAccessor::XYZW); break;
case FUDaeGeometryInput::TEXCOORD: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, FUDaeAccessor::STPQ); break;
case FUDaeGeometryInput::TEXTANGENT: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, FUDaeAccessor::XYZW); break;
case FUDaeGeometryInput::TEXBINORMAL: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, FUDaeAccessor::XYZW); break;
case FUDaeGeometryInput::UV: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, FUDaeAccessor::XYZW); break;
case FUDaeGeometryInput::COLOR: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, FUDaeAccessor::RGBA); break;
case FUDaeGeometryInput::EXTRA: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, NULL); break;
case FUDaeGeometryInput::UNKNOWN: sourceNode = AddSourceFloat(parentNode, GetDaeId(), sourceData, sourceStride, NULL); break;
case FUDaeGeometryInput::VERTEX: // Refuse to export these sources
default: break;
}
if (!name.empty())
{
AddAttribute(sourceNode, DAE_NAME_ATTRIBUTE, name);
}
return sourceNode;
}