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

195 lines
5.6 KiB
C++

/*
Copyright (C) 2005-2006 Feeling Software Inc.
MIT License: http://www.opensource.org/licenses/mit-license.php
*/
#include "StdAfx.h"
#include "FCDocument/FCDEffectTechnique.h"
#include "FCDocument/FCDocument.h"
#include "FCDocument/FCDEffectPass.h"
#include "FCDocument/FCDEffectPassShader.h"
#include "FCDocument/FCDEffectParameter.h"
#include "FCDocument/FCDEffectParameterList.h"
#include "FUtils/FUDaeParser.h"
#include "FUtils/FUDaeWriter.h"
using namespace FUDaeParser;
using namespace FUDaeWriter;
FCDEffectPass::FCDEffectPass(FCDocument* document, FCDEffectTechnique *_parent) : FCDObject(document, "FCDEffectPass")
{
parent = _parent;
}
FCDEffectPass::~FCDEffectPass()
{
CLEAR_POINTER_VECTOR(shaders);
meshdata.clear();
parent = NULL;
}
// Adds a new shader to the pass.
FCDEffectPassShader* FCDEffectPass::AddShader()
{
FCDEffectPassShader* shader = new FCDEffectPassShader(GetDocument(), this);
shaders.push_back(shader);
return shader;
}
// Releases a shader contained within the pass.
void FCDEffectPass::ReleaseShader(FCDEffectPassShader* shader)
{
FCDEffectPassShaderList::iterator it = std::find(shaders.begin(), shaders.end(), shader);
if (it != shaders.end())
{
delete *it;
shaders.push_back(shader);
}
}
// Adds a new vertex shader to the pass.
// If a vertex shader already exists within the pass, it will be released.
FCDEffectPassShader* FCDEffectPass::AddVertexShader()
{
FCDEffectPassShader* vertexShader;
for (vertexShader = GetVertexShader(); vertexShader != NULL; vertexShader = GetVertexShader())
{
ReleaseShader(vertexShader);
}
vertexShader = AddShader();
vertexShader->AffectsVertices();
return vertexShader;
}
// Adds a new fragment shader to the pass.
// If a fragment shader already exists within the pass, it will be released.
FCDEffectPassShader* FCDEffectPass::AddFragmentShader()
{
FCDEffectPassShader* fragmentShader;
for (fragmentShader = GetFragmentShader(); fragmentShader != NULL; fragmentShader = GetFragmentShader())
{
ReleaseShader(fragmentShader);
}
fragmentShader = AddShader();
fragmentShader->AffectsFragments();
return fragmentShader;
}
FCDEffectPass* FCDEffectPass::Clone(FCDEffectTechnique* newParent) const
{
FCDEffectPass* clone = new FCDEffectPass(GetDocument(), newParent);
clone->name = name;
clone->meshdata = meshdata;
// Clone the shaderss
clone->shaders.reserve(shaders.size());
for (FCDEffectPassShaderList::const_iterator itS = shaders.begin(); itS != shaders.end(); ++itS)
{
clone->shaders.push_back((*itS)->Clone(clone));
}
return clone;
}
const string& FCDEffectPass::GetDaeId() const
{
return parent->GetDaeId();
}
// Retrieve the type-specific shaders
FCDEffectPassShader* FCDEffectPass::GetVertexShader()
{
for (FCDEffectPassShaderList::iterator itS = shaders.begin(); itS != shaders.end(); ++itS)
{
if ((*itS)->IsVertexShader()) return (*itS);
}
return NULL;
}
const FCDEffectPassShader* FCDEffectPass::GetVertexShader() const
{
for (FCDEffectPassShaderList::const_iterator itS = shaders.begin(); itS != shaders.end(); ++itS)
{
if ((*itS)->IsVertexShader()) return (*itS);
}
return NULL;
}
FCDEffectPassShader* FCDEffectPass::GetFragmentShader()
{
for (FCDEffectPassShaderList::iterator itS = shaders.begin(); itS != shaders.end(); ++itS)
{
if ((*itS)->IsFragmentShader()) return (*itS);
}
return NULL;
}
const FCDEffectPassShader* FCDEffectPass::GetFragmentShader() const
{
for (FCDEffectPassShaderList::const_iterator itS = shaders.begin(); itS != shaders.end(); ++itS)
{
if ((*itS)->IsFragmentShader()) return (*itS);
}
return NULL;
}
FUStatus FCDEffectPass::LoadFromXML(xmlNode* passNode, xmlNode* techniqueNode, xmlNode* profileNode)
{
FUStatus status;
if (!IsEquivalent(passNode->name, DAE_PASS_ELEMENT))
{
return status.Warning(FS("Pass contains unknown element."), passNode->line);
}
name = TO_FSTRING(ReadNodeProperty(passNode, DAE_SID_ATTRIBUTE));
// parse mesh data
const char* smdnames[10] = { "COLOR0", "COLOR1", "TEXCOORD0", "TEXCOORD1", "TEXCOORD2", "TEXCOORD3", "TEXCOORD4", "TEXCOORD5", "TEXCOORD6", "TEXCOORD7" };
for(uint32 i = 0; i < 10; ++i)
{
string smdname = smdnames[i];
string smdata = "";
xmlNode *mdataNode = FindChildByProperty(profileNode, "sid", smdname.c_str() );
if(mdataNode == NULL)
mdataNode = FindChildByProperty(techniqueNode, "sid", smdname.c_str() );
if( mdataNode != NULL )
{
xmlNode *stringNode = FindChildByType(mdataNode, "string" );
smdata = ReadNodeContentDirect(stringNode);
}
meshdata.push_back(smdata);
}
// Look for the <shader> elements
xmlNodeList shaderNodes;
FindChildrenByType(passNode, DAE_SHADER_ELEMENT, shaderNodes);
for (xmlNodeList::iterator itS = shaderNodes.begin(); itS != shaderNodes.end(); ++itS)
{
FCDEffectPassShader* shader = new FCDEffectPassShader(GetDocument(), this);
shaders.push_back(shader);
status.AppendStatus(shader->LoadFromXML(*itS));
}
return status;
}
// Write out the pass to the COLLADA xml node tree
xmlNode* FCDEffectPass::WriteToXML(xmlNode* parentNode) const
{
// Write out the <pass> element, with the shader's name
xmlNode* passNode = AddChild(parentNode, DAE_PASS_ELEMENT);
if (!name.empty())
{
const_cast<FCDEffectPass*>(this)->name = TO_FSTRING(AddNodeSid(passNode, TO_STRING(name).c_str()));
}
// Write out the shaders
for (FCDEffectPassShaderList::const_iterator itS = shaders.begin(); itS != shaders.end(); ++itS)
{
(*itS)->WriteToXML(passNode);
}
return passNode;
}