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

164 lines
5.2 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/FCDGeometry.h"
#include "FCDocument/FCDGeometrySource.h"
#include "FCDocument/FCDGeometrySpline.h"
#include "FUtils/FUStringConversion.h"
#include "FUtils/FUDaeParser.h"
#include "FUtils/FUDaeWriter.h"
using namespace FUDaeParser;
using namespace FUDaeWriter;
FCDGeometrySpline::FCDGeometrySpline(FCDocument* document, FCDGeometry* _parent) : FCDObject(document, "FCDGeometrySpline")
{
parent = _parent;
isClosed = false;
}
FCDGeometrySpline::~FCDGeometrySpline()
{
parent = NULL;
cvs.clear();
knots.clear();
}
// Read in the <spline> node of the COLLADA document
FUStatus FCDGeometrySpline::LoadFromXML(xmlNode* splineNode)
{
FUStatus status;
// Read the curve properties
isClosed = FUStringConversion::ToBoolean(ReadNodeProperty(splineNode, DAE_CLOSED_ATTRIBUTE));
// Read in the <control_vertices> element, which define the base type for this curve
xmlNode* cvsNode = FindChildByType(splineNode, DAE_CONTROL_VERTICES_ELEMENT);
if (cvsNode == NULL)
{
return status.Fail(FS("No <control_vertices> element in spline: ") + TO_FSTRING(parent->GetDaeId()), splineNode->line);
}
// Read in the per-vertex inputs
string positionSrc;
string sknots;
int hasPositions = 0;
int hasKnots = 0;
xmlNodeList vertexInputNodes;
FindChildrenByType(cvsNode, DAE_INPUT_ELEMENT, vertexInputNodes);
for (xmlNodeList::iterator it = vertexInputNodes.begin(); it < vertexInputNodes.end(); ++it)
{
xmlNode* vertexInputNode = *it;
string inputSemantic = ReadNodeSemantic(vertexInputNode);
if( strcmp(inputSemantic.c_str(), "POSITION" ) == 0 )
{
positionSrc = ReadNodeProperty(vertexInputNode,"source");
hasPositions = 1;
}
else if( strcmp(inputSemantic.c_str(), "KNOTSEQUENCES" ) == 0 )
{
sknots = ReadNodeProperty(vertexInputNode,"source");
hasKnots = 1;
}
}
if (!hasPositions)
{
return status.Warning(FS("No vertex position input node in spline: ") + TO_FSTRING(parent->GetDaeId()), splineNode->line);
}
if (!hasKnots)
{
return status.Warning(FS("No knot sequence input node in spline: ") + TO_FSTRING(parent->GetDaeId()), splineNode->line);
}
xmlNode* positionSrcNode = NULL;
xmlNode* knotSrcNode = NULL;
// Read in the data sources
xmlNodeList sourceDataNodes;
FindChildrenByType(splineNode, DAE_SOURCE_ELEMENT, sourceDataNodes);
for (xmlNodeList::iterator it = sourceDataNodes.begin(); it != sourceDataNodes.end(); ++it)
{
xmlNode* sourceNode = *it;
string srcid = ReadNodeProperty(*it,"id");
if( strcmp( srcid.c_str(), positionSrc.substr(1).c_str() ) == 0 )
positionSrcNode = sourceNode;
else if( strcmp( srcid.c_str(), sknots.substr(1).c_str() ) == 0 )
knotSrcNode = sourceNode;
}
if (positionSrcNode == NULL)
{
return status.Warning(FS("No vertex position source element in spline: ") + TO_FSTRING(parent->GetDaeId()), splineNode->line);
}
xmlNode* farrayNode = FindChildByType(positionSrcNode, "float_array");
if (farrayNode == NULL)
{
return status.Warning(FS("No vertex position float array element in spline: ") + TO_FSTRING(parent->GetDaeId()), positionSrcNode->line);
}
// Setup the curve data
const char* content = ReadNodeContentDirect(farrayNode);
int32 icount = ReadNodeCount(farrayNode);
for(int32 i = 0; i < icount / 3; ++i)
{
FMVector3 p = FUStringConversion::ToPoint(&content);
cvs.push_back(p);
}
farrayNode = FindChildByType(knotSrcNode, "float_array");
if(farrayNode==NULL)
{
return status.Warning(FS("No knot sequence float array element in spline: ") + TO_FSTRING(parent->GetDaeId()), farrayNode->line);
}
content = ReadNodeContentDirect(farrayNode);
icount = atoi(ReadNodeProperty( farrayNode, "count").c_str());
// setup the curve data
for( int i=0; i< icount; i++ )
{
float f = FUStringConversion::ToFloat(&content);
knots.push_back(double(f));
}
return status;
}
// Write out the <spline> node to the COLLADA xml tree
xmlNode* FCDGeometrySpline::WriteToXML(xmlNode* parentNode) const
{
xmlNode* splineNode = AddChild(parentNode, DAE_SPLINE_ELEMENT);
AddAttribute(splineNode, DAE_CLOSED_ATTRIBUTE, isClosed);
// Export the control point source
FUSStringBuilder controlPointSourceId(GetParent()->GetDaeId()); controlPointSourceId += "-cvs";
AddSourcePosition(splineNode, controlPointSourceId.ToCharPtr(), cvs);
// Export the knots
FUSStringBuilder knotSourceId(GetParent()->GetDaeId());
knotSourceId += "-knots";
FloatList floatKnots; floatKnots.reserve(knots.size());
for (FCDKnots::const_iterator itK = knots.begin(); itK != knots.end(); ++itK)
{
floatKnots.push_back(float(*itK));
}
AddSourceFloat(splineNode, knotSourceId.ToCharPtr(), floatKnots, "KNOT");
// Write out the control vertices information
xmlNode* verticesNode = AddChild(splineNode, DAE_CONTROL_VERTICES_ELEMENT);
AddInput(verticesNode, controlPointSourceId.ToCharPtr(), DAE_POSITION_SPLINE_INPUT);
AddInput(verticesNode, knotSourceId.ToCharPtr(), DAE_KNOT_SPLINE_INPUT);
return splineNode;
}